Skip to content
This repository was archived by the owner on Feb 25, 2026. It is now read-only.

Commit 48c8c7e

Browse files
Merge branch 'Kilo-Org:dev' into dev
2 parents 943f280 + 6e48aab commit 48c8c7e

46 files changed

Lines changed: 1003 additions & 159 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

install

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ else
132132
needs_baseline=false
133133
if [ "$arch" = "x64" ]; then
134134
if [ "$os" = "linux" ]; then
135-
if ! grep -qi avx2 /proc/cpuinfo 2>/dev/null; then
135+
if ! grep -qwi avx2 /proc/cpuinfo 2>/dev/null; then
136136
needs_baseline=true
137137
fi
138138
fi
@@ -143,6 +143,20 @@ else
143143
needs_baseline=true
144144
fi
145145
fi
146+
147+
if [ "$os" = "windows" ]; then
148+
ps="(Add-Type -MemberDefinition \"[DllImport(\"\"kernel32.dll\"\")] public static extern bool IsProcessorFeaturePresent(int ProcessorFeature);\" -Name Kernel32 -Namespace Win32 -PassThru)::IsProcessorFeaturePresent(40)"
149+
out=""
150+
if command -v powershell.exe >/dev/null 2>&1; then
151+
out=$(powershell.exe -NoProfile -NonInteractive -Command "$ps" 2>/dev/null || true)
152+
elif command -v pwsh >/dev/null 2>&1; then
153+
out=$(pwsh -NoProfile -NonInteractive -Command "$ps" 2>/dev/null || true)
154+
fi
155+
out=$(echo "$out" | tr -d '\r' | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]')
156+
if [ "$out" != "true" ] && [ "$out" != "1" ]; then
157+
needs_baseline=true
158+
fi
159+
fi
146160
fi
147161

148162
target="$os-$arch"

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"description": "AI-powered development tool",
55
"private": true,
66
"type": "module",
7-
"packageManager": "bun@1.3.5",
7+
"packageManager": "bun@1.3.9",
88
"scripts": {
99
"dev": "bun run --cwd packages/opencode --conditions=browser src/index.ts",
1010
"dev:desktop": "bun --cwd packages/desktop tauri dev",

packages/app/e2e/selectors.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,11 @@ export const settingsNotificationsAgentSelector = '[data-action="settings-notifi
1010
export const settingsNotificationsPermissionsSelector = '[data-action="settings-notifications-permissions"]'
1111
export const settingsNotificationsErrorsSelector = '[data-action="settings-notifications-errors"]'
1212
export const settingsSoundsAgentSelector = '[data-action="settings-sounds-agent"]'
13+
export const settingsSoundsAgentEnabledSelector = '[data-action="settings-sounds-agent-enabled"]'
1314
export const settingsSoundsPermissionsSelector = '[data-action="settings-sounds-permissions"]'
15+
export const settingsSoundsPermissionsEnabledSelector = '[data-action="settings-sounds-permissions-enabled"]'
1416
export const settingsSoundsErrorsSelector = '[data-action="settings-sounds-errors"]'
17+
export const settingsSoundsErrorsEnabledSelector = '[data-action="settings-sounds-errors-enabled"]'
1518
export const settingsUpdatesStartupSelector = '[data-action="settings-updates-startup"]'
1619
export const settingsReleaseNotesSelector = '[data-action="settings-release-notes"]'
1720

packages/app/e2e/settings/settings.spec.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
settingsNotificationsPermissionsSelector,
1010
settingsReleaseNotesSelector,
1111
settingsSoundsAgentSelector,
12+
settingsSoundsAgentEnabledSelector,
1213
settingsSoundsErrorsSelector,
1314
settingsSoundsPermissionsSelector,
1415
settingsThemeSelector,
@@ -335,6 +336,30 @@ test("changing sound agent selection persists in localStorage", async ({ page, g
335336
expect(stored?.sounds?.agent).not.toBe("staplebops-01")
336337
})
337338

339+
test("disabling agent sound disables sound selection", async ({ page, gotoSession }) => {
340+
await gotoSession()
341+
342+
const dialog = await openSettings(page)
343+
const select = dialog.locator(settingsSoundsAgentSelector)
344+
const switchContainer = dialog.locator(settingsSoundsAgentEnabledSelector)
345+
const trigger = select.locator('[data-slot="select-select-trigger"]')
346+
await expect(select).toBeVisible()
347+
await expect(switchContainer).toBeVisible()
348+
await expect(trigger).toBeEnabled()
349+
350+
await switchContainer.locator('[data-slot="switch-control"]').click()
351+
await page.waitForTimeout(100)
352+
353+
await expect(trigger).toBeDisabled()
354+
355+
const stored = await page.evaluate((key) => {
356+
const raw = localStorage.getItem(key)
357+
return raw ? JSON.parse(raw) : null
358+
}, settingsKey)
359+
360+
expect(stored?.sounds?.agentEnabled).toBe(false)
361+
})
362+
338363
test("changing permissions and errors sounds updates localStorage", async ({ page, gotoSession }) => {
339364
await gotoSession()
340365

packages/app/src/components/dialog-connect-provider.tsx

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,24 @@ export function DialogConnectProvider(props: { provider: string }) {
103103
return value.label ?? ""
104104
}
105105

106+
function formatError(value: unknown, fallback: string): string {
107+
if (value && typeof value === "object" && "data" in value) {
108+
const data = (value as { data?: { message?: unknown } }).data
109+
if (typeof data?.message === "string" && data.message) return data.message
110+
}
111+
if (value && typeof value === "object" && "error" in value) {
112+
const nested = formatError((value as { error?: unknown }).error, "")
113+
if (nested) return nested
114+
}
115+
if (value && typeof value === "object" && "message" in value) {
116+
const message = (value as { message?: unknown }).message
117+
if (typeof message === "string" && message) return message
118+
}
119+
if (value instanceof Error && value.message) return value.message
120+
if (typeof value === "string" && value) return value
121+
return fallback
122+
}
123+
106124
async function selectMethod(index: number) {
107125
if (timer.current !== undefined) {
108126
clearTimeout(timer.current)
@@ -141,7 +159,7 @@ export function DialogConnectProvider(props: { provider: string }) {
141159
})
142160
.catch((e) => {
143161
if (!alive.value) return
144-
dispatch({ type: "auth.error", error: String(e) })
162+
dispatch({ type: "auth.error", error: formatError(e, language.t("common.requestFailed")) })
145163
})
146164
}
147165
}
@@ -330,8 +348,7 @@ export function DialogConnectProvider(props: { provider: string }) {
330348
await complete()
331349
return
332350
}
333-
const message = result.error instanceof Error ? result.error.message : String(result.error)
334-
setFormStore("error", message || language.t("provider.connect.oauth.code.invalid"))
351+
setFormStore("error", formatError(result.error, language.t("provider.connect.oauth.code.invalid")))
335352
}
336353

337354
return (
@@ -387,7 +404,7 @@ export function DialogConnectProvider(props: { provider: string }) {
387404
if (!alive.value) return
388405

389406
if (!result.ok) {
390-
const message = result.error instanceof Error ? result.error.message : String(result.error)
407+
const message = formatError(result.error, language.t("common.requestFailed"))
391408
dispatch({ type: "auth.error", error: message })
392409
return
393410
}

packages/app/src/components/dialog-select-file.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -347,9 +347,9 @@ export function DialogSelectFile(props: { mode?: DialogSelectFileMode; onOpenFil
347347
tabs().open(value)
348348
file.load(path)
349349
if (!view().reviewPanel.opened()) view().reviewPanel.open()
350-
layout.fileTree.open()
351350
layout.fileTree.setTab("all")
352351
props.onOpenFile?.(path)
352+
tabs().setActive(value)
353353
}
354354

355355
const handleSelect = (item: Entry | undefined) => {

packages/app/src/components/prompt-input.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,14 +158,13 @@ export const PromptInput: Component<PromptInputProps> = (props) => {
158158
const wantsReview = item.commentOrigin === "review" || (item.commentOrigin !== "file" && commentInReview(item.path))
159159
if (wantsReview) {
160160
if (!view().reviewPanel.opened()) view().reviewPanel.open()
161-
layout.fileTree.open()
162161
layout.fileTree.setTab("changes")
162+
tabs().setActive("review")
163163
requestAnimationFrame(() => comments.setFocus(focus))
164164
return
165165
}
166166

167167
if (!view().reviewPanel.opened()) view().reviewPanel.open()
168-
layout.fileTree.open()
169168
layout.fileTree.setTab("all")
170169
const tab = files.tab(item.path)
171170
tabs().open(tab)

packages/app/src/components/prompt-input/slash-popover.tsx

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,18 +53,15 @@ export const PromptPopover: Component<PromptPopoverProps> = (props) => {
5353
>
5454
<For each={props.atFlat.slice(0, 10)}>
5555
{(item) => {
56-
const active = props.atActive === props.atKey(item)
57-
const shared = {
58-
"w-full flex items-center gap-x-2 rounded-md px-2 py-0.5": true,
59-
"bg-surface-raised-base-hover": active,
60-
}
56+
const key = props.atKey(item)
6157

6258
if (item.type === "agent") {
6359
return (
6460
<button
65-
classList={shared}
61+
class="w-full flex items-center gap-x-2 rounded-md px-2 py-0.5"
62+
classList={{ "bg-surface-raised-base-hover": props.atActive === key }}
6663
onClick={() => props.onAtSelect(item)}
67-
onMouseEnter={() => props.setAtActive(props.atKey(item))}
64+
onMouseEnter={() => props.setAtActive(key)}
6865
>
6966
<Icon name="brain" size="small" class="text-icon-info-active shrink-0" />
7067
<span class="text-14-regular text-text-strong whitespace-nowrap">@{item.name}</span>
@@ -78,9 +75,10 @@ export const PromptPopover: Component<PromptPopoverProps> = (props) => {
7875

7976
return (
8077
<button
81-
classList={shared}
78+
class="w-full flex items-center gap-x-2 rounded-md px-2 py-0.5"
79+
classList={{ "bg-surface-raised-base-hover": props.atActive === key }}
8280
onClick={() => props.onAtSelect(item)}
83-
onMouseEnter={() => props.setAtActive(props.atKey(item))}
81+
onMouseEnter={() => props.setAtActive(key)}
8482
>
8583
<FileIcon node={{ path: item.path, type: "file" }} class="shrink-0 size-4" />
8684
<div class="flex items-center text-14-regular min-w-0">

packages/app/src/components/session-context-usage.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ function openSessionContext(args: {
1919
tabs: ReturnType<ReturnType<typeof useLayout>["tabs"]>
2020
}) {
2121
if (!args.view.reviewPanel.opened()) args.view.reviewPanel.open()
22-
args.layout.fileTree.open()
23-
args.layout.fileTree.setTab("all")
22+
if (args.layout.fileTree.opened() && args.layout.fileTree.tab() !== "all") args.layout.fileTree.setTab("all")
2423
args.tabs.open("context")
2524
args.tabs.setActive("context")
2625
}

packages/app/src/components/session/session-header.tsx

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -311,12 +311,14 @@ export function SessionHeader() {
311311
platform,
312312
})
313313

314-
const centerMount = createMemo(() => document.getElementById("opencode-titlebar-center"))
314+
const leftMount = createMemo(
315+
() => document.getElementById("opencode-titlebar-left") ?? document.getElementById("opencode-titlebar-center"),
316+
)
315317
const rightMount = createMemo(() => document.getElementById("opencode-titlebar-right"))
316318

317319
return (
318320
<>
319-
<Show when={centerMount()}>
321+
<Show when={leftMount()}>
320322
{(mount) => (
321323
<Portal mount={mount()}>
322324
<button
@@ -550,7 +552,7 @@ export function SessionHeader() {
550552
</Show>
551553
</div>
552554
</Show>
553-
<div class="hidden md:flex items-center gap-3 ml-2 shrink-0">
555+
<div class="hidden lg:flex items-center gap-3 ml-2 shrink-0">
554556
<TooltipKeybind
555557
title={language.t("command.terminal.toggle")}
556558
keybind={command.keybind("terminal.toggle")}
@@ -583,7 +585,7 @@ export function SessionHeader() {
583585
</Button>
584586
</TooltipKeybind>
585587
</div>
586-
<div class="hidden md:block shrink-0">
588+
<div class="hidden lg:block shrink-0">
587589
<TooltipKeybind title={language.t("command.review.toggle")} keybind={command.keybind("review.toggle")}>
588590
<Button
589591
variant="ghost"
@@ -613,7 +615,7 @@ export function SessionHeader() {
613615
</Button>
614616
</TooltipKeybind>
615617
</div>
616-
<div class="hidden md:block shrink-0">
618+
<div class="hidden lg:block shrink-0">
617619
<TooltipKeybind
618620
title={language.t("command.fileTree.toggle")}
619621
keybind={command.keybind("fileTree.toggle")}

0 commit comments

Comments
 (0)