diff --git a/packages/mobile-voice/notes.md b/packages/mobile-voice/notes.md index f1d46ebaca..070b59f85b 100644 --- a/packages/mobile-voice/notes.md +++ b/packages/mobile-voice/notes.md @@ -4,3 +4,4 @@ - Need to figure out a good way to start new sessions. - When an agent returns a generation, we should be able to expand it into a reader mode view. - Work on the live activity widget. +- In the OpenCode Control app, if a link is generated in Markdown, it should be tappable and open in the device's default browser. diff --git a/packages/mobile-voice/src/app/index.tsx b/packages/mobile-voice/src/app/index.tsx index 0e775f119a..f4d24edc1e 100644 --- a/packages/mobile-voice/src/app/index.tsx +++ b/packages/mobile-voice/src/app/index.tsx @@ -370,7 +370,6 @@ function formatWorkingDirectory(directory?: string): string { type DropdownMode = "none" | "server" | "session" type Pair = { - v: 1 serverID?: string relayURL: string relaySecret: string @@ -454,18 +453,19 @@ type Cam = { function parsePairShape(data: unknown): Pair | undefined { if (!data || typeof data !== "object") return - if ((data as { v?: unknown }).v !== 1) return - if (typeof (data as { relayURL?: unknown }).relayURL !== "string") return + const version = (data as { v?: unknown }).v + if (version !== undefined && version !== 1) return if (typeof (data as { relaySecret?: unknown }).relaySecret !== "string") return if (!Array.isArray((data as { hosts?: unknown }).hosts)) return const hosts = (data as { hosts: unknown[] }).hosts.filter((item): item is string => typeof item === "string") if (!hosts.length) return + const relayURLRaw = (data as { relayURL?: unknown }).relayURL + const relayURL = typeof relayURLRaw === "string" && relayURLRaw.length > 0 ? relayURLRaw : DEFAULT_RELAY_URL const serverIDRaw = (data as { serverID?: unknown }).serverID const serverID = typeof serverIDRaw === "string" && serverIDRaw.length > 0 ? serverIDRaw : undefined return { - v: 1, serverID, - relayURL: (data as { relayURL: string }).relayURL, + relayURL, relaySecret: (data as { relaySecret: string }).relaySecret, hosts, } diff --git a/packages/opencode/src/cli/cmd/serve.ts b/packages/opencode/src/cli/cmd/serve.ts index 10dff74daa..4e3ea41ce0 100644 --- a/packages/opencode/src/cli/cmd/serve.ts +++ b/packages/opencode/src/cli/cmd/serve.ts @@ -15,13 +15,17 @@ import * as QRCode from "qrcode" const log = Log.create({ service: "serve" }) type PairPayload = { - v: 1 serverID?: string relayURL: string relaySecret: string hosts: string[] } +type PairQRCodePayload = { + relaySecret: string + hosts: string[] +} + type TailscaleStatus = { Self?: { DNSName?: unknown @@ -102,12 +106,12 @@ function hosts(hostname: string, port: number, advertised: string[] = [], includ return [...preferred, ...entries.map((item) => item.url)] } -function pairLink(pair: unknown) { - return `mobilevoice:///?pair=${encodeURIComponent(JSON.stringify(pair))}` -} - -function pairServerID(input: { relayURL: string; relaySecret: string }) { - return createHash("sha256").update(`${input.relayURL}|${input.relaySecret}`).digest("hex").slice(0, 16) +function pairLink(pair: PairQRCodePayload) { + const payload: PairQRCodePayload = { + relaySecret: pair.relaySecret, + hosts: pair.hosts, + } + return `mobilevoice:///?pair=${encodeURIComponent(JSON.stringify(payload))}` } function secretHash(input: string) { @@ -240,8 +244,6 @@ export const ServeCommand = cmd({ console.log("printing connect qr without starting the server") await printPairQR({ - v: 1, - serverID: pairServerID({ relayURL, relaySecret }), relayURL, relaySecret, hosts: pairHosts, @@ -274,8 +276,6 @@ export const ServeCommand = cmd({ }) const pair = started ?? PushRelay.pair() ?? { - v: 1 as const, - serverID: pairServerID({ relayURL, relaySecret }), relayURL, relaySecret, hosts: hosts(host, port, advertiseHosts), diff --git a/packages/opencode/src/server/routes/experimental.ts b/packages/opencode/src/server/routes/experimental.ts index 7dcc4c3eae..63f15d643c 100644 --- a/packages/opencode/src/server/routes/experimental.ts +++ b/packages/opencode/src/server/routes/experimental.ts @@ -21,9 +21,6 @@ import { Agent } from "@/agent/agent" const PushPairPayload = z .object({ - v: z.literal(1), - serverID: z.string().optional(), - relayURL: z.string(), relaySecret: z.string(), hosts: z.array(z.string()), }) @@ -49,12 +46,16 @@ const pushPairQROptions = { width: 256, } -function pushPairLink(payload: z.infer) { +function pushPairLink(input: { relaySecret: string; hosts: string[] }) { + const payload: z.infer = { + relaySecret: input.relaySecret, + hosts: input.hosts, + } return `mobilevoice:///?pair=${encodeURIComponent(JSON.stringify(payload))}` } -async function pushPairQRCode(payload: z.infer) { - return QRCode.toDataURL(pushPairLink(payload), pushPairQROptions) +async function pushPairQRCode(input: { relaySecret: string; hosts: string[] }) { + return QRCode.toDataURL(pushPairLink(input), pushPairQROptions) } const ConsoleOrgOption = z.object({