mindwire 0.1.47 → 0.1.48

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -185,6 +185,22 @@ new Mindwire({ target: oblien({ clientId: process.env.OBLIEN_CLIENT_ID, clientSe
185
185
 
186
186
  Any object implementing `Target` can also be passed as `target` (bring-your-own).
187
187
 
188
+ For an application-owned local profile, use `local({ cwd, statePath, environment,
189
+ authSource: "host", shared: false })`. `environment` replaces the inherited process
190
+ environment; the optional `authSource` lets the native adapters automatically reuse
191
+ the host's saved connection on the first agent/status read or turn. Existing account
192
+ choices and explicit sign-out are preserved. No client-side `auth.begin()` is needed
193
+ for first setup. Use `authSource: { home, environment, reuse: "manual" }` if a host
194
+ requires explicit selection instead. Methods with `existing` metadata display the
195
+ discovered account/provider and model without exposing credentials;
196
+ `auth.begin(method.id)` remains available to reconnect after sign-out or retry a
197
+ failed import. Native tools, hooks and unrelated host configuration are not imported.
198
+ `await mw.close()` stops the owned daemon. Shared local targets remain alive until
199
+ the host exits or their embedded handle is explicitly stopped.
200
+ `local().profileVersion` advertises this SDK contract before a process starts;
201
+ applications requiring private profiles should reject targets without it. The
202
+ daemon separately reports `health.nativeAuthSource`, which the SDK checks at startup.
203
+
188
204
  ### Provisioning logs & `ensure()`
189
205
 
190
206
  `ssh` / `docker` / `oblien` prep the box on connect — upload the daemon binary, launch it, health-poll
@@ -1,4 +1,4 @@
1
- import { websocketURL, readJSON, writeJSON, acquireProcessLock, computerClient, versionAtLeast } from './chunk-7QLYFISG.js';
1
+ import { websocketURL, readJSON, writeJSON, acquireProcessLock, computerClient, versionAtLeast } from './chunk-PCBZ5RU5.js';
2
2
  import { join } from 'path';
3
3
  import { setTimeout } from 'timers/promises';
4
4
 
@@ -302,5 +302,5 @@ function updateProgress(update) {
302
302
  }
303
303
 
304
304
  export { activeUpdate, connectionAddress, connectionDescription, connectionInfo, disableAddressDiscovery, discoveryDescription, discoveryPreference, enableAddressDiscovery, queueServiceUpdate, reconcileAddressDiscovery, saveDiscoveryPreference, updateComputer, updateProgress };
305
- //# sourceMappingURL=chunk-ZL4EIEF7.js.map
306
- //# sourceMappingURL=chunk-ZL4EIEF7.js.map
305
+ //# sourceMappingURL=chunk-DDXMDQOM.js.map
306
+ //# sourceMappingURL=chunk-DDXMDQOM.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/computer/provider-info.ts","../src/computer/directory-http.ts","../src/computer/discovery.ts","../src/computer/service-update.ts"],"names":["delay","join"],"mappings":"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","file":"chunk-ZL4EIEF7.js","sourcesContent":["import type { ComputerConnectionInfo } from \"../computer.js\";\nimport type { RelayOptions } from \"./relay.js\";\nimport { websocketURL } from \"./relay.js\";\n\n/** Credential renewal does not change the address already saved by the phone. */\nexport function connectionAddress(relay: RelayOptions, host?: string): string {\n return relay.kind === \"none\" ? `ssh:${host ?? \"network\"}`\n : relay.url ? websocketURL(relay.url) : `temporary:${relay.kind}`;\n}\n\n/** Public, non-secret metadata. Route/SSH identity is independent of provider credentials. */\nexport function connectionInfo(relay: RelayOptions, host?: string): ComputerConnectionInfo {\n if (relay.kind === \"none\") return { provider: \"direct\", address: host ? \"persistent\" : \"network\" };\n return { provider: relay.kind, address: [\"cloudflare\", \"ngrok\"].includes(relay.kind) && !relay.url ? \"temporary\" : \"persistent\" };\n}\n\nexport function connectionDescription(info: ComputerConnectionInfo): string {\n const name = { oblien: \"Oblien\", cloudflare: \"Cloudflare\", ngrok: \"ngrok\", custom: \"Your tunnel\", direct: \"Direct SSH / VPN\" }[info.provider];\n if (info.address === \"temporary\") return `${name} · temporary address. For reconnect after a restart, run mindwire connection to choose a persistent address.`;\n if (info.address === \"network\") return `${name} · reachable network required. Use a VPN hostname for access across networks.`;\n return `${name} · persistent address. Saved phones retry automatically when this computer is online.`;\n}\n","export class DirectoryRequestError extends Error {\n constructor(\n readonly status: number,\n readonly code: string,\n readonly retryAfter = 0,\n ) {\n super(\n status === 0\n ? \"Couldn't reach the address directory securely. Check its HTTPS address and retry.\"\n : `The address directory rejected the request (${code}).`,\n );\n }\n}\n\n/** Bounded, same-origin requests. No redirects, cookie jar or retained credentials. */\nexport async function directoryRequest<T>(url: string, path: string, body: unknown, signal?: AbortSignal): Promise<T> {\n let response: Response;\n try {\n response = await fetch(url + path, {\n method: \"POST\",\n redirect: \"error\",\n signal: signal ? AbortSignal.any([signal, AbortSignal.timeout(10_000)]) : AbortSignal.timeout(10_000),\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n },\n body: JSON.stringify(body),\n });\n } catch {\n signal?.throwIfAborted();\n throw new DirectoryRequestError(0, \"unreachable\");\n }\n const reader = response.body?.getReader();\n const chunks: Uint8Array[] = [];\n let length = 0;\n try {\n if (reader)\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n length += value.byteLength;\n if (length > 64 * 1024) throw new Error(\"The address directory returned an oversized response.\");\n chunks.push(value);\n }\n } finally {\n void reader?.cancel().catch(() => {});\n }\n let data: unknown;\n try {\n data = JSON.parse(Buffer.concat(chunks).toString(\"utf8\"));\n } catch {\n throw new DirectoryRequestError(response.status, \"invalid_response\");\n }\n if (!response.ok) {\n const error = (data as { error?: unknown } | null)?.error;\n const code = typeof error === \"string\" ? error : (error as { code?: unknown } | null)?.code;\n const retryAfter = Number(response.headers.get(\"Retry-After\"));\n throw new DirectoryRequestError(\n response.status,\n typeof code === \"string\" && /^[a-z_]{1,64}$/.test(code) ? code : \"directory_error\",\n Number.isFinite(retryAfter) ? Math.max(0, Math.min(60, retryAfter)) : 0,\n );\n }\n return data as T;\n}\n","import { join } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport type { Mindwire } from \"../client.js\";\nimport type { ComputerDiscoveryStatus } from \"../computer.js\";\nimport { acquireProcessLock } from \"./lock.js\";\nimport type { SetupPrompt } from \"./setup-prompt.js\";\nimport { directoryRequest, DirectoryRequestError } from \"./directory-http.js\";\nimport { readJSON, writeJSON, type ComputerConfig } from \"./lifecycle.js\";\n\nexport const DIRECTORY_API_PATH = \"/api/computer-directory/v1\";\nexport const DIRECTORY_URL = `https://console.mindwire.sh${DIRECTORY_API_PATH}`;\n\nexport interface DiscoveryPreference { enabled: boolean; url?: string }\nexport const discoveryPreference = (directory: string) =>\n readJSON<DiscoveryPreference>(join(directory, \"computer-discovery-preference.json\"));\n\n/** Desired setup is durable even if enrollment is temporarily offline. The\n * daemon remains the authority for signed publications and phone access. */\nexport async function saveDiscoveryPreference(directory: string, value: DiscoveryPreference): Promise<void> {\n const preference = { ...value, url: value.url ? directoryURL(value.url) : undefined };\n await writeJSON(join(directory, \"computer-discovery-preference.json\"), preference);\n}\n\nexport function directoryURL(value: string): string {\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n throw new Error(\"Enter the directory's HTTPS API URL.\");\n }\n if (\n value.length > 2048 ||\n /[\\s\\x00]/.test(value) ||\n url.username ||\n url.password ||\n url.search ||\n url.hash ||\n (url.protocol !== \"https:\" &&\n !(url.protocol === \"http:\" && [\"localhost\", \"127.0.0.1\", \"[::1]\"].includes(url.hostname)))\n ) {\n throw new Error(\"Use an HTTPS directory URL without credentials, a query, or a fragment.\");\n }\n if (url.pathname === \"/\") url.pathname = DIRECTORY_API_PATH;\n if (url.pathname.endsWith(\"/\") || url.pathname.includes(\"//\") || url.pathname.includes(\"%\")) {\n throw new Error(\"Use the exact directory API URL without a trailing slash.\");\n }\n return url.href;\n}\n\nexport async function enableAddressDiscovery(options: {\n directory: string;\n computer: Mindwire;\n prompt: SetupPrompt;\n url?: string;\n waitForPublication?: boolean;\n signal?: AbortSignal;\n reconcile?: boolean;\n}): Promise<ComputerDiscoveryStatus> {\n const lock = await acquireProcessLock(join(options.directory, \"discovery-setup.lock\"), { signal: options.signal });\n try {\n let status: ComputerDiscoveryStatus;\n try {\n status = await options.computer.computer.discovery();\n } catch (error) {\n if ((error as { status?: number }).status === 404)\n throw new Error(\"Update the Mindwire service before enabling automatic address recovery.\");\n throw error;\n }\n const preference = await discoveryPreference(options.directory);\n if (options.reconcile && preference?.enabled === false) return status;\n // Preserve a saved private directory across upgrades. Credentials belonging\n // to another provider are never read by this flow.\n const url = directoryURL(\n options.url ?? process.env.MINDWIRE_DIRECTORY_URL ?? status.url ?? preference?.url ?? DIRECTORY_URL,\n );\n if (\n status.url &&\n status.url !== url &&\n (status.enabled || (status.sequence ?? 0) !== (status.publishedSequence ?? 0))\n ) {\n throw new Error(\n \"Disable the current directory with mindwire discovery disable and wait for its withdrawal before changing the directory URL.\",\n );\n }\n await saveDiscoveryPreference(options.directory, { enabled: true, url });\n if (!status.enabled || status.url !== url || status.error?.includes(\"enrollment\")) {\n options.prompt.print(`Enabling encrypted address recovery with ${new URL(url).host}…`);\n try {\n const challenge = await directoryRequest<{ challenge: string }>(url, \"/registrations/challenge\", {\n directoryId: status.directoryId,\n }, options.signal);\n if (\n typeof challenge?.challenge !== \"string\" ||\n challenge.challenge.length < 16 ||\n challenge.challenge.length > 2048\n ) {\n throw new Error(\"The address directory returned an invalid enrollment challenge.\");\n }\n const proof = await options.computer.computer.directoryEnrollment(url, challenge.challenge);\n const enrolled = await directoryRequest<{ directoryId: string }>(url, \"/registrations\", proof, options.signal);\n if (enrolled?.directoryId !== status.directoryId)\n throw new Error(\"The directory acknowledged a different computer.\");\n } catch (error) {\n if (error instanceof DirectoryRequestError) {\n if (error.status === 404 || error.status === 501)\n throw new Error(\n \"The address directory isn't available at this URL. Your existing connection still works; retry after the backend is deployed.\",\n );\n if (error.status === 409)\n throw new Error(\n \"This computer's directory registration is revoked or conflicts with its saved identity. Contact the directory operator.\",\n );\n if (error.code === \"account_required\")\n throw new Error(\n \"This directory still requires an account. Update its Mindwire backend to enable key-based registration, or choose another directory with --directory-url.\",\n );\n if (error.status === 401 || error.status === 403)\n throw new Error(\n \"The directory couldn't verify this computer's key or challenge. Retry enrollment.\",\n );\n if (error.status === 429)\n throw new Error(\n \"The directory's registration limit was reached. Retry later or use another directory.\",\n );\n if (error.status === 503)\n throw new Error(\n \"The directory is temporarily unavailable or at capacity. Your existing connection still works.\",\n );\n }\n throw error;\n }\n status = await options.computer.computer.configureDiscovery(true, url);\n }\n if (options.waitForPublication === false) return status;\n const deadline = Date.now() + 15_000;\n while (Date.now() < deadline) {\n status = await options.computer.computer.discovery();\n if (status.enabled && status.sequence && status.publishedSequence === status.sequence) return status;\n if (status.error?.includes(\"enrollment\") || status.error?.includes(\"older revision\"))\n throw new Error(status.error);\n await delay(250, undefined, { signal: options.signal });\n }\n throw new Error(\n \"Address recovery is configured and will retry in the background. Run mindwire discovery status to check publication.\",\n );\n } finally {\n await lock?.close();\n }\n}\n\nexport async function disableAddressDiscovery(directory: string, computer: Mindwire, reconcile = false): Promise<ComputerDiscoveryStatus> {\n const lock = await acquireProcessLock(join(directory, \"discovery-setup.lock\"));\n try {\n const status = await computer.computer.discovery();\n const preference = await discoveryPreference(directory);\n if (reconcile && preference?.enabled === true) return status;\n await saveDiscoveryPreference(directory, { enabled: false, url: status.url ?? preference?.url });\n if (!status.enabled) return status;\n return await computer.computer.configureDiscovery(false);\n } finally { await lock?.close(); }\n}\n\n/** Runs once after startup and retries failed enrollment in the controller. A\n * healthy setup makes only a local status read: publication/renewal stays in Go.\n * Direct/VPN/custom connections never opt into a hosted directory implicitly. */\nexport async function reconcileAddressDiscovery(options: {\n directory: string; config: ComputerConfig; computer: Mindwire; signal?: AbortSignal;\n}): Promise<void> {\n const preference = await discoveryPreference(options.directory);\n const { discovery: status } = await options.computer.computer.info();\n const automatic = options.config.relay.kind === \"cloudflare\" && !options.config.relay.url;\n const enabled = preference?.enabled ?? (status?.enabled || automatic && !status?.url);\n if (!enabled) {\n if (preference?.enabled === false && status?.enabled) await disableAddressDiscovery(options.directory, options.computer, true);\n return;\n }\n if (!status) throw new Error(\"Update the Mindwire service to enable automatic reconnection.\");\n const url = directoryURL(preference?.url ?? process.env.MINDWIRE_DIRECTORY_URL ?? status.url ?? DIRECTORY_URL);\n if (status.enabled && status.url === url && !status.error?.includes(\"enrollment\")) return;\n await enableAddressDiscovery({ ...options, url, waitForPublication: false, reconcile: true,\n prompt: { print() {}, open() {}, question: async () => { throw new Error(\"Unexpected interactive setup.\"); },\n secret: async () => { throw new Error(\"Unexpected interactive setup.\"); } } });\n}\n\nexport function discoveryDescription(status: ComputerDiscoveryStatus | undefined): string {\n if (!status?.enabled) return \"Automatic address recovery is off. Enable it with mindwire discovery enable.\";\n if (status.error) return status.error;\n return status.sequence && status.publishedSequence === status.sequence\n ? \"Encrypted address recovery is on. Saved phones can find this computer when its tunnel address changes.\"\n : \"Publishing the computer's encrypted address…\";\n}\n","import { join } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport type { ComputerUpdate } from \"../computer.js\";\nimport type { Mindwire } from \"../client.js\";\nimport { computerClient, readJSON } from \"./lifecycle.js\";\nimport { versionAtLeast } from \"../version.js\";\n\ntype UpdateClient = Pick<Mindwire, \"health\" | \"computer\">;\nexport function activeUpdate(update: ComputerUpdate | undefined): update is ComputerUpdate {\n return !!update && [\"queued\", \"downloading\", \"waiting\", \"restarting\"].includes(update.status);\n}\n\n/** The daemon arbitrates requests. Join an earlier version before requesting the\n * next; promoting a request never creates a second download or bypasses its lease. */\nexport async function queueServiceUpdate(client: UpdateClient, version: string, force = false): Promise<ComputerUpdate> {\n for (let attempt = 0; ; attempt++) {\n const previous = await client.computer.updateStatus();\n if (activeUpdate(previous) && (!force || previous.force)) return previous;\n try {\n return await client.computer.requestUpdate(activeUpdate(previous) ? previous.version : version, { force });\n } catch (error) {\n if ((error as { status?: number }).status !== 409 || attempt >= 2) throw error;\n // Another caller won admission. Read the authoritative request and join it.\n }\n }\n}\n\nexport interface ServiceUpdateResult { version: string; complete: boolean; update?: ComputerUpdate }\n\n/** A CLI may close after queuing: the controller owns download/restart. Human\n * callers get a bounded result, including the exact older request being joined. */\nexport async function updateComputer(options: {\n directory: string; version: string; force?: boolean; allowDowngrade?: boolean;\n onProgress?: (update: ComputerUpdate) => void; signal?: AbortSignal; timeoutMs?: number;\n connect?: () => Promise<UpdateClient>;\n}):\nPromise<ServiceUpdateResult> {\n const version = options.version.replace(/^v/, \"\");\n if (!/^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?$/.test(version)) throw new Error(\"Enter a Mindwire release version, such as 0.1.38.\");\n const connect = options.connect ?? (() => computerClient(options.directory));\n const deadline = Date.now() + (options.timeoutMs ?? 120_000);\n let requested: ComputerUpdate | undefined, last = \"\";\n for (;;) {\n options.signal?.throwIfAborted();\n if (!requested) {\n const client = await connect();\n const installed = (await client.health()).version.replace(/^v/, \"\");\n if (installed === version || !options.allowDowngrade && versionAtLeast(installed, version))\n return { version: installed, complete: true };\n requested = await queueServiceUpdate(client, version, options.force);\n }\n // Progress survives the short API outage during restart. Only the daemon\n // accepts new requests; this read never changes or clears its status.\n const update = await readJSON<ComputerUpdate>(join(options.directory, \"computer-update.json\")) ?? requested;\n if (update.id !== requested.id) {\n // A concurrent update completed/advanced first. Recheck the live service.\n requested = undefined;\n } else {\n const key = `${update.id}:${update.status}`;\n if (last !== key) { last = key; options.onProgress?.(update); }\n if (update.status === \"failed\") throw new Error(update.error ?? \"The service update failed. Run mindwire inspect for details.\");\n if (update.status === \"complete\") {\n requested = undefined;\n if (Date.now() < deadline) continue;\n } else if (!options.force && update.status === \"waiting\") {\n return { version, complete: false, update };\n }\n }\n if (Date.now() >= deadline) return { version, complete: false, update };\n await delay(500, undefined, { signal: options.signal });\n }\n}\n\nexport function updateProgress(update: ComputerUpdate): string {\n const phase: Record<ComputerUpdate[\"status\"], string> = {\n idle: \"Ready\", queued: \"Queued\", downloading: \"Downloading verified release…\",\n waiting: \"Waiting for active work to finish\", restarting: \"Restarting service…\",\n complete: \"Installed\", failed: \"Update failed\",\n };\n return `${update.version} · ${phase[update.status]}`;\n}\n"]}
1
+ {"version":3,"sources":["../src/computer/provider-info.ts","../src/computer/directory-http.ts","../src/computer/discovery.ts","../src/computer/service-update.ts"],"names":["delay","join"],"mappings":"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","file":"chunk-DDXMDQOM.js","sourcesContent":["import type { ComputerConnectionInfo } from \"../computer.js\";\nimport type { RelayOptions } from \"./relay.js\";\nimport { websocketURL } from \"./relay.js\";\n\n/** Credential renewal does not change the address already saved by the phone. */\nexport function connectionAddress(relay: RelayOptions, host?: string): string {\n return relay.kind === \"none\" ? `ssh:${host ?? \"network\"}`\n : relay.url ? websocketURL(relay.url) : `temporary:${relay.kind}`;\n}\n\n/** Public, non-secret metadata. Route/SSH identity is independent of provider credentials. */\nexport function connectionInfo(relay: RelayOptions, host?: string): ComputerConnectionInfo {\n if (relay.kind === \"none\") return { provider: \"direct\", address: host ? \"persistent\" : \"network\" };\n return { provider: relay.kind, address: [\"cloudflare\", \"ngrok\"].includes(relay.kind) && !relay.url ? \"temporary\" : \"persistent\" };\n}\n\nexport function connectionDescription(info: ComputerConnectionInfo): string {\n const name = { oblien: \"Oblien\", cloudflare: \"Cloudflare\", ngrok: \"ngrok\", custom: \"Your tunnel\", direct: \"Direct SSH / VPN\" }[info.provider];\n if (info.address === \"temporary\") return `${name} · temporary address. For reconnect after a restart, run mindwire connection to choose a persistent address.`;\n if (info.address === \"network\") return `${name} · reachable network required. Use a VPN hostname for access across networks.`;\n return `${name} · persistent address. Saved phones retry automatically when this computer is online.`;\n}\n","export class DirectoryRequestError extends Error {\n constructor(\n readonly status: number,\n readonly code: string,\n readonly retryAfter = 0,\n ) {\n super(\n status === 0\n ? \"Couldn't reach the address directory securely. Check its HTTPS address and retry.\"\n : `The address directory rejected the request (${code}).`,\n );\n }\n}\n\n/** Bounded, same-origin requests. No redirects, cookie jar or retained credentials. */\nexport async function directoryRequest<T>(url: string, path: string, body: unknown, signal?: AbortSignal): Promise<T> {\n let response: Response;\n try {\n response = await fetch(url + path, {\n method: \"POST\",\n redirect: \"error\",\n signal: signal ? AbortSignal.any([signal, AbortSignal.timeout(10_000)]) : AbortSignal.timeout(10_000),\n headers: {\n \"Content-Type\": \"application/json\",\n Accept: \"application/json\",\n },\n body: JSON.stringify(body),\n });\n } catch {\n signal?.throwIfAborted();\n throw new DirectoryRequestError(0, \"unreachable\");\n }\n const reader = response.body?.getReader();\n const chunks: Uint8Array[] = [];\n let length = 0;\n try {\n if (reader)\n for (;;) {\n const { done, value } = await reader.read();\n if (done) break;\n length += value.byteLength;\n if (length > 64 * 1024) throw new Error(\"The address directory returned an oversized response.\");\n chunks.push(value);\n }\n } finally {\n void reader?.cancel().catch(() => {});\n }\n let data: unknown;\n try {\n data = JSON.parse(Buffer.concat(chunks).toString(\"utf8\"));\n } catch {\n throw new DirectoryRequestError(response.status, \"invalid_response\");\n }\n if (!response.ok) {\n const error = (data as { error?: unknown } | null)?.error;\n const code = typeof error === \"string\" ? error : (error as { code?: unknown } | null)?.code;\n const retryAfter = Number(response.headers.get(\"Retry-After\"));\n throw new DirectoryRequestError(\n response.status,\n typeof code === \"string\" && /^[a-z_]{1,64}$/.test(code) ? code : \"directory_error\",\n Number.isFinite(retryAfter) ? Math.max(0, Math.min(60, retryAfter)) : 0,\n );\n }\n return data as T;\n}\n","import { join } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport type { Mindwire } from \"../client.js\";\nimport type { ComputerDiscoveryStatus } from \"../computer.js\";\nimport { acquireProcessLock } from \"./lock.js\";\nimport type { SetupPrompt } from \"./setup-prompt.js\";\nimport { directoryRequest, DirectoryRequestError } from \"./directory-http.js\";\nimport { readJSON, writeJSON, type ComputerConfig } from \"./lifecycle.js\";\n\nexport const DIRECTORY_API_PATH = \"/api/computer-directory/v1\";\nexport const DIRECTORY_URL = `https://console.mindwire.sh${DIRECTORY_API_PATH}`;\n\nexport interface DiscoveryPreference { enabled: boolean; url?: string }\nexport const discoveryPreference = (directory: string) =>\n readJSON<DiscoveryPreference>(join(directory, \"computer-discovery-preference.json\"));\n\n/** Desired setup is durable even if enrollment is temporarily offline. The\n * daemon remains the authority for signed publications and phone access. */\nexport async function saveDiscoveryPreference(directory: string, value: DiscoveryPreference): Promise<void> {\n const preference = { ...value, url: value.url ? directoryURL(value.url) : undefined };\n await writeJSON(join(directory, \"computer-discovery-preference.json\"), preference);\n}\n\nexport function directoryURL(value: string): string {\n let url: URL;\n try {\n url = new URL(value);\n } catch {\n throw new Error(\"Enter the directory's HTTPS API URL.\");\n }\n if (\n value.length > 2048 ||\n /[\\s\\x00]/.test(value) ||\n url.username ||\n url.password ||\n url.search ||\n url.hash ||\n (url.protocol !== \"https:\" &&\n !(url.protocol === \"http:\" && [\"localhost\", \"127.0.0.1\", \"[::1]\"].includes(url.hostname)))\n ) {\n throw new Error(\"Use an HTTPS directory URL without credentials, a query, or a fragment.\");\n }\n if (url.pathname === \"/\") url.pathname = DIRECTORY_API_PATH;\n if (url.pathname.endsWith(\"/\") || url.pathname.includes(\"//\") || url.pathname.includes(\"%\")) {\n throw new Error(\"Use the exact directory API URL without a trailing slash.\");\n }\n return url.href;\n}\n\nexport async function enableAddressDiscovery(options: {\n directory: string;\n computer: Mindwire;\n prompt: SetupPrompt;\n url?: string;\n waitForPublication?: boolean;\n signal?: AbortSignal;\n reconcile?: boolean;\n}): Promise<ComputerDiscoveryStatus> {\n const lock = await acquireProcessLock(join(options.directory, \"discovery-setup.lock\"), { signal: options.signal });\n try {\n let status: ComputerDiscoveryStatus;\n try {\n status = await options.computer.computer.discovery();\n } catch (error) {\n if ((error as { status?: number }).status === 404)\n throw new Error(\"Update the Mindwire service before enabling automatic address recovery.\");\n throw error;\n }\n const preference = await discoveryPreference(options.directory);\n if (options.reconcile && preference?.enabled === false) return status;\n // Preserve a saved private directory across upgrades. Credentials belonging\n // to another provider are never read by this flow.\n const url = directoryURL(\n options.url ?? process.env.MINDWIRE_DIRECTORY_URL ?? status.url ?? preference?.url ?? DIRECTORY_URL,\n );\n if (\n status.url &&\n status.url !== url &&\n (status.enabled || (status.sequence ?? 0) !== (status.publishedSequence ?? 0))\n ) {\n throw new Error(\n \"Disable the current directory with mindwire discovery disable and wait for its withdrawal before changing the directory URL.\",\n );\n }\n await saveDiscoveryPreference(options.directory, { enabled: true, url });\n if (!status.enabled || status.url !== url || status.error?.includes(\"enrollment\")) {\n options.prompt.print(`Enabling encrypted address recovery with ${new URL(url).host}…`);\n try {\n const challenge = await directoryRequest<{ challenge: string }>(url, \"/registrations/challenge\", {\n directoryId: status.directoryId,\n }, options.signal);\n if (\n typeof challenge?.challenge !== \"string\" ||\n challenge.challenge.length < 16 ||\n challenge.challenge.length > 2048\n ) {\n throw new Error(\"The address directory returned an invalid enrollment challenge.\");\n }\n const proof = await options.computer.computer.directoryEnrollment(url, challenge.challenge);\n const enrolled = await directoryRequest<{ directoryId: string }>(url, \"/registrations\", proof, options.signal);\n if (enrolled?.directoryId !== status.directoryId)\n throw new Error(\"The directory acknowledged a different computer.\");\n } catch (error) {\n if (error instanceof DirectoryRequestError) {\n if (error.status === 404 || error.status === 501)\n throw new Error(\n \"The address directory isn't available at this URL. Your existing connection still works; retry after the backend is deployed.\",\n );\n if (error.status === 409)\n throw new Error(\n \"This computer's directory registration is revoked or conflicts with its saved identity. Contact the directory operator.\",\n );\n if (error.code === \"account_required\")\n throw new Error(\n \"This directory still requires an account. Update its Mindwire backend to enable key-based registration, or choose another directory with --directory-url.\",\n );\n if (error.status === 401 || error.status === 403)\n throw new Error(\n \"The directory couldn't verify this computer's key or challenge. Retry enrollment.\",\n );\n if (error.status === 429)\n throw new Error(\n \"The directory's registration limit was reached. Retry later or use another directory.\",\n );\n if (error.status === 503)\n throw new Error(\n \"The directory is temporarily unavailable or at capacity. Your existing connection still works.\",\n );\n }\n throw error;\n }\n status = await options.computer.computer.configureDiscovery(true, url);\n }\n if (options.waitForPublication === false) return status;\n const deadline = Date.now() + 15_000;\n while (Date.now() < deadline) {\n status = await options.computer.computer.discovery();\n if (status.enabled && status.sequence && status.publishedSequence === status.sequence) return status;\n if (status.error?.includes(\"enrollment\") || status.error?.includes(\"older revision\"))\n throw new Error(status.error);\n await delay(250, undefined, { signal: options.signal });\n }\n throw new Error(\n \"Address recovery is configured and will retry in the background. Run mindwire discovery status to check publication.\",\n );\n } finally {\n await lock?.close();\n }\n}\n\nexport async function disableAddressDiscovery(directory: string, computer: Mindwire, reconcile = false): Promise<ComputerDiscoveryStatus> {\n const lock = await acquireProcessLock(join(directory, \"discovery-setup.lock\"));\n try {\n const status = await computer.computer.discovery();\n const preference = await discoveryPreference(directory);\n if (reconcile && preference?.enabled === true) return status;\n await saveDiscoveryPreference(directory, { enabled: false, url: status.url ?? preference?.url });\n if (!status.enabled) return status;\n return await computer.computer.configureDiscovery(false);\n } finally { await lock?.close(); }\n}\n\n/** Runs once after startup and retries failed enrollment in the controller. A\n * healthy setup makes only a local status read: publication/renewal stays in Go.\n * Direct/VPN/custom connections never opt into a hosted directory implicitly. */\nexport async function reconcileAddressDiscovery(options: {\n directory: string; config: ComputerConfig; computer: Mindwire; signal?: AbortSignal;\n}): Promise<void> {\n const preference = await discoveryPreference(options.directory);\n const { discovery: status } = await options.computer.computer.info();\n const automatic = options.config.relay.kind === \"cloudflare\" && !options.config.relay.url;\n const enabled = preference?.enabled ?? (status?.enabled || automatic && !status?.url);\n if (!enabled) {\n if (preference?.enabled === false && status?.enabled) await disableAddressDiscovery(options.directory, options.computer, true);\n return;\n }\n if (!status) throw new Error(\"Update the Mindwire service to enable automatic reconnection.\");\n const url = directoryURL(preference?.url ?? process.env.MINDWIRE_DIRECTORY_URL ?? status.url ?? DIRECTORY_URL);\n if (status.enabled && status.url === url && !status.error?.includes(\"enrollment\")) return;\n await enableAddressDiscovery({ ...options, url, waitForPublication: false, reconcile: true,\n prompt: { print() {}, open() {}, question: async () => { throw new Error(\"Unexpected interactive setup.\"); },\n secret: async () => { throw new Error(\"Unexpected interactive setup.\"); } } });\n}\n\nexport function discoveryDescription(status: ComputerDiscoveryStatus | undefined): string {\n if (!status?.enabled) return \"Automatic address recovery is off. Enable it with mindwire discovery enable.\";\n if (status.error) return status.error;\n return status.sequence && status.publishedSequence === status.sequence\n ? \"Encrypted address recovery is on. Saved phones can find this computer when its tunnel address changes.\"\n : \"Publishing the computer's encrypted address…\";\n}\n","import { join } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport type { ComputerUpdate } from \"../computer.js\";\nimport type { Mindwire } from \"../client.js\";\nimport { computerClient, readJSON } from \"./lifecycle.js\";\nimport { versionAtLeast } from \"../version.js\";\n\ntype UpdateClient = Pick<Mindwire, \"health\" | \"computer\">;\nexport function activeUpdate(update: ComputerUpdate | undefined): update is ComputerUpdate {\n return !!update && [\"queued\", \"downloading\", \"waiting\", \"restarting\"].includes(update.status);\n}\n\n/** The daemon arbitrates requests. Join an earlier version before requesting the\n * next; promoting a request never creates a second download or bypasses its lease. */\nexport async function queueServiceUpdate(client: UpdateClient, version: string, force = false): Promise<ComputerUpdate> {\n for (let attempt = 0; ; attempt++) {\n const previous = await client.computer.updateStatus();\n if (activeUpdate(previous) && (!force || previous.force)) return previous;\n try {\n return await client.computer.requestUpdate(activeUpdate(previous) ? previous.version : version, { force });\n } catch (error) {\n if ((error as { status?: number }).status !== 409 || attempt >= 2) throw error;\n // Another caller won admission. Read the authoritative request and join it.\n }\n }\n}\n\nexport interface ServiceUpdateResult { version: string; complete: boolean; update?: ComputerUpdate }\n\n/** A CLI may close after queuing: the controller owns download/restart. Human\n * callers get a bounded result, including the exact older request being joined. */\nexport async function updateComputer(options: {\n directory: string; version: string; force?: boolean; allowDowngrade?: boolean;\n onProgress?: (update: ComputerUpdate) => void; signal?: AbortSignal; timeoutMs?: number;\n connect?: () => Promise<UpdateClient>;\n}):\nPromise<ServiceUpdateResult> {\n const version = options.version.replace(/^v/, \"\");\n if (!/^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?$/.test(version)) throw new Error(\"Enter a Mindwire release version, such as 0.1.38.\");\n const connect = options.connect ?? (() => computerClient(options.directory));\n const deadline = Date.now() + (options.timeoutMs ?? 120_000);\n let requested: ComputerUpdate | undefined, last = \"\";\n for (;;) {\n options.signal?.throwIfAborted();\n if (!requested) {\n const client = await connect();\n const installed = (await client.health()).version.replace(/^v/, \"\");\n if (installed === version || !options.allowDowngrade && versionAtLeast(installed, version))\n return { version: installed, complete: true };\n requested = await queueServiceUpdate(client, version, options.force);\n }\n // Progress survives the short API outage during restart. Only the daemon\n // accepts new requests; this read never changes or clears its status.\n const update = await readJSON<ComputerUpdate>(join(options.directory, \"computer-update.json\")) ?? requested;\n if (update.id !== requested.id) {\n // A concurrent update completed/advanced first. Recheck the live service.\n requested = undefined;\n } else {\n const key = `${update.id}:${update.status}`;\n if (last !== key) { last = key; options.onProgress?.(update); }\n if (update.status === \"failed\") throw new Error(update.error ?? \"The service update failed. Run mindwire inspect for details.\");\n if (update.status === \"complete\") {\n requested = undefined;\n if (Date.now() < deadline) continue;\n } else if (!options.force && update.status === \"waiting\") {\n return { version, complete: false, update };\n }\n }\n if (Date.now() >= deadline) return { version, complete: false, update };\n await delay(500, undefined, { signal: options.signal });\n }\n}\n\nexport function updateProgress(update: ComputerUpdate): string {\n const phase: Record<ComputerUpdate[\"status\"], string> = {\n idle: \"Ready\", queued: \"Queued\", downloading: \"Downloading verified release…\",\n waiting: \"Waiting for active work to finish\", restarting: \"Restarting service…\",\n complete: \"Installed\", failed: \"Update failed\",\n };\n return `${update.version} · ${phase[update.status]}`;\n}\n"]}
@@ -88,7 +88,7 @@ function computerPairingURI(invitation) {
88
88
  }
89
89
 
90
90
  // src/version.ts
91
- var SDK_VERSION = "0.1.47" ;
91
+ var SDK_VERSION = "0.1.48" ;
92
92
  function versionAtLeast(actual, desired) {
93
93
  if (actual === desired) return true;
94
94
  if (!actual || !/^\d+\.\d+\.\d+$/.test(actual) || !/^\d+\.\d+\.\d+$/.test(desired)) return false;
@@ -1694,17 +1694,135 @@ var TerminalsApi = class {
1694
1694
  }
1695
1695
  };
1696
1696
 
1697
+ // src/voice.ts
1698
+ var VoiceApi = class {
1699
+ constructor(client) {
1700
+ this.client = client;
1701
+ }
1702
+ client;
1703
+ status(scoped) {
1704
+ return this.client.http.request("GET", "/voice", {
1705
+ query: { agent: scoped?.agent ?? this.client.defaultAgent }
1706
+ });
1707
+ }
1708
+ /** Start in an idle chat. Keep requestId/clientId when retrying a lost receipt. */
1709
+ async start(input) {
1710
+ const clientId = input.clientId ?? crypto.randomUUID();
1711
+ const data = await this.client.http.request("POST", "/turns", {
1712
+ query: { agent: input.agent ?? this.client.defaultAgent },
1713
+ body: {
1714
+ chatId: input.chatId,
1715
+ message: "",
1716
+ cwd: input.cwd,
1717
+ gitAuth: input.gitAuth,
1718
+ requestId: input.requestId ?? crypto.randomUUID(),
1719
+ options: { voice: { clientId, voice: input.voice } }
1720
+ }
1721
+ });
1722
+ return new VoiceSession(this.client.http, new Run(this.client.http, data), clientId);
1723
+ }
1724
+ };
1725
+ var VoiceSession = class {
1726
+ constructor(http, run, clientId) {
1727
+ this.http = http;
1728
+ this.run = run;
1729
+ this.clientId = clientId;
1730
+ }
1731
+ http;
1732
+ run;
1733
+ clientId;
1734
+ sequence = 0;
1735
+ sending = false;
1736
+ ended = false;
1737
+ streaming = false;
1738
+ get path() {
1739
+ return `/runs/${encodeURIComponent(this.run.id)}/voice`;
1740
+ }
1741
+ /** Await each ordered batch. No automatic audio replay after a network failure. */
1742
+ async appendAudio(audio, signal) {
1743
+ if (this.ended || this.sending) throw new Error("Voice ended or the previous audio batch is still being delivered.");
1744
+ this.sending = true;
1745
+ try {
1746
+ await this.http.request("POST", this.path, { signal, body: {
1747
+ clientId: this.clientId,
1748
+ action: "audio",
1749
+ sequence: ++this.sequence,
1750
+ audio
1751
+ } });
1752
+ } catch (error) {
1753
+ await this.stop().catch(() => {
1754
+ });
1755
+ throw error;
1756
+ } finally {
1757
+ this.sending = false;
1758
+ }
1759
+ }
1760
+ /** Subscribe before sending audio; wait for ready. Breaking the loop ends voice. */
1761
+ async *stream(signal) {
1762
+ if (this.streaming || this.ended) throw new Error("This voice stream is already open or ended.");
1763
+ this.streaming = true;
1764
+ const controller = new AbortController();
1765
+ const abort = () => controller.abort(signal?.reason);
1766
+ signal?.addEventListener("abort", abort, { once: true });
1767
+ if (signal?.aborted) abort();
1768
+ let heartbeatPending = false;
1769
+ const heartbeat = setInterval(() => {
1770
+ if (heartbeatPending || controller.signal.aborted) return;
1771
+ heartbeatPending = true;
1772
+ void this.http.request("POST", this.path, {
1773
+ signal: controller.signal,
1774
+ body: { clientId: this.clientId, action: "heartbeat" }
1775
+ }).catch((error) => controller.abort(error)).finally(() => {
1776
+ heartbeatPending = false;
1777
+ });
1778
+ }, 5e3);
1779
+ try {
1780
+ const response = await this.http.open("GET", `${this.path}/stream`, {
1781
+ query: { clientId: this.clientId },
1782
+ signal: controller.signal
1783
+ });
1784
+ for await (const event of readSSE(response.body, controller.signal)) {
1785
+ if (event.type !== "heartbeat") yield event;
1786
+ if (event.type === "closed" || event.type === "error") break;
1787
+ }
1788
+ } finally {
1789
+ clearInterval(heartbeat);
1790
+ signal?.removeEventListener("abort", abort);
1791
+ controller.abort();
1792
+ this.streaming = false;
1793
+ await this.stop().catch(() => {
1794
+ });
1795
+ }
1796
+ }
1797
+ async stop() {
1798
+ if (this.ended) return;
1799
+ this.ended = true;
1800
+ await this.http.request("POST", this.path, { body: { clientId: this.clientId, action: "stop" } });
1801
+ }
1802
+ };
1803
+
1697
1804
  // src/embedded.ts
1698
1805
  var shared = /* @__PURE__ */ new Map();
1699
1806
  function configKey(opts) {
1700
- return JSON.stringify([opts.cwd ?? "", opts.statePath ?? "", opts.bin ?? ""]);
1807
+ const entries = (env) => env && Object.entries(env).sort(([a], [b]) => a.localeCompare(b));
1808
+ return JSON.stringify([
1809
+ opts.cwd ?? "",
1810
+ opts.statePath ?? "",
1811
+ opts.bin ?? "",
1812
+ opts.exactVersion,
1813
+ entries(opts.environment),
1814
+ opts.authSource === "host" ? ["host", entries(serverRuntime().process?.env)] : opts.authSource && [opts.authSource.home, opts.authSource.reuse ?? "automatic", entries(opts.authSource.environment)]
1815
+ ]);
1701
1816
  }
1702
1817
  function startEmbedded(opts = {}) {
1818
+ if (opts.shared === false) return spawnDaemon(opts);
1703
1819
  const key = configKey(opts);
1704
1820
  let daemon = shared.get(key);
1705
1821
  if (!daemon) {
1706
- daemon = spawnDaemon(opts).catch((err) => {
1707
- shared.delete(key);
1822
+ daemon = spawnDaemon(opts, () => {
1823
+ if (shared.get(key) === daemon) shared.delete(key);
1824
+ }).catch((err) => {
1825
+ if (shared.get(key) === daemon) shared.delete(key);
1708
1826
  throw err;
1709
1827
  });
1710
1828
  shared.set(key, daemon);
@@ -1718,7 +1836,8 @@ function isServerRuntime() {
1718
1836
  const g = serverRuntime();
1719
1837
  return typeof g.process !== "undefined" && !!g.process.versions?.node || typeof g.Bun !== "undefined" || typeof g.Deno !== "undefined";
1720
1838
  }
1721
- async function spawnDaemon(opts) {
1839
+ async function spawnDaemon(opts, onStop = () => {
1840
+ }) {
1722
1841
  if (!isServerRuntime()) {
1723
1842
  throw new MindwireError(
1724
1843
  "MindWire embedded mode needs a server runtime (Node/Bun/Deno). In the browser or an edge runtime, pass { baseUrl } to connect to a running daemon."
@@ -1728,40 +1847,78 @@ async function spawnDaemon(opts) {
1728
1847
  const net = await import('net');
1729
1848
  const proc = serverRuntime().process;
1730
1849
  const { randomBytes } = await import('crypto');
1731
- const resolved = await resolveBinary(opts.bin);
1850
+ const resolved = await resolveBinary(opts.bin, opts.exactVersion);
1732
1851
  const bin = resolved.bin;
1733
1852
  const port = await freePort(net);
1734
1853
  const baseUrl = `http://127.0.0.1:${port}`;
1735
1854
  const token = randomBytes(32).toString("hex");
1855
+ const authSource = opts.authSource === "host" ? { home: (await import('os')).homedir(), environment: proc.env } : opts.authSource;
1736
1856
  const child = spawn3(bin, [], {
1737
1857
  env: {
1738
- ...proc.env,
1858
+ ...opts.environment ?? proc.env,
1739
1859
  ADDR: `127.0.0.1:${port}`,
1740
1860
  AGENT_CWD: opts.cwd ?? proc.cwd(),
1741
1861
  STATE_PATH: opts.statePath ?? ".mindwire-state.json",
1742
- DAEMON_TOKEN: token
1862
+ DAEMON_TOKEN: token,
1863
+ // The daemon consumes and unsets this before starting any native process.
1864
+ ...authSource ? { MINDWIRE_AUTH_SOURCE: JSON.stringify(authSource) } : {}
1743
1865
  },
1866
+ cwd: opts.cwd ?? proc.cwd(),
1744
1867
  stdio: "ignore"
1745
1868
  });
1746
1869
  let spawnError = null;
1747
- child.on("error", (e) => {
1748
- spawnError = e;
1749
- });
1750
- const stop = () => {
1870
+ let exited = false;
1871
+ let stopping;
1872
+ const isAlive = () => !exited && !stopping && !spawnError;
1873
+ const killOnExit = () => {
1751
1874
  try {
1752
1875
  child.kill();
1753
1876
  } catch {
1754
1877
  }
1755
1878
  };
1756
- proc.once?.("exit", stop);
1757
- proc.once?.("SIGINT", () => {
1758
- stop();
1759
- proc.exit?.(130);
1879
+ const cleanup = () => {
1880
+ exited = true;
1881
+ proc.off?.("exit", killOnExit);
1882
+ onStop();
1883
+ };
1884
+ child.once("exit", cleanup);
1885
+ child.on("error", (e) => {
1886
+ spawnError = e;
1887
+ cleanup();
1760
1888
  });
1761
- await waitHealthy(baseUrl, token, () => spawnError, resolved);
1762
- return { baseUrl, token, stop };
1889
+ const stop = () => {
1890
+ return stopping ??= new Promise((resolve3) => {
1891
+ if (exited) {
1892
+ resolve3();
1893
+ return;
1894
+ }
1895
+ const timer = setTimeout(() => {
1896
+ try {
1897
+ child.kill("SIGKILL");
1898
+ } catch {
1899
+ }
1900
+ }, 2e3);
1901
+ child.once("exit", () => {
1902
+ clearTimeout(timer);
1903
+ resolve3();
1904
+ });
1905
+ child.once("error", () => {
1906
+ clearTimeout(timer);
1907
+ resolve3();
1908
+ });
1909
+ killOnExit();
1910
+ });
1911
+ };
1912
+ proc.once?.("exit", killOnExit);
1913
+ try {
1914
+ await waitHealthy(baseUrl, token, () => spawnError ?? (exited ? new Error("daemon exited during startup") : null), resolved, 15e3, !!authSource);
1915
+ return { baseUrl, token, isAlive, stop };
1916
+ } catch (error) {
1917
+ await stop();
1918
+ throw error;
1919
+ }
1763
1920
  }
1764
- async function resolveBinary(explicit) {
1921
+ async function resolveBinary(explicit, exactVersion) {
1765
1922
  const fs4 = await import('fs');
1766
1923
  const path5 = await import('path');
1767
1924
  const proc = serverRuntime().process;
@@ -1782,7 +1939,7 @@ async function resolveBinary(explicit) {
1782
1939
  } catch {
1783
1940
  }
1784
1941
  }
1785
- const downloaded = await ensureDaemonBinary({ platform: proc.platform, arch: proc.arch });
1942
+ const downloaded = await ensureDaemonBinary({ platform: proc.platform, arch: proc.arch, exactVersion });
1786
1943
  return { bin: downloaded, found: true, checked: [...candidates, downloaded] };
1787
1944
  }
1788
1945
  function daemonStartError(resolved, cause) {
@@ -1811,7 +1968,7 @@ function freePort(net) {
1811
1968
  });
1812
1969
  });
1813
1970
  }
1814
- async function waitHealthy(baseUrl, token, getError, resolved, timeoutMs = 15e3) {
1971
+ async function waitHealthy(baseUrl, token, getError, resolved, timeoutMs = 15e3, authSource = false) {
1815
1972
  const deadline = Date.now() + timeoutMs;
1816
1973
  while (Date.now() < deadline) {
1817
1974
  const err = getError();
@@ -1819,9 +1976,14 @@ async function waitHealthy(baseUrl, token, getError, resolved, timeoutMs = 15e3)
1819
1976
  throw new MindwireError(daemonStartError(resolved, err), { cause: err });
1820
1977
  }
1821
1978
  try {
1822
- const res = await fetch(`${baseUrl}/healthz`, { headers: { Authorization: `Bearer ${token}` } });
1823
- if (res.ok) return;
1824
- } catch {
1979
+ const res = await fetch(`${baseUrl}/healthz`, { headers: { Authorization: `Bearer ${token}` }, signal: AbortSignal.timeout(1e3) });
1980
+ if (res.ok) {
1981
+ if (authSource && (await res.json()).nativeAuthSource !== true)
1982
+ throw new MindwireError("This daemon does not support native auth sources. Update Mindwire or build the matching daemon before using authSource.");
1983
+ return;
1984
+ }
1985
+ } catch (error) {
1986
+ if (error instanceof MindwireError) throw error;
1825
1987
  }
1826
1988
  await new Promise((r) => setTimeout(r, 150));
1827
1989
  }
@@ -1837,17 +1999,27 @@ function emit(spec, e) {
1837
1999
  }
1838
2000
  }
1839
2001
  function local(opts = {}) {
2002
+ let daemon;
2003
+ let pending;
1840
2004
  return {
1841
2005
  name: "local",
2006
+ profileVersion: 1,
1842
2007
  async connect(spec) {
1843
- const d = await startEmbedded(opts);
2008
+ if (daemon && !daemon.isAlive()) {
2009
+ daemon = void 0;
2010
+ pending = void 0;
2011
+ }
2012
+ const d = await (pending ??= startEmbedded(opts).then((value) => daemon = value).catch((error) => {
2013
+ pending = void 0;
2014
+ throw error;
2015
+ }));
1844
2016
  emit(spec, { target: "local", phase: "ready", message: `embedded daemon on ${d.baseUrl}` });
1845
2017
  return {
1846
2018
  id: d.baseUrl,
1847
2019
  baseUrl: d.baseUrl,
1848
2020
  ...d.token !== void 0 ? { token: d.token } : {},
1849
- // No-op: the embedded daemon is shared (keyed memoization) and reaped on process exit.
1850
- stop: async () => {
2021
+ isAlive: d.isAlive,
2022
+ stop: opts.shared === false ? d.stop : async () => {
1851
2023
  }
1852
2024
  };
1853
2025
  }
@@ -1880,6 +2052,7 @@ var Mindwire = class _Mindwire {
1880
2052
  service;
1881
2053
  execution;
1882
2054
  computer;
2055
+ voice;
1883
2056
  http;
1884
2057
  /** The default agent type applied to agent-scoped calls, if set. */
1885
2058
  defaultAgent;
@@ -1918,6 +2091,7 @@ var Mindwire = class _Mindwire {
1918
2091
  this.service = new ServiceApi(this);
1919
2092
  this.execution = new ExecutionApi(this);
1920
2093
  this.computer = new ComputerApi(this);
2094
+ this.voice = new VoiceApi(this);
1921
2095
  this.auth = new AuthApi(this);
1922
2096
  this.prompts = new PromptsApi(this);
1923
2097
  this.mcp = new McpApi(this);
@@ -1943,6 +2117,7 @@ var Mindwire = class _Mindwire {
1943
2117
  clone.service = new ServiceApi(clone);
1944
2118
  clone.execution = new ExecutionApi(clone);
1945
2119
  clone.computer = new ComputerApi(clone);
2120
+ clone.voice = new VoiceApi(clone);
1946
2121
  clone.auth = new AuthApi(clone);
1947
2122
  clone.prompts = new PromptsApi(clone);
1948
2123
  clone.mcp = new McpApi(clone);
@@ -1959,8 +2134,8 @@ var Mindwire = class _Mindwire {
1959
2134
  * Release target-owned resources by calling the {@link TargetHandle}'s `stop()` — once, even across
1960
2135
  * {@link withAgent} clones that share the transport. For an `ssh`/`docker`/`oblien` target this reaps
1961
2136
  * the box (tear down the tunnel, stop or delete the container/workspace, per `stopOnExit`); a no-op
1962
- * for `local`/`remote` (embedded self-cleans on process exit; remote is not ours to stop). Safe to
1963
- * call before the target has connected (nothing to reap yet).
2137
+ * for shared local and remote targets. With `local({ shared: false })`, closes the owned daemon.
2138
+ * Safe to call before the target has connected (nothing to reap yet).
1964
2139
  */
1965
2140
  async close() {
1966
2141
  const handle = handleByTransport.get(this.http);
@@ -2005,6 +2180,12 @@ var Mindwire = class _Mindwire {
2005
2180
  models(scoped) {
2006
2181
  return this.http.request("GET", "/models", { query: this.agentParam(scoped) });
2007
2182
  }
2183
+ /** Discover native commands for a project without starting a model turn. */
2184
+ commands(opts = {}) {
2185
+ return this.http.request("GET", "/commands", {
2186
+ query: { ...this.agentParam(opts), dir: opts.directory, refresh: opts.refresh }
2187
+ });
2188
+ }
2008
2189
  /** `GET /doctor` — daemon-level health plus the selected agent's own checks. */
2009
2190
  doctor(scoped) {
2010
2191
  return this.http.request("GET", "/doctor", { query: this.agentParam(scoped) });
@@ -2142,7 +2323,8 @@ var Mindwire = class _Mindwire {
2142
2323
  limit,
2143
2324
  before: opts.before,
2144
2325
  paged: "true",
2145
- maxBytes: opts.maxBytes ?? 1048576
2326
+ maxBytes: opts.maxBytes ?? 1048576,
2327
+ ifRevision: opts.before ? void 0 : opts.ifRevision
2146
2328
  }
2147
2329
  }
2148
2330
  );
@@ -2221,7 +2403,7 @@ var Mindwire = class _Mindwire {
2221
2403
  `/chats/${encodeURIComponent(chatId)}/compact`,
2222
2404
  {
2223
2405
  query: this.agentParam(opts),
2224
- body: opts.instructions ? { instructions: opts.instructions } : {}
2406
+ body: { instructions: opts.instructions, requestId: opts.requestId }
2225
2407
  }
2226
2408
  );
2227
2409
  return new Run(this.http, data);
@@ -2647,7 +2829,7 @@ async function ensureComputer(directory, cliPath, patch = {}, onProgress, option
2647
2829
  if (!compatible(controller2) || !await processStateAlive(controller2)) {
2648
2830
  await ensureComputer(directory, cliPath, {}, onProgress, { ...options, waitForRoutes: false });
2649
2831
  }
2650
- const { changeComputerConnection } = await import('./connection-change-LCT3UM7M.js');
2832
+ const { changeComputerConnection } = await import('./connection-change-4FVOAA4K.js');
2651
2833
  await changeComputerConnection(directory, Object.fromEntries(changed.map((key) => [key, patch[key]])), { signal: options.signal, onProgress });
2652
2834
  return computerClient(directory);
2653
2835
  }
@@ -2688,7 +2870,7 @@ async function ensureComputer(directory, cliPath, patch = {}, onProgress, option
2688
2870
  let controller = await readJSON(path4.join(directory, "computer-controller.json"));
2689
2871
  if (existing && controller && !compatible(controller) && await processStateAlive(controller)) {
2690
2872
  onProgress?.("Refreshing the background connection service\u2026");
2691
- const { handoffController } = await import('./controller-handoff-RPZJDZJR.js');
2873
+ const { handoffController } = await import('./controller-handoff-IDV2S7DI.js');
2692
2874
  await handoffController(directory, controller, config, await existing.computer.info());
2693
2875
  controller = void 0;
2694
2876
  }
@@ -2722,7 +2904,7 @@ async function ensureComputer(directory, cliPath, patch = {}, onProgress, option
2722
2904
  }
2723
2905
  }
2724
2906
  async function superviseComputer(directory) {
2725
- const controller = await import('./controller-I7A3APTF.js');
2907
+ const controller = await import('./controller-NYTBXYAN.js');
2726
2908
  await controller.superviseComputer(directory);
2727
2909
  }
2728
2910
  async function stopComputer(directory, force = false) {
@@ -2747,5 +2929,5 @@ async function stopComputer(directory, force = false) {
2747
2929
  }
2748
2930
 
2749
2931
  export { CONTROLLER_PROTOCOL, ProviderConnectionError, RelayOutput, SDK_VERSION, acquireProcessLock, adoptProcess, adoptRelay, cloudflareCommand, computerClient, computerPairingQRData, computerPairingURI, currentProcessIdentity, defaultComputerConfig, defaultStateDirectory, directRoutes, ensureComputer, ensureDaemonBinary, hasCertificateError, ownChild, processIdentity, processStateAlive, providerFailure, providerNeedsAction, readJSON, startRelay, stopComputer, superviseComputer, versionAtLeast, websocketURL, writeJSON };
2750
- //# sourceMappingURL=chunk-7QLYFISG.js.map
2751
- //# sourceMappingURL=chunk-7QLYFISG.js.map
2932
+ //# sourceMappingURL=chunk-PCBZ5RU5.js.map
2933
+ //# sourceMappingURL=chunk-PCBZ5RU5.js.map