diff options
| author | Brendan Allan <[email protected]> | 2026-01-13 13:58:00 +0800 |
|---|---|---|
| committer | GitHub <[email protected]> | 2026-01-13 13:58:00 +0800 |
| commit | f05f175842d57003692ea766b07857d6f4b05f2b (patch) | |
| tree | ed9d6ce0d89a1f7b615970183366e9d7031ae908 /packages/desktop/src | |
| parent | c0b214232d8820f53c6a9f7fc1d38334012417db (diff) | |
| download | opencode-f05f175842d57003692ea766b07857d6f4b05f2b.tar.gz opencode-f05f175842d57003692ea766b07857d6f4b05f2b.zip | |
feat(desktop): spawn local server with password (#8139)
Diffstat (limited to 'packages/desktop/src')
| -rw-r--r-- | packages/desktop/src/index.tsx | 54 |
1 files changed, 41 insertions, 13 deletions
diff --git a/packages/desktop/src/index.tsx b/packages/desktop/src/index.tsx index a26cc61ca..1ad015aff 100644 --- a/packages/desktop/src/index.tsx +++ b/packages/desktop/src/index.tsx @@ -13,12 +13,11 @@ import { AsyncStorage } from "@solid-primitives/storage" import { fetch as tauriFetch } from "@tauri-apps/plugin-http" import { Store } from "@tauri-apps/plugin-store" import { Logo } from "@opencode-ai/ui/logo" -import { Accessor, JSX, createResource } from "solid-js" +import { createSignal, Show, Accessor, JSX, createResource } from "solid-js" import { UPDATER_ENABLED } from "./updater" import { createMenu } from "./menu" import pkg from "../package.json" -import { Show } from "solid-js" const root = document.getElementById("root") if (import.meta.env.DEV && !(root instanceof HTMLElement)) { @@ -29,7 +28,7 @@ if (import.meta.env.DEV && !(root instanceof HTMLElement)) { let update: Update | null = null -const platform: Platform = { +const createPlatform = (password: Accessor<string | null>): Platform => ({ platform: "desktop", version: pkg.version, @@ -256,7 +255,25 @@ const platform: Platform = { }, // @ts-expect-error - fetch: tauriFetch, + fetch: (input, init) => { + const pw = password() + + const addHeader = (headers: Headers, password: string) => { + headers.append("Authorization", `Basic ${btoa(`opencode:${password}`)}`) + } + + if (input instanceof Request) { + if (pw) addHeader(input.headers, pw) + return tauriFetch(input) + } else { + const headers = new Headers(init?.headers) + if (pw) addHeader(headers, pw) + return tauriFetch(input, { + ...(init as any), + headers: headers, + }) + } + }, getDefaultServerUrl: async () => { const result = await invoke<string | null>("get_default_server_url").catch(() => null) @@ -266,7 +283,7 @@ const platform: Platform = { setDefaultServerUrl: async (url: string | null) => { await invoke("set_default_server_url", { url }) }, -} +}) createMenu() @@ -276,26 +293,37 @@ root?.addEventListener("mousewheel", (e) => { }) render(() => { + const [serverPassword, setServerPassword] = createSignal<string | null>(null) + const platform = createPlatform(() => serverPassword()) + return ( <PlatformProvider value={platform}> - {ostype() === "macos" && ( - <div class="mx-px bg-background-base border-b border-border-weak-base h-8" data-tauri-drag-region /> - )} <AppBaseProviders> - <ServerGate>{(serverUrl) => <AppInterface defaultUrl={serverUrl()} />}</ServerGate> + {ostype() === "macos" && ( + <div class="mx-px bg-background-base border-b border-border-weak-base h-8" data-tauri-drag-region /> + )} + <ServerGate> + {(data) => { + setServerPassword(data().password) + + return <AppInterface defaultUrl={data().url} /> + }} + </ServerGate> </AppBaseProviders> </PlatformProvider> ) }, root!) +type ServerReadyData = { url: string; password: string | null } + // Gate component that waits for the server to be ready -function ServerGate(props: { children: (url: Accessor<string>) => JSX.Element }) { - const [serverUrl] = createResource<string>(() => invoke("ensure_server_ready")) +function ServerGate(props: { children: (data: Accessor<ServerReadyData>) => JSX.Element }) { + const [serverData] = createResource<ServerReadyData>(() => invoke("ensure_server_ready")) return ( // Not using suspense as not all components are compatible with it (undefined refs) <Show - when={serverUrl.state !== "pending" && serverUrl()} + when={serverData.state !== "pending" && serverData()} fallback={ <div class="h-screen w-screen flex flex-col items-center justify-center bg-background-base"> <Logo class="w-xl opacity-12 animate-pulse" /> @@ -303,7 +331,7 @@ function ServerGate(props: { children: (url: Accessor<string>) => JSX.Element }) </div> } > - {(serverUrl) => props.children(serverUrl)} + {(data) => props.children(data)} </Show> ) } |
