diff --git a/packages/desktop/src/main/ipc.ts b/packages/desktop/src/main/ipc.ts index 8dbca8ee..45ed1b4e 100644 --- a/packages/desktop/src/main/ipc.ts +++ b/packages/desktop/src/main/ipc.ts @@ -11,7 +11,7 @@ import type { WslConfig, } from "../preload/types" import { getStore } from "./store" -import { setTitlebar } from "./windows" +import { setTitlebar, setNativeThemeSource } from "./windows" const pickerFilters = (ext?: string[]) => { if (!ext || ext.length === 0) return undefined @@ -38,6 +38,7 @@ type Deps = { checkUpdate: () => Promise<{ updateAvailable: boolean; version?: string }> installUpdate: () => Promise | void setBackgroundColor: (color: string) => void + setNativeTheme: (mode: "light" | "dark") => void } export function registerIpcHandlers(deps: Deps) { @@ -69,6 +70,7 @@ export function registerIpcHandlers(deps: Deps) { ipcMain.handle("check-update", () => deps.checkUpdate()) ipcMain.handle("install-update", () => deps.installUpdate()) ipcMain.handle("set-background-color", (_event: IpcMainInvokeEvent, color: string) => deps.setBackgroundColor(color)) + ipcMain.handle("set-native-theme", (_event: IpcMainInvokeEvent, mode: "light" | "dark") => setNativeThemeSource(mode)) ipcMain.handle("store-get", (_event: IpcMainInvokeEvent, name: string, key: string) => { const store = getStore(name) const value = store.get(key) diff --git a/packages/desktop/src/main/windows.ts b/packages/desktop/src/main/windows.ts index 337e1ca0..ae1b45f1 100644 --- a/packages/desktop/src/main/windows.ts +++ b/packages/desktop/src/main/windows.ts @@ -52,6 +52,10 @@ function overlay(theme: Partial = {}) { } } +export function setNativeThemeSource(mode: "light" | "dark") { + nativeTheme.themeSource = mode +} + export function setTitlebar(win: BrowserWindow, theme: Partial = {}) { if (process.platform !== "win32") return win.setTitleBarOverlay(overlay(theme)) diff --git a/packages/desktop/src/preload/index.ts b/packages/desktop/src/preload/index.ts index 6261419c..4b33f0ed 100644 --- a/packages/desktop/src/preload/index.ts +++ b/packages/desktop/src/preload/index.ts @@ -66,6 +66,7 @@ const api: ElectronAPI = { checkUpdate: () => ipcRenderer.invoke("check-update"), installUpdate: () => ipcRenderer.invoke("install-update"), setBackgroundColor: (color: string) => ipcRenderer.invoke("set-background-color", color), + setNativeTheme: (mode: "light" | "dark") => ipcRenderer.invoke("set-native-theme", mode), } contextBridge.exposeInMainWorld("api", api) diff --git a/packages/desktop/src/preload/types.ts b/packages/desktop/src/preload/types.ts index 6e22954d..74beeee9 100644 --- a/packages/desktop/src/preload/types.ts +++ b/packages/desktop/src/preload/types.ts @@ -76,4 +76,5 @@ export type ElectronAPI = { checkUpdate: () => Promise<{ updateAvailable: boolean; version?: string }> installUpdate: () => Promise setBackgroundColor: (color: string) => Promise + setNativeTheme: (mode: "light" | "dark") => Promise } diff --git a/packages/desktop/src/renderer/index.tsx b/packages/desktop/src/renderer/index.tsx index f7df9d4d..83e9fb6a 100644 --- a/packages/desktop/src/renderer/index.tsx +++ b/packages/desktop/src/renderer/index.tsx @@ -310,11 +310,12 @@ render(() => { createEffect(() => { theme.themeId() - theme.mode() + const mode = theme.mode() const bg = getComputedStyle(document.documentElement).getPropertyValue("--background-base").trim() if (bg) { void window.api.setBackgroundColor(bg) } + void window.api.setNativeTheme(mode) }) return null diff --git a/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx b/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx index c9c94a45..a2f73152 100644 --- a/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx +++ b/packages/opencode/src/cli/cmd/tui/component/dialog-provider.tsx @@ -188,10 +188,9 @@ export async function runCustomProviderWizard(opts: { const baseURL = baseURLRaw.trim() if (!baseURL) return - const apiKeyRaw = await step(4, 6, "API key", "sk-...") + const apiKeyRaw = await step(4, 6, "API key (optional, Enter to skip)", "sk-...") if (apiKeyRaw === null) return const apiKey = apiKeyRaw.trim() - if (!apiKey) return const modelIDRaw = await step(5, 6, "First model id", "e.g. claude-sonnet-4-6") if (modelIDRaw === null) return @@ -208,7 +207,7 @@ export async function runCustomProviderWizard(opts: { [providerID]: { name, npm: "@ai-sdk/openai-compatible", - env: [envKey], + ...(apiKey ? { env: [envKey] } : {}), options: { baseURL, setCacheKey: true, @@ -228,13 +227,15 @@ export async function runCustomProviderWizard(opts: { return } - const authRes = await sdk.client.auth.set({ - providerID, - auth: { type: "api", key: apiKey }, - }) - if (authRes.error) { - toast.show({ variant: "error", message: JSON.stringify(authRes.error) }) - return + if (apiKey) { + const authRes = await sdk.client.auth.set({ + providerID, + auth: { type: "api", key: apiKey }, + }) + if (authRes.error) { + toast.show({ variant: "error", message: JSON.stringify(authRes.error) }) + return + } } await sdk.client.instance.dispose()