Skip to content

Commit 7bd487a

Browse files
Merge branch 'anomalyco:dev' into feat/hot-reload-smooth
2 parents 682203f + dd296f7 commit 7bd487a

74 files changed

Lines changed: 1261 additions & 333 deletions

Some content is hidden

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

bun.lock

Lines changed: 18 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

install

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

146160
target="$os-$arch"

nix/hashes.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"nodeModules": {
3-
"x86_64-linux": "sha256-saYZlUTkBfg9vp5J1CrJUM1PBXK4xKwyz28RKlT0JWo=",
4-
"aarch64-linux": "sha256-qoiX2CpOD+HSI+eLh3I84TTPdhWdG6MzfkDAXE6ldPo=",
5-
"aarch64-darwin": "sha256-LbAvdaOBuftBoHvQPFwJGr0smg8vH4wNHS6BYdyXdDs=",
6-
"x86_64-darwin": "sha256-bv5qb9Fi8SyrgZFhcdlvYNc4bjyvdyHY3YgUpmkEH2U="
3+
"x86_64-linux": "sha256-XIf7b6yALzH1/MkGGrsmq2DeXIC9vgD9a7D/dxhi6iU=",
4+
"aarch64-linux": "sha256-mKDCs6QhIelWc3E17zOufaSDTovtjO/Xyh3JtlWl01s=",
5+
"aarch64-darwin": "sha256-wC7bbbIyZ62uMxTr9FElTbEBMrfz0S/ndqwZZ3V9EOA=",
6+
"x86_64-darwin": "sha256-/7Nn65m5Zhvzz0TKsG9nWd2v5WDHQNi3UzCfuAR8SLo="
77
}
88
}

package.json

Lines changed: 2 additions & 2 deletions
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",
@@ -23,7 +23,7 @@
2323
"packages/slack"
2424
],
2525
"catalog": {
26-
"@types/bun": "1.3.5",
26+
"@types/bun": "1.3.9",
2727
"@octokit/rest": "22.0.0",
2828
"@hono/zod-validator": "0.4.2",
2929
"ulid": "3.0.1",

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/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@opencode-ai/app",
3-
"version": "1.1.63",
3+
"version": "1.1.64",
44
"description": "",
55
"type": "module",
66
"exports": {

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
}
@@ -328,8 +346,7 @@ export function DialogConnectProvider(props: { provider: string }) {
328346
await complete()
329347
return
330348
}
331-
const message = result.error instanceof Error ? result.error.message : String(result.error)
332-
setFormStore("error", message || language.t("provider.connect.oauth.code.invalid"))
349+
setFormStore("error", formatError(result.error, language.t("provider.connect.oauth.code.invalid")))
333350
}
334351

335352
return (
@@ -385,7 +402,7 @@ export function DialogConnectProvider(props: { provider: string }) {
385402
if (!alive.value) return
386403

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

packages/app/src/components/dialog-manage-models.tsx

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { Dialog } from "@opencode-ai/ui/dialog"
22
import { List } from "@opencode-ai/ui/list"
33
import { Switch } from "@opencode-ai/ui/switch"
4+
import { Tooltip } from "@opencode-ai/ui/tooltip"
45
import { Button } from "@opencode-ai/ui/button"
56
import type { Component } from "solid-js"
67
import { useLocal } from "@/context/local"
@@ -18,6 +19,14 @@ export const DialogManageModels: Component = () => {
1819
dialog.show(() => <DialogSelectProvider />)
1920
}
2021
const providerRank = (id: string) => popularProviders.indexOf(id)
22+
const providerList = (providerID: string) => local.model.list().filter((x) => x.provider.id === providerID)
23+
const providerVisible = (providerID: string) =>
24+
providerList(providerID).every((x) => local.model.visible({ modelID: x.id, providerID: x.provider.id }))
25+
const setProviderVisibility = (providerID: string, checked: boolean) => {
26+
providerList(providerID).forEach((x) => {
27+
local.model.setVisibility({ modelID: x.id, providerID: x.provider.id }, checked)
28+
})
29+
}
2130

2231
return (
2332
<Dialog
@@ -36,7 +45,28 @@ export const DialogManageModels: Component = () => {
3645
items={local.model.list()}
3746
filterKeys={["provider.name", "name", "id"]}
3847
sortBy={(a, b) => a.name.localeCompare(b.name)}
39-
groupBy={(x) => x.provider.name}
48+
groupBy={(x) => x.provider.id}
49+
groupHeader={(group) => {
50+
const provider = group.items[0].provider
51+
return (
52+
<>
53+
<span>{provider.name}</span>
54+
<Tooltip
55+
placement="top"
56+
value={language.t("dialog.model.manage.provider.toggle", { provider: provider.name })}
57+
>
58+
<Switch
59+
class="-mr-1"
60+
checked={providerVisible(provider.id)}
61+
onChange={(checked) => setProviderVisibility(provider.id, checked)}
62+
hideLabel
63+
>
64+
{provider.name}
65+
</Switch>
66+
</Tooltip>
67+
</>
68+
)
69+
}}
4070
sortGroupsBy={(a, b) => {
4171
const aRank = providerRank(a.items[0].provider.id)
4272
const bRank = providerRank(b.items[0].provider.id)

0 commit comments

Comments
 (0)