zidane 9.0.1 → 9.0.2
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/dist/{auto-update-restart-Di-QOmbc.js → auto-update-restart-B1ukz5-_.js} +2 -2
- package/dist/{auto-update-restart-Di-QOmbc.js.map → auto-update-restart-B1ukz5-_.js.map} +1 -1
- package/dist/chat.js +3 -3
- package/dist/daemon-cli.js +2 -2
- package/dist/{engine-gnOWE8_z.js → engine-C_v7ggaM.js} +2 -2
- package/dist/{engine-gnOWE8_z.js.map → engine-C_v7ggaM.js.map} +1 -1
- package/dist/{executor-D8qIXJK9.js → executor-Bopn2Uvo.js} +2 -2
- package/dist/{executor-D8qIXJK9.js.map → executor-Bopn2Uvo.js.map} +1 -1
- package/dist/{extensions-BlizVmBJ.js → extensions-4D_tk7i-.js} +2 -2
- package/dist/{extensions-BlizVmBJ.js.map → extensions-4D_tk7i-.js.map} +1 -1
- package/dist/extensions.js +1 -1
- package/dist/{host-signals-Bod6f9lW.js → host-signals-DN6nZ4zd.js} +5 -5
- package/dist/{host-signals-Bod6f9lW.js.map → host-signals-DN6nZ4zd.js.map} +1 -1
- package/dist/index.js +1 -1
- package/dist/ipc/remote.js +3 -3
- package/dist/{ipc-CxU525LK.js → ipc-BdazyU1h.js} +4 -4
- package/dist/{ipc-CxU525LK.js.map → ipc-BdazyU1h.js.map} +1 -1
- package/dist/ipc.js +4 -4
- package/dist/{links-vCRfuwcf.js → links-Mt4r43nD.js} +6 -6
- package/dist/{links-vCRfuwcf.js.map → links-Mt4r43nD.js.map} +1 -1
- package/dist/{memory-D_IXaDph.js → memory-Dj9Eeybi.js} +7 -7
- package/dist/{memory-D_IXaDph.js.map → memory-Dj9Eeybi.js.map} +1 -1
- package/dist/{path-display-DKLe4XMx.js → path-display-BKAU3XtR.js} +3 -3
- package/dist/{path-display-DKLe4XMx.js.map → path-display-BKAU3XtR.js.map} +1 -1
- package/dist/{remote-hosts-CrWY_6M4.js → remote-hosts-Ep4bgs3F.js} +4 -4
- package/dist/{remote-hosts-CrWY_6M4.js.map → remote-hosts-Ep4bgs3F.js.map} +1 -1
- package/dist/{settings-keys-D17NBeft.js → settings-keys-CEmlwy2H.js} +2 -2
- package/dist/{settings-keys-D17NBeft.js.map → settings-keys-CEmlwy2H.js.map} +1 -1
- package/dist/tui.js +8 -8
- package/dist/{version-4D2cCm14.js → version-DzI0HMrv.js} +2 -2
- package/dist/{version-4D2cCm14.js.map → version-DzI0HMrv.js.map} +1 -1
- package/dist/{ws-B5dFRL2T.js → ws-Bv6QGsEr.js} +3 -3
- package/dist/{ws-B5dFRL2T.js.map → ws-Bv6QGsEr.js.map} +1 -1
- package/dist/{ws-client-KorHNu6H.js → ws-client-BWiyy8Op.js} +2 -2
- package/dist/{ws-client-KorHNu6H.js.map → ws-client-BWiyy8Op.js.map} +1 -1
- package/package.json +3 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-D_IXaDph.js","names":["MAX_KEY_LENGTH","DEFAULT_TIMEOUT_MS","NAME_RE","process","isRecord","isRecord","isRecord","process"],"sources":["../src/ipc/transports/paced-writer.ts","../src/ipc/client.ts","../src/ipc/daemon/watch-file.ts","../src/ipc/daemon/environment.ts","../src/ipc/daemon/handlers/machine-links.ts","../src/ipc/daemon/handlers/machines.ts","../src/ipc/transports/peer-rpc.ts","../src/ipc/transports/send-budget.ts","../src/ipc/history/rpc-client.ts","../src/ipc/history/transcript.ts","../src/ipc/daemon/redact.ts","../src/ipc/daemon/catalog-entries.ts","../src/ipc/daemon/handlers/catalogs.ts","../src/ipc/daemon/handlers/artifacts.ts","../src/ipc/daemon/handlers/auth.ts","../src/ipc/daemon/handlers/browser.ts","../src/ipc/daemon/handlers/catalog-install.ts","../src/text-origin.ts","../src/ipc/daemon/send-requests.ts","../src/ipc/daemon/handlers/chat.ts","../src/ipc/daemon/handlers/client-state.ts","../src/ipc/daemon/handlers/context.ts","../src/ipc/daemon/handlers/daemon.ts","../src/ipc/daemon/handlers/drafts.ts","../src/ipc/daemon/handlers/environments.ts","../src/ipc/daemon/handlers/extension-ui.ts","../src/ipc/daemon/handlers/extensions.ts","../src/ipc/daemon/handlers/files.ts","../src/ipc/daemon/handlers/fs.ts","../src/ipc/daemon/handlers/session-policy.ts","../src/ipc/daemon/handlers/sessions.ts","../src/ipc/daemon/handlers/git.ts","../src/ipc/daemon/handlers/history.ts","../src/ipc/daemon/handlers/hitl.ts","../src/ipc/daemon/handlers/launch-overrides.ts","../src/ipc/daemon/handlers/machine-serve.ts","../src/ipc/daemon/handlers/oauth-flows.ts","../src/ipc/daemon/handlers/onboarding.ts","../src/ipc/daemon/handlers/orchestration.ts","../src/ipc/daemon/handlers/panels.ts","../src/ipc/daemon/handlers/perf.ts","../src/ipc/daemon/integrations.ts","../src/ipc/daemon/handlers/integrations.ts","../src/ipc/daemon/handlers/presence.ts","../src/ipc/daemon/handlers/queue.ts","../src/ipc/daemon/handlers/resume.ts","../src/ipc/daemon/handlers/logs.ts","../src/ipc/daemon/handlers/server.ts","../src/ipc/daemon/handlers/session-reads.ts","../src/ipc/daemon/handlers/settings.ts","../src/ipc/daemon/handlers/suggest.ts","../src/ipc/daemon/sync-apply.ts","../src/ipc/daemon/sync-store.ts","../src/ipc/daemon/handlers/sync.ts","../src/ipc/daemon/handlers/terminal.ts","../src/ipc/daemon/handlers/titles.ts","../src/ipc/daemon/handlers/todos.ts","../src/ipc/daemon/handlers/transcript.ts","../src/ipc/daemon/handlers/usage.ts","../src/ipc/daemon/handlers/workspace.ts","../src/ipc/daemon/handlers/workspace-exec-stream.ts","../src/ipc/daemon/handshake.ts","../src/ipc/daemon/identity.ts","../src/ipc/daemon/peers.ts","../src/ipc/daemon/principal-work.ts","../src/ipc/daemon/signal-log.ts","../src/ipc/daemon/workspace-roots.ts","../src/ipc/daemon/dispatcher.ts","../src/ipc/daemon/update-retire.ts","../src/ipc/daemon/server.ts","../src/ipc/daemon/shell-path.ts","../src/ipc/memory.ts"],"sourcesContent":["/**\n * Writes to a socket with backpressure: slices go out while the socket takes\n * them (`write` returns true), the rest waits for `drain`. Messages keep\n * their order, and `buffered` counts what is queued here plus what the\n * socket still holds, so a send budget measuring it sees the whole backlog.\n *\n * Handing a socket one large buffer at once is what this avoids: Bun's\n * `node:net` re-copies the unsent remainder after each partial write, so a\n * 100 MB reply took ~12 s to cross a unix socket, against ~70 ms when paced\n * (Node is fast either way).\n *\n * Small messages written in one go (a fan-out, a reply behind its signals)\n * are joined and handed over as one buffer, from a microtask (so before any\n * I/O), as soon as the socket asks for more, or once they add up to a slice:\n * one encode and one socket write instead of one per message. A large message is not joined: it goes\n * out in slices, after what was written before it.\n */\nimport type { Writable } from 'node:stream'\nimport { Buffer } from 'node:buffer'\n\n/** Largest slice handed to the socket at once. */\nconst SLICE_BYTES = 64 * 1024\n\nexport interface PacedWriter {\n write: (text: string) => void\n /** Bytes not yet handed to the OS: queued here, plus the socket's own buffer. */\n buffered: () => number\n}\n\nexport function createPacedWriter(stream: Writable): PacedWriter {\n const queue: Buffer[] = []\n let queuedBytes = 0\n let waiting = false\n /** Small messages not yet encoded, joined on their way into `queue`. */\n let pending: string[] = []\n let pendingBytes = 0\n let armed = false\n\n const takePending = (): void => {\n if (pending.length === 0)\n return\n const bytes = Buffer.from(pending.length === 1 ? pending[0]! : pending.join(''))\n pending = []\n pendingBytes = 0\n queue.push(bytes)\n queuedBytes += bytes.length\n }\n\n const pump = (): void => {\n waiting = false\n takePending()\n while (queue.length > 0) {\n if (stream.destroyed || stream.writableEnded) {\n queue.length = 0\n queuedBytes = 0\n return\n }\n const head = queue[0]!\n const slice = head.length > SLICE_BYTES ? head.subarray(0, SLICE_BYTES) : head\n if (slice === head)\n queue.shift()\n else\n queue[0] = head.subarray(SLICE_BYTES)\n queuedBytes -= slice.length\n if (!stream.write(slice)) {\n waiting = true\n stream.once('drain', pump)\n return\n }\n }\n }\n\n return {\n write(text) {\n if (text.length >= SLICE_BYTES) {\n takePending()\n const bytes = Buffer.from(text)\n queue.push(bytes)\n queuedBytes += bytes.length\n if (!waiting)\n pump()\n return\n }\n pending.push(text)\n pendingBytes += Buffer.byteLength(text)\n // While the socket is full, `drain` takes them.\n if (waiting)\n return\n if (pendingBytes >= SLICE_BYTES) {\n pump()\n return\n }\n if (armed)\n return\n armed = true\n queueMicrotask(() => {\n armed = false\n if (!waiting)\n pump()\n })\n },\n buffered: () => pendingBytes + queuedBytes + stream.writableLength,\n }\n}\n","/**\n * Typed daemon client — the only thing a zidane window (TUI, attach CLI,\n * GUI main process) needs to talk to a shared chat host.\n *\n * `request` is checked against the `IpcMethods` contract, `onSignal`\n * delivers every `HostSignal` fan-out, and `connectIpcClient` handles the\n * handshake including the protocol-version dance: a mismatched daemon is\n * asked to drain (`daemon.shutdown`) so the caller can respawn a fresh one.\n * The transport-independent half (handshake, deadlines, signals) is shared\n * with the WebSocket client in `./transports/client-core`.\n */\nimport type { Socket } from 'node:net'\nimport type { EnsureDaemonOptions } from './daemon/lifecycle'\nimport type { IpcClient } from './transports/client-core'\nimport { connect } from 'node:net'\nimport { createJsonRpcConnection, errorResponse } from '../acp/json-rpc'\nimport { METHOD_NOT_FOUND } from '../chat/hosts/connection'\nimport { ensureDaemonRunning, probeSocket } from './daemon/lifecycle'\nimport { createSignalListeners, IpcVersionMismatchError, openIpcClient } from './transports/client-core'\nimport { createPacedWriter } from './transports/paced-writer'\n\nexport { type IpcClient, IpcVersionMismatchError } from './transports/client-core'\n\n/** Options for {@link connectIpcClient}. */\nexport interface IpcClientOptions {\n /** Path of the daemon's unix socket. */\n socketPath: string\n /** Client zidane version, surfaced in daemon diagnostics. */\n appVersion?: string\n /** Called when the daemon connection drops (socket close/error). */\n onClose?: () => void\n /**\n * On a version/build mismatch, ask the stale daemon to drain before\n * throwing (default). PASSIVE clients (the presence watcher) must set\n * this false: they retry on a timer, and an old-build window left open\n * across a protocol bump would otherwise drain the NEW daemon in a\n * loop, aborting every other window's runs.\n */\n drainOnMismatch?: boolean\n}\n\n/**\n * Connects to a daemon over its unix socket and completes the `ipc.hello` handshake.\n * On a protocol, build or code version mismatch it throws {@link IpcVersionMismatchError}. Unless `drainOnMismatch` is `false`, it first asks the stale daemon to drain. Rejects when nothing listens on the socket.\n * @param options - Socket path and client settings.\n * @returns A typed client. Requests are checked against {@link IpcMethods}.\n * @example\n * ```ts\n * import { connectIpcClient, defaultSocketPath } from 'zidane/ipc'\n *\n * const client = await connectIpcClient({ socketPath: defaultSocketPath() })\n * const sessions = await client.request('sessions.list', {})\n * const stop = client.onSignal(signal => console.log(signal.kind))\n * console.log(sessions.length)\n * stop()\n * client.close()\n * ```\n */\nexport async function connectIpcClient(options: IpcClientOptions): Promise<IpcClient> {\n const socket: Socket = await new Promise((resolvePromise, reject) => {\n const s = connect(options.socketPath)\n s.once('connect', () => {\n s.off('error', reject)\n resolvePromise(s)\n })\n s.once('error', reject)\n })\n\n const signals = createSignalListeners()\n let closed = false\n\n // A large request (turns with images) goes out paced, as the daemon's replies do.\n const writer = createPacedWriter(socket)\n const connection = createJsonRpcConnection({\n input: socket,\n output: socket,\n send: json => writer.write(`${json}\\n`),\n // The daemon never sends requests to clients — only notifications.\n onRequest: message => errorResponse(message.id, METHOD_NOT_FOUND, 'Clients do not accept requests.'),\n onNotification: signals.onNotification,\n })\n connection.start()\n\n const close = (): void => {\n if (closed)\n return\n closed = true\n connection.close()\n socket.destroy()\n }\n\n socket.on('close', () => {\n if (closed)\n return\n closed = true\n connection.close()\n options.onClose?.()\n })\n socket.on('error', () => {\n // 'close' follows; swallow so an unhandled 'error' doesn't crash us.\n })\n\n const passive = options.drainOnMismatch === false\n return openIpcClient(\n // `abort` destroys the socket (not `close()`), so its 'close' handler fires `onClose`.\n { rpc: connection, close, abort: () => socket.destroy(), where: options.socketPath },\n signals.listeners,\n {\n ...(options.appVersion ? { appVersion: options.appVersion } : {}),\n drain: passive ? 'stale-only' : 'always',\n buildFence: !passive,\n },\n )\n}\n\n/**\n * One-call convenience for windows: make sure a daemon is up (spawning if\n * needed), connect, and — when the running daemon speaks an older protocol\n * — drain it and spawn a fresh one before retrying once.\n * @param options - Client options without `socketPath`, plus the daemon spawn options.\n * @returns A connected client.\n */\nexport async function connectOrSpawnDaemon(\n options: Omit<IpcClientOptions, 'socketPath'> & EnsureDaemonOptions = {},\n): Promise<IpcClient> {\n const socketPath = await ensureDaemonRunning(options)\n try {\n return await connectIpcClient({ ...options, socketPath })\n }\n catch (err) {\n if (!(err instanceof IpcVersionMismatchError))\n throw err\n /*\n * The stale daemon was told to drain by `connectIpcClient`, but\n * `daemon.shutdown` replies BEFORE the socket actually closes (the\n * drain runs on `setImmediate`). Poll until the socket stops\n * accepting connections (bounded) before respawning, so\n * `ensureDaemonRunning` doesn't re-probe the still-listening stale\n * daemon and hit a second mismatch.\n */\n const drainDeadline = Date.now() + 2000\n while (await probeSocket(socketPath)) {\n if (Date.now() > drainDeadline)\n break\n await new Promise(r => setTimeout(r, 100))\n }\n const retryPath = await ensureDaemonRunning(options)\n return connectIpcClient({ ...options, socketPath: retryPath })\n }\n}\n","/**\n * Notice when another process rewrites a file (the settings in `state.json`):\n * a watch on the file, followed to each new file a writer swaps in (writers\n * replace it atomically), plus a slow poll for file systems that send no\n * events. Both compare its modification time and size, so a burst of events\n * from one write calls back once.\n */\n\nimport { statSync, watch } from 'node:fs'\n\n/** Coalesces the events one write produces. */\nconst DEBOUNCE_MS = 100\n/** The fallback poll, when file events are missed. */\nconst POLL_MS = 2_000\n\nfunction stampOf(file: string): string {\n try {\n const stats = statSync(file)\n return `${stats.mtimeMs}:${stats.size}`\n }\n catch {\n return 'missing'\n }\n}\n\n/**\n * Call `onChange` after `file` changes. Returns the function that stops watching.\n *\n * @param file - The file to watch.\n * @param onChange - Called once per change, after its events settle.\n * @param options - Options.\n * @param options.pollMs - The fallback poll interval. Default 2 s.\n * @param options.watch - The file watch: `node:fs`'s by default; tests pass their own.\n */\nexport function watchFileChanges(file: string, onChange: () => void, options: { pollMs?: number, watch?: typeof watch } = {}): () => void {\n let stamp = stampOf(file)\n let pending: ReturnType<typeof setTimeout> | undefined\n let watcher: ReturnType<typeof watch> | undefined\n let stopped = false\n\n const check = (): void => {\n pending = undefined\n const now = stampOf(file)\n if (now === stamp)\n return\n stamp = now\n onChange()\n }\n // One check after a burst of events settles.\n const onEvent = (): void => {\n clearTimeout(pending)\n pending = setTimeout(check, DEBOUNCE_MS)\n pending.unref?.()\n }\n const arm = (): void => {\n watcher?.close()\n watcher = undefined\n if (stopped)\n return\n try {\n watcher = (options.watch ?? watch)(file, (event) => {\n onEvent()\n // The file was replaced: the watch still follows the old one.\n if (event === 'rename')\n arm()\n })\n watcher.on('error', () => undefined)\n watcher.unref()\n }\n catch {\n // No file yet: the poll watches it once it exists.\n }\n }\n\n arm()\n // Leaves a burst to its debounced check.\n const poll = setInterval(() => {\n if (watcher === undefined)\n arm()\n if (pending === undefined)\n check()\n }, options.pollMs ?? POLL_MS)\n poll.unref?.()\n return () => {\n stopped = true\n clearTimeout(pending)\n clearInterval(poll)\n watcher?.close()\n watcher = undefined\n }\n}\n","import type { ChatHostEnvironment, PendingApprovalsStore } from '../../chat/host/environment'\n/**\n * Disk-backed `ChatHostEnvironment` for the zidane daemon.\n *\n * Mirrors the TUI's storage layout so the daemon is a drop-in peer of the\n * terminal process: sessions in `sessions.db` (canonical sqlite store),\n * settings in `state.json`'s `settings` slot, credentials/safelist under the\n * shared user dir, extensions discovered per-cwd with the same allowlist +\n * trust contract every other surface uses.\n */\nimport type { ResolvedConfig } from '../../chat/index'\nimport type { ExtensionBus, ExtensionHostRuntimeBridge } from '../../extensions/index'\nimport type { LogSink } from '../../logger'\nimport type { SessionStore } from '../../session/index'\nimport type { HostSettings, HostSignal, HudState, WireApprovalRequest } from '../protocol'\nimport { existsSync, readFileSync, unlinkSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { OWNER_ONLY, writeJsonFileAtomic } from '../../atomic-write'\nimport { resolveConfig } from '../../chat/config'\nimport { applyApiKeyEnv, credentialsPath } from '../../chat/credentials'\nimport { createExtensionMcpHost } from '../../chat/extension-mcp-host'\nimport { createMemoryApprovalsStore } from '../../chat/host/approvals'\nimport { createFileMcpCredentialStore } from '../../chat/mcp-credentials'\nimport { BUILTIN_PROVIDERS } from '../../chat/providers'\nimport { enforceSettingsInvariants, SETTINGS_TOGGLES } from '../../chat/settings-catalog'\nimport { DEFAULT_SETTINGS, settingsFromStored, sparseSettingsUpdate } from '../../chat/settings-defaults'\nimport { createExtensionBus, createExtensionHostRuntimeBridge, createExtensionHud, discoverAndBuildExtensionRegistry } from '../../extensions/index'\nimport { consoleSink, createLogger, fanoutSink } from '../../logger'\nimport { watchFileChanges } from './watch-file'\n\n/** The host environment of a daemon or an embedded host: a {@link ChatHostEnvironment} backed by disk, with settings writes and runtime-config control. */\nexport interface DaemonEnvironment extends ChatHostEnvironment {\n /** Merges a patch into the stored settings, drops the `reset` keys it doesn't set, and returns the settings in effect afterwards. */\n writeSettings: (patch: Partial<HostSettings>, reset?: readonly (keyof HostSettings)[]) => HostSettings\n /** The extensions' HUD now, as `hud:state` pushes it (`hud.get`). Absent: an environment without a HUD of its own. */\n hudState?: () => HudState\n /** Drop the per-cwd runtime-config memo (settings changed) and dispose the registries it held. */\n invalidateRuntime: () => void\n /**\n * Drop the memo WITHOUT disposing: the next `runtimeConfig` builds fresh\n * registries while agents still running on the old ones keep working.\n * Returns the disposer for what was dropped; call it once no agent\n * holds those registries (`runtime.reload` after every session rebuilt).\n */\n forgetRuntime: () => () => void\n /** Base config resolved at daemon boot (paths, store, state). */\n config: ResolvedConfig\n /** The config `runtimeConfig(cwd)` already built or is building, without building one. Absent: never known. */\n peekRuntimeConfig?: (cwd: string) => Promise<ResolvedConfig> | undefined\n /**\n * Calls `onChange` after the settings file changes, whoever wrote it (another\n * daemon or window on the same `state.json`). Returns the function that stops\n * watching. Absent when the settings live in no file.\n */\n watchSettings?: (onChange: () => void) => () => void\n /**\n * Shared extension bus for daemon-side registries (`ctx.bus`). The\n * server delivers validated `extension.emit` notifications into it;\n * daemon-side emits leave through its `onEmit` → `broadcast`. Optional:\n * test environments without extensions omit it.\n */\n extensionBus?: ExtensionBus\n}\n\n/**\n * File-backed pending-approvals persistence (`pending-approvals.json` next\n * to `state.json`). Small, rewritten atomically enough for its purpose —\n * the queue holds at most a handful of rows.\n * @param path - Path of the JSON file. A missing or unreadable file reads as empty.\n * @returns A store that persists approvals to that file.\n */\nexport function createFileApprovalsStore(path: string): PendingApprovalsStore {\n function read(): WireApprovalRequest[] {\n if (!existsSync(path))\n return []\n try {\n const parsed = JSON.parse(readFileSync(path, 'utf8'))\n return Array.isArray(parsed) ? (parsed as WireApprovalRequest[]) : []\n }\n catch {\n return []\n }\n }\n\n function write(rows: WireApprovalRequest[]): void {\n if (rows.length === 0) {\n try {\n unlinkSync(path)\n }\n catch {\n // absent already — fine\n }\n return\n }\n // Atomic: this file exists to survive a crash — a torn write would\n // corrupt the very queue we're persisting to recover. Owner-only: rows\n // carry tool inputs (commands, file contents).\n writeJsonFileAtomic(path, rows, OWNER_ONLY)\n }\n\n return {\n insert(request) {\n const rows = read().filter(r => r.id !== request.id)\n rows.push(request)\n write(rows)\n },\n delete(id) {\n write(read().filter(r => r.id !== id))\n },\n clear() {\n write([])\n },\n list() {\n return read()\n },\n }\n}\n\n/** Options for {@link createHostEnvironment}. */\nexport interface HostEnvironmentOptions {\n /** Sink that fans a signal out to every connected client. */\n broadcast: (signal: HostSignal) => void\n /** Turns on verbose stream logging to the host console. */\n debugStream?: boolean\n /** Also receives its extensions' setup and runtime log records (stderr gets the warnings either way). */\n logSink?: LogSink\n /** Daemon only: base cwd for its own boot-time config resolution. Default: `process.cwd()`. */\n cwd?: string\n /**\n * Share the embedding window's setup instead of resolving the daemon's\n * own: a host in the window's process. Absent: the daemon (own config,\n * per-cwd extension discovery, multi-process).\n */\n shared?: SharedHostSetup\n}\n\n/** What a host in the window's own process takes from the window. */\nexport interface SharedHostSetup {\n /**\n * The window's boot config (paths, store, state file): one store and one\n * writer to `state.json` in the process.\n */\n config: ResolvedConfig\n /**\n * The window's per-cwd session config. Discovering extensions here instead\n * would run every extension's `setup` a second time in the same process.\n * `invalidate` / `forget` back `DaemonEnvironment.invalidateRuntime` /\n * `forgetRuntime` (settings changes, `runtime.reload`).\n */\n runtimeConfig: {\n resolve: (cwd: string) => Promise<ResolvedConfig>\n invalidate?: () => void\n forget?: () => () => void\n }\n /** Host-runtime bridge the window's registries were built with (`ChatHostEnvironment.hostRuntime`). */\n hostRuntime?: ExtensionHostRuntimeBridge\n /** The window's extension bus, so `extension.emit` from other clients reaches its extensions. */\n extensionBus?: ExtensionBus\n /** Whether another process also drives these sessions. Default `false` (single writer). */\n multiProcess?: boolean\n /** The window's instrumentation for every agent the host builds (`ChatHostEnvironment.instrumentAgent`). */\n instrumentAgent?: ChatHostEnvironment['instrumentAgent']\n /** Whether the window can show terminals (`ChatHostEnvironment.terminals`). */\n terminals?: boolean\n}\n\n/**\n * The daemon's environment: its own config, per-cwd extension discovery, multi-process.\n * @param options - Broadcast sink and boot settings. `shared` is not accepted.\n * @returns The environment.\n */\nexport function createDaemonEnvironment(options: Omit<HostEnvironmentOptions, 'shared'>): Promise<DaemonEnvironment> {\n return createHostEnvironment(options)\n}\n\n/**\n * Disk-backed host environment: the daemon's, or (with `shared`) a host\n * sharing the window's process and setup.\n * @param options - Broadcast sink, boot settings and the optional shared window setup.\n * @returns The environment.\n */\nexport async function createHostEnvironment(options: HostEnvironmentOptions): Promise<DaemonEnvironment> {\n const { shared } = options\n const config = shared?.config ?? await resolveOwnConfig(options.cwd)\n const store: SessionStore = config.store\n\n /*\n * Project-DB mode resolves storage to a PER-REPO `.zidane/sessions.db`\n * from the boot cwd. A single daemon serving windows opened in different\n * projects would then read/write every session against ONE project's DB.\n * The daemon is a single-store process, so warn loudly rather than\n * silently mixing projects; a project-scoped daemon (own socket) is the\n * supported way to use project-DB mode with the daemon.\n */\n if (!shared && config.paths.projectDir) {\n process.stderr.write(\n `[zidane-daemon] warning: project-DB mode is on, so this daemon uses ${config.paths.db}. `\n + `Windows opened in other projects will share this project's sessions. `\n + `Run a per-project daemon (ZIDANE_DAEMON_SOCKET) to isolate them.\\n`,\n )\n }\n\n /*\n * `config.initialSettings` is `resolveConfig`'s migrated snapshot of the\n * on-disk settings (it went through `settingsFromStored`, which maps the\n * legacy keys). Layering it under the live raw read means a user with\n * legacy-shaped settings gets the SAME effective settings in the daemon\n * as in the TUI, while mid-session writes (live `stateStore`) still win.\n * The live read goes through the same defaults migration, so a value\n * frozen at an old default by an older full-object writer doesn't override it.\n */\n const readSettings = (): HostSettings => ({\n ...DEFAULT_SETTINGS,\n ...config.initialSettings,\n ...settingsFromStored(config.stateStore.load().settings ?? {}),\n })\n\n /**\n * Fields the invariant forced (only ever `false`), so the stored file records\n * them too — otherwise a later read of `state.settings` would resurrect the\n * value the invariant just rejected. A field already `false` before the\n * invariant ran is left out: writing it would freeze a default on disk.\n */\n const pickInvariantFields = (unenforced: HostSettings, merged: HostSettings, patch: Partial<HostSettings>): Partial<HostSettings> => {\n const out: Partial<HostSettings> = {}\n for (const row of SETTINGS_TOGGLES) {\n if (row.requires && merged[row.key] === false && unenforced[row.key] !== false && patch[row.key] !== false)\n out[row.key] = false\n }\n return out\n }\n\n const writeSettings = (patch: Partial<HostSettings>, reset: readonly (keyof HostSettings)[] = []): HostSettings => {\n /*\n * Read-modify-write of the whole `state.json`, synchronous, through the\n * state store. A host in the window's process shares the window's store\n * (`config`), so the two writers interleave whole writes and each keeps\n * the other's fields. Across processes (the daemon and a local-mode\n * window on the same file) nothing locks; in daemon mode the window\n * leaves settings to the daemon and persists only its window-local\n * keys (`WINDOW_LOCAL_SETTINGS`: `useDaemon`, `remoteHosts`).\n */\n const state = config.stateStore.load()\n // Same invariants every writer applies (`orchestration` needs `useDaemon`,\n // …) — enforced on the MERGED view, since a patch can flip a requirement\n // off while the dependent stays true in the stored fields.\n const written = sparseSettingsUpdate(state.settings, patch, reset)\n const unenforced: HostSettings = { ...DEFAULT_SETTINGS, ...config.initialSettings, ...settingsFromStored(written) }\n const merged = enforceSettingsInvariants(unenforced)\n const next = sparseSettingsUpdate(written, pickInvariantFields(unenforced, merged, patch)) as Partial<HostSettings>\n config.stateStore.save({ ...state, settings: next })\n return merged\n }\n\n const userDataDir = (): string => config.paths.userDir\n\n const applyAuthEnv = (): void => {\n const dir = userDataDir()\n process.env.ZIDANE_CREDENTIALS_PATH = credentialsPath(dir)\n // The window's own registry when sharing its config (custom providers);\n // the daemon uses the built-ins.\n applyApiKeyEnv(dir, shared ? config.providers : BUILTIN_PROVIDERS)\n }\n\n /*\n * Daemon-side extension HUD: extension hooks run HERE in daemon mode, so\n * their `ctx.tui` writes need a live bus (headless hosts otherwise no-op\n * them). Every change is forwarded to the windows as `hud:state` /\n * `hud:notify` signals; the TUI overlays them under its local HUD.\n */\n const hud = createExtensionHud()\n const hudState = (): HudState => {\n const state = hud.getState()\n return {\n statuses: Object.fromEntries(\n Object.entries(state.statuses).map(([name, s]) => [name, { text: s.text, loader: s.loader }]),\n ),\n banners: Object.fromEntries(\n Object.entries(state.banners).map(([name, lines]) => [name, [...lines]]),\n ),\n sessions: Object.fromEntries(\n Object.entries(state.sessions).map(([id, byExtension]) => [\n id,\n Object.fromEntries(Object.entries(byExtension).map(([name, s]) => [name, { text: s.text, loader: s.loader }])),\n ]),\n ),\n badges: Object.fromEntries(Object.entries(state.badges).map(([id, list]) => [id, [...list]])),\n }\n }\n hud.subscribe(() => options.broadcast({ kind: 'hud:state', ...hudState() }))\n hud.onNotify((n) => {\n options.broadcast({ kind: 'hud:notify', extension: n.extension, text: n.text, tone: n.tone })\n })\n\n const base = {\n // The daemon serves explicitly-invoked clients (`zidane attach`)\n // even when `useDaemon` is off: a multi-writer surface by\n // construction, so the run guard + heartbeat are not setting-gated.\n // A shared host is single-writer unless told otherwise.\n multiProcess: shared ? shared.multiProcess === true : true,\n hudState,\n broadcast: (signal: HostSignal) => {\n // A deleted session's extension statuses and composer badges go with it.\n if (signal.kind === 'sessions:changed' && signal.op === 'delete')\n hud.clearSession(signal.sessionId)\n options.broadcast(signal)\n },\n store,\n readSettings,\n writeSettings,\n ...(config.stateStore.path ? { watchSettings: (onChange: () => void) => watchFileChanges(config.stateStore.path!, onChange) } : {}),\n userDataDir,\n stateDir: () => config.paths.stateDir,\n /*\n * The host's own log (a shared MCP server's output no session owns): the\n * daemon's stderr, its log file, plus the log sink. A host in the window's\n * process writes only to the sink: stderr there is the window's terminal.\n */\n ...(shared\n ? (options.logSink ? { logger: createLogger(options.logSink) } : {})\n : { logger: createLogger(options.logSink ? fanoutSink([options.logSink, consoleSink()]) : consoleSink()) }),\n applyAuthEnv,\n mcpCredentialStore: () => createFileMcpCredentialStore(userDataDir()),\n /*\n * The daemon persists parked approvals so a restart can re-offer them. A\n * host in the window's process dies with its runs, so it keeps them in\n * memory: the file is the daemon's (same state dir), not its to load or\n * clear.\n */\n approvalsPersistence: shared\n ? createMemoryApprovalsStore()\n : createFileApprovalsStore(join(dirname(config.paths.state), 'pending-approvals.json')),\n ...(options.debugStream !== undefined ? { debugStream: options.debugStream } : {}),\n config,\n }\n\n // The window's per-cwd config: no discovery, HUD or bus of our own;\n // the window's registries own those.\n if (shared) {\n const { resolve, invalidate, forget } = shared.runtimeConfig\n return {\n ...base,\n // Session artifacts where the window's local agent kept them.\n cacheDir: () => config.paths.cacheDir,\n runtimeConfig: resolve,\n ...(shared.hostRuntime ? { hostRuntime: shared.hostRuntime } : {}),\n ...(shared.extensionBus ? { extensionBus: shared.extensionBus } : {}),\n ...(shared.instrumentAgent ? { instrumentAgent: shared.instrumentAgent } : {}),\n ...(shared.terminals !== undefined ? { terminals: shared.terminals } : {}),\n invalidateRuntime: () => invalidate?.(),\n // Same contract as the daemon's: drop now, dispose when the returned\n // disposer runs (once no agent holds the old registries).\n forgetRuntime: () => forget?.() ?? (() => undefined),\n }\n }\n\n /*\n * Per-(cwd + allowlist + trust) runtime-config memo — same invalidation\n * axes the GUI's extension registry cache uses. Dropped wholesale on\n * settings writes that touch extension keys (see the server's\n * `settings.set` handler calling `invalidate`).\n */\n /*\n * Daemon-side extension bus: one bus shared by every per-cwd registry\n * (channels are private per extension id, so sharing is safe — and it\n * lets the server deliver a validated `extension.emit` no matter which\n * cwd's registry claimed the id). Emits from daemon-side extensions\n * already delivered loopback inside the bus; the hook fans the envelope\n * out to every window as `extension:signal`.\n */\n const extensionBus = createExtensionBus()\n extensionBus.onEmit((envelope) => {\n options.broadcast({ kind: 'extension:signal', ...envelope })\n })\n\n /*\n * LRU-bounded: a service-style daemon (`--idle-exit 0`) serving many\n * project folders would otherwise accumulate a full ResolvedConfig +\n * extension registry per (cwd × allowlist) key forever. Map iteration\n * order is insertion order; a cache hit re-inserts to mark recency.\n */\n const RUNTIME_CACHE_MAX = 16\n const runtimeCache = new Map<string, Promise<ResolvedConfig>>()\n\n // One bridge for every registry this daemon builds; the engine scopes the\n // invoking session onto it per command (see `ChatHostEnvironment.hostRuntime`).\n const hostRuntime = createExtensionHostRuntimeBridge()\n\n // `ctx.mcp` (`'mcp:call'` permission): one connection pool for every per-cwd registry.\n const mcpHost = createExtensionMcpHost({\n prefix: config.prefix,\n readSettings,\n credentialStore: () => createFileMcpCredentialStore(userDataDir()),\n })\n\n /**\n * Best-effort release of an evicted entry's extension registry\n * (teardown hooks, HUD writers — `registry.dispose()` is idempotent).\n * Fire-and-forget: eviction must never block or throw on a broken\n * extension teardown, and a rejected resolve has nothing to release.\n */\n const disposeRuntime = (promise: Promise<ResolvedConfig>): void => {\n void promise\n .then(config => config.extensions.dispose())\n .catch(() => undefined)\n }\n\n const runtimeKey = (cwd: string, settings: HostSettings): string => [\n cwd,\n JSON.stringify(settings.enabledExtensions ?? null),\n String(settings.loadProjectExtensions === true),\n ].join('\\u0000')\n\n const runtimeConfig = (cwd: string): Promise<ResolvedConfig> => {\n const settings = readSettings()\n const key = runtimeKey(cwd, settings)\n\n const existing = runtimeCache.get(key)\n if (existing) {\n // Refresh recency.\n runtimeCache.delete(key)\n runtimeCache.set(key, existing)\n return existing\n }\n\n const promise = (async () => {\n const extensionRegistry = await discoverAndBuildExtensionRegistry({\n cwd,\n hud,\n bus: extensionBus,\n hostRuntime,\n mcp: mcpHost,\n prefix: config.prefix,\n ...(settings.enabledExtensions !== undefined ? { enabledAllowlist: [...settings.enabledExtensions] } : {}),\n trustProjectExtensions: settings.loadProjectExtensions === true,\n readSettings,\n ...(options.logSink ? { sink: fanoutSink([options.logSink, consoleSink({ minLevel: 'warn' })]) } : {}),\n })\n return resolveConfig({\n cwd,\n extensionRegistry,\n store: () => store,\n })\n })()\n\n runtimeCache.set(key, promise)\n while (runtimeCache.size > RUNTIME_CACHE_MAX) {\n const oldest = runtimeCache.keys().next().value\n if (oldest === undefined)\n break\n const evicted = runtimeCache.get(oldest)\n runtimeCache.delete(oldest)\n if (evicted)\n disposeRuntime(evicted)\n }\n promise.catch(() => {\n if (runtimeCache.get(key) === promise)\n runtimeCache.delete(key)\n })\n return promise\n }\n\n return {\n ...base,\n runtimeConfig,\n peekRuntimeConfig: cwd => runtimeCache.get(runtimeKey(cwd, readSettings())),\n hostRuntime,\n invalidateRuntime: () => {\n for (const entry of runtimeCache.values())\n disposeRuntime(entry)\n runtimeCache.clear()\n },\n forgetRuntime: () => {\n const dropped = [...runtimeCache.values()]\n runtimeCache.clear()\n return () => {\n for (const entry of dropped)\n disposeRuntime(entry)\n }\n },\n extensionBus,\n }\n}\n\n/** The daemon's own boot config: paths + store + state, from `cwd`. */\nasync function resolveOwnConfig(cwd: string | undefined): Promise<ResolvedConfig> {\n /*\n * `bun:sqlite` is loaded LAZILY so `zidane/ipc` stays importable under\n * plain Node (the Electron GUI main process imports this barrel for\n * `createChatHost`; the sqlite chunk must never be evaluated there).\n * Same invariant the tsdown config maintains for `zidane/session/sqlite`.\n */\n const { createTuiStore } = await import('../../session/sqlite')\n /*\n * Session-facing runtime config is re-resolved per cwd (project\n * extensions differ per folder); this one only carries paths, store, state.\n */\n return resolveConfig({\n ...(cwd !== undefined ? { cwd } : {}),\n store: resolved => createTuiStore(resolved.db),\n })\n}\n","/**\n * A local host's machine links for its clients (`machines.share.*`,\n * `machines.useServer`, `machines.links.status`; `docs/MACHINES.md` § Client\n * UI). Opt-in down to the module graph: the controller (`../../machine/links`,\n * which dials servers) is imported only while remote hosts are on, so with\n * the setting off nothing is loaded, no token read, nothing dialed. Turning\n * remote hosts off stops every link (the wanted links stay saved).\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { MachineLinksStatus } from '../../../chat/machine-protocol'\nimport type { MachineLinks } from '../../machine/links'\nimport type { HostSignal } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { Handlers } from './types'\nimport { existsSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { remoteHostsGate } from '../../../chat/feature-gate'\nimport { InvalidParamsError } from './params'\n\nconst GATE_POLL_MS = 2000\nconst EMPTY: MachineLinksStatus = { shares: [], uses: [] }\n\n/** Options for {@link createMachineLinkHandlers}: the host, settings access and the signal sink. */\nexport interface MachineLinksHandlerOptions {\n /** The chat host whose machine registry the links feed. */\n host: ChatHost\n /** Environment accessors for reading settings and locating the user data directory. */\n env: Pick<DaemonEnvironment, 'readSettings' | 'userDataDir'>\n /** Sink that fans a signal out to every connected client. */\n broadcast: (signal: HostSignal) => void\n /** Id of this host, when it has one. */\n hostId: string | undefined\n /** A zidane-server: it has no links (a server is shared from, never shares from here); every method is refused. */\n server?: boolean\n /** zidane version reported when dialing a server. */\n appVersion: string\n /** Connection pacing for the links (tests shrink it). */\n pacing?: { minDelayMs?: number, maxDelayMs?: number, heartbeatMs?: number, pollMs?: number }\n}\n\ntype Methods = 'machines.share.start' | 'machines.share.stop' | 'machines.useServer' | 'machines.links.status'\n\n/** A server's: no links, nothing loaded or resumed. */\nfunction serverLinkHandlers(): Handlers<Methods> {\n const refuse = (): never => {\n throw new Error('A zidane-server has no machine links: share a computer with it from that computer (zidane machine share, or its Hosts page).')\n }\n return { 'machines.share.start': refuse, 'machines.share.stop': refuse, 'machines.useServer': refuse, 'machines.links.status': refuse }\n}\n\n/**\n * Builds the `machines.share.*`, `machines.useServer` and `machines.links.status` handlers.\n * The links load lazily and only while remote hosts are enabled. On a zidane-server every method throws. Turning remote hosts off stops every link.\n * @param options - Host, environment, broadcast sink and pacing.\n * @returns The four method handlers.\n */\nexport function createMachineLinkHandlers(options: MachineLinksHandlerOptions): Handlers<Methods> {\n if (options.server)\n return serverLinkHandlers()\n const { host, env, broadcast } = options\n let links: Promise<MachineLinks> | undefined\n let gateTimer: ReturnType<typeof setInterval> | undefined\n\n const gateOn = (): boolean => remoteHostsGate.isEnabled(env.readSettings())\n\n const stop = (): void => {\n const current = links\n links = undefined\n clearInterval(gateTimer)\n gateTimer = undefined\n void current?.then(l => l.close()).catch(() => undefined)\n broadcast({ kind: 'machine:links', links: EMPTY })\n }\n\n const load = (): Promise<MachineLinks> => {\n links ??= import('../../machine/links').then(({ startMachineLinks }) => startMachineLinks({\n dataDir: env.userDataDir(),\n machines: host.machines,\n hostId: options.hostId,\n appVersion: options.appVersion,\n settings: () => env.readSettings(),\n onChange: status => broadcast({ kind: 'machine:links', links: status }),\n ...options.pacing,\n }))\n // Remote hosts turned off (here or in another window): every link stops.\n gateTimer ??= setInterval(() => {\n if (!gateOn())\n stop()\n }, options.pacing?.pollMs ?? GATE_POLL_MS)\n gateTimer.unref?.()\n return links\n }\n\n const required = (): Promise<MachineLinks> => {\n if (!gateOn())\n throw new Error(`Remote hosts are off${remoteHostsGate.isKilled() ? ` (${remoteHostsGate.killSwitchEnv}=1)` : ''}: machines are part of them.`)\n return load()\n }\n\n const str = (value: unknown, name: string): string => {\n if (typeof value !== 'string' || value === '')\n throw new InvalidParamsError(`\"${name}\" must be a non-empty string.`)\n return value\n }\n\n // Links saved by an earlier run resume with the host, only while remote hosts are on.\n if (gateOn() && existsSync(join(env.userDataDir(), 'machine-links.json')))\n void load().catch(() => undefined)\n host.machines.onClose(() => {\n const current = links\n links = undefined\n clearInterval(gateTimer)\n void current?.then(l => l.close()).catch(() => undefined)\n })\n\n return {\n 'machines.share.start': async (p) => {\n if (!Array.isArray(p.roots))\n throw new InvalidParamsError('\"roots\" must be a list of folders.')\n // A confined host lends only its own workspace (local hosts are not confined).\n if (host.workspace.confined) {\n for (const root of p.roots)\n host.workspace.resolveFolder(String(root))\n }\n return (await required()).startShare({ hostId: str(p.hostId, 'hostId'), name: str(p.name, 'name'), roots: p.roots, ...(typeof p.token === 'string' ? { token: p.token } : {}) })\n },\n 'machines.share.stop': async p => (await required()).stopShare(str(p.hostId, 'hostId')),\n 'machines.useServer': async (p) => {\n if (typeof p.enabled !== 'boolean')\n throw new InvalidParamsError('\"enabled\" must be a boolean.')\n return (await required()).setUse(str(p.hostId, 'hostId'), p.enabled)\n },\n 'machines.links.status': async () => (gateOn() ? (await load()).status() : EMPTY),\n }\n}\n","/** Machines this host knows, for clients (`docs/MACHINES.md`): list them, forget one, browse one's folders. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostSignal } from '../../protocol'\nimport type { Handlers } from './types'\nimport { posix } from 'node:path'\nimport { insideDeclaredRoots } from '../../../chat/host/machines'\nimport { InvalidParamsError } from './params'\n\n/** Folders listed per call at most. */\nconst MAX_DIRS = 2000\n\n/**\n * Builds the `machines.list`, `machines.forget` and `machines.listDirs` handlers.\n * `machines.forget` broadcasts a `machine:status` signal with the machine offline when it removed one. `machines.listDirs` is confined to the machine's declared roots and throws for a path outside them.\n * @param options - The chat host and the signal broadcast sink.\n * @returns The three method handlers.\n */\nexport function createMachineHandlers({ host, broadcast }: { host: ChatHost, broadcast: (signal: HostSignal) => void }): Handlers<'machines.list' | 'machines.forget' | 'machines.listDirs'> {\n return {\n 'machines.list': () => host.machines.list(),\n 'machines.forget': (p) => {\n if (typeof p.machineId !== 'string')\n throw new InvalidParamsError('machines.forget: \"machineId\" must be a string.')\n const machine = host.machines.get(p.machineId)\n const forgotten = host.machines.forget(p.machineId)\n if (forgotten && machine)\n broadcast({ kind: 'machine:status', machineId: machine.id, name: machine.name, status: 'offline' })\n return { forgotten }\n },\n 'machines.listDirs': async (p) => {\n if (typeof p.machineId !== 'string')\n throw new InvalidParamsError('machines.listDirs: \"machineId\" must be a string.')\n const machine = host.machines.get(p.machineId)\n const link = host.machines.link(p.machineId)\n if (!machine || !link)\n throw new Error(`Unknown machine \"${p.machineId}\".`)\n const roots = machine.roots.map(root => root.path)\n // No path: the first root.\n const asked = p.path === undefined || p.path === '' ? roots[0]! : p.path\n if (typeof asked !== 'string' || !insideDeclaredRoots(machine.roots, asked))\n throw new Error(`${String(asked)} is outside ${machine.name}'s roots.`)\n const path = posix.normalize(asked)\n const root = roots.find(r => insideDeclaredRoots([{ path: r }], path))!\n // The machine confines the listing again on its filesystem (real paths); never waits for an offline one.\n const { entries } = await link.call('fs.list', { handle: { id: 'host-list-dirs', cwd: root }, path }, { wait: false })\n const dirs = entries\n .map(entry => (typeof entry === 'string' ? entry : entry.path))\n .filter(name => name.endsWith('/'))\n .map(name => posix.join(path, name.slice(0, -1)))\n .sort()\n .slice(0, MAX_DIRS)\n return { path, dirs, roots }\n },\n }\n}\n","/**\n * The host side of one JSON-RPC connection, for every wire transport (the\n * unix socket in `../daemon/server.ts`, the WebSocket in `./ws-server.ts`):\n * a dispatcher {@link HostPeer} whose signals go out as `ipc.signal`\n * notifications, and the request / notification handlers that hand incoming\n * messages to the dispatcher. Framing and the write-backpressure bound\n * (`./send-budget`) stay with the transport.\n *\n * A signal is serialized once per fan-out, not once per peer: the first peer\n * builds the notification text from the signal's JSON and every other peer\n * of the fan-out sends the same string ({@link signalFrame}).\n */\nimport type { JsonRpcConnectionOptions } from '../../acp/json-rpc'\nimport type { AcpPeer, JsonRpcMessage, JsonRpcRequest, JsonRpcResponse } from '../../acp/types'\nimport type { HostDispatcher, HostPeer } from '../daemon/dispatcher'\nimport type { HostSignal } from '../protocol'\nimport { errorResponse, successResponse } from '../../acp/json-rpc'\nimport { SIGNAL_SEQ_FIELD } from '../protocol'\n\n/**\n * Per-peer write backpressure bound. A wedged peer (e.g. a SIGSTOP'd\n * terminal) stops reading, so fan-out writes pile up in the transport's\n * send buffer without bound and can OOM the host. A peer buffering more\n * than this is dropped: the protocol supports re-attach + backfill, so\n * killing a wedged peer is safe and self-healing.\n */\nexport const PEER_WRITE_HIGH_WATERMARK = 8 * 1024 * 1024\n\nexport interface RpcPeerOptions {\n /** The connection's JSON-RPC side; signals are dropped until it exists. */\n rpc: () => (Pick<AcpPeer, 'sendNotification'> & { sendSerialized?: (json: string, message: JsonRpcMessage) => void }) | undefined\n}\n\n/** What the send budget sees of a pre-serialized signal: a notification, never a reply. */\nconst SIGNAL_MESSAGE: JsonRpcMessage = { jsonrpc: '2.0', method: 'ipc.signal' }\n\n/**\n * The `ipc.signal` notification text for a signal whose JSON is `json`,\n * byte for byte what serializing `{ jsonrpc, method, params: { ...signal,\n * [SIGNAL_SEQ_FIELD]: seq } }` gives; `undefined` when splicing could not\n * promise that (an empty or non-object JSON, a signal that has the field).\n */\nexport function signalFrame(signal: HostSignal, json: string, seq: number | undefined): string | undefined {\n if (seq === undefined)\n return `{\"jsonrpc\":\"2.0\",\"method\":\"ipc.signal\",\"params\":${json}}`\n if (json.length <= 2 || json[0] !== '{' || !json.endsWith('}') || Object.hasOwn(signal, SIGNAL_SEQ_FIELD))\n return undefined\n return `{\"jsonrpc\":\"2.0\",\"method\":\"ipc.signal\",\"params\":${json.slice(0, -1)},\"${SIGNAL_SEQ_FIELD}\":${seq}}}`\n}\n\nexport function createRpcPeer(options: RpcPeerOptions): HostPeer {\n return {\n ready: false,\n watching: null,\n send(signal, seq, encoded) {\n try {\n const rpc = options.rpc()\n if (!rpc)\n return\n if (encoded && rpc.sendSerialized) {\n const json = encoded.json()\n if (json === undefined)\n return // Not JSON-able: no peer can receive it.\n encoded.frame ??= signalFrame(signal, json, seq)\n if (encoded.frame !== undefined) {\n rpc.sendSerialized(encoded.frame, SIGNAL_MESSAGE)\n return\n }\n }\n rpc.sendNotification('ipc.signal', seq === undefined ? signal : { ...signal, [SIGNAL_SEQ_FIELD]: seq })\n }\n catch {\n // A dying connection (or a signal JSON can't encode) must never take the host down with it.\n }\n },\n }\n}\n\n/** The JSON-RPC handlers that route one peer's requests and notifications to the dispatcher. */\nexport function dispatcherHandlers(dispatcher: HostDispatcher, peer: HostPeer): Pick<JsonRpcConnectionOptions, 'onRequest' | 'onNotification'> {\n return {\n onRequest: async (message: JsonRpcRequest): Promise<JsonRpcResponse> => {\n const outcome = await dispatcher.handleRequest(message.method, message.params, peer)\n return outcome.ok\n ? successResponse(message.id, outcome.result)\n : errorResponse(message.id, outcome.code, outcome.message, outcome.data)\n },\n onNotification: message => dispatcher.handleNotification(message.method, message.params, peer),\n }\n}\n","/**\n * One connection's outgoing budget, for every wire transport (the unix\n * socket in `../daemon/server.ts`, the WebSocket in `./ws-server.ts`).\n *\n * The slow-consumer bound is about pushed signals piling up for a peer that\n * stopped reading, not about one big reply it asked for: reply bytes still\n * queued are set aside (`replyReserve`) when the backlog is measured. The\n * buffer drains in order, so the reserve can only shrink to what is still\n * buffered; a peer that never reads keeps it whole and is dropped once the\n * signals behind it pass the bound. A reply itself is bounded by the message\n * size (over it, an `IpcErrorCode.ResponseTooLarge` error goes instead and\n * the connection stays), and the whole buffer by a hard cap for memory.\n *\n * The reserve is an approximation: it assumes the buffer drains oldest\n * first and only clamps it to what is still buffered, so after a partial\n * drain it may still count reply bytes that already left, and the signals\n * backlog reads low by at most that much. The memory bound, precisely: a\n * reply leaves the whole buffer at most `H = maxBuffered + 2 × maxMessage`\n * (checked after its write), and every signal re-clamps the reserve to what\n * is buffered, so the reserve never exceeds what the buffer held at the\n * first signal after the last reply (at most `H` plus that signal). A\n * signal leaves the measured backlog at most `maxBuffered`, so between\n * sends a peer holds at most `maxBuffered + H = 2 × maxBuffered + 2 ×\n * maxMessage` bytes (plus one signal). The write that crosses a bound is\n * the last: the peer is marked stuck and nothing more goes out. That is the\n * only backlog check: the buffer grows through `send`, so a backlog\n * over the bound is always seen by the write that made it.\n */\nimport type { JsonRpcMessage } from '../../acp/types'\nimport { Buffer } from 'node:buffer'\nimport { errorResponse } from '../../acp/json-rpc'\nimport { IpcErrorCode } from '../protocol'\n\n/** What the budget writes to: the transport's buffer and its framing. */\nexport interface SendTarget {\n /** Bytes written but not yet handed to the OS. */\n buffered: () => number\n /** Write one serialized message (the target frames it); `false`: the transport dropped it. */\n write: (json: string) => boolean\n}\n\nexport interface SendLimits {\n /** Signals backlog past which the peer is stuck (replies set aside). */\n maxBuffered: number\n /** Largest reply; a bigger one is answered with `ResponseTooLarge`. */\n maxMessage: number\n /** The peer cannot keep up: tear it down (called once). */\n stuck: (why: string) => void\n log: (line: string) => void\n /** Log prefix, e.g. `[ipc-ws]`. */\n label: string\n}\n\nexport interface PeerSend {\n /** Bytes buffered that are not reply bytes: what the slow-consumer bound measures. */\n backlog: () => number\n /** Send one message (the JSON-RPC endpoint's `send`): replies and the rest apart. */\n send: (json: string, message: JsonRpcMessage) => void\n /** Give up on the peer (once): {@link SendLimits.stuck} runs and nothing more goes out. */\n markStuck: (why: string) => void\n}\n\nfunction isReply(message: JsonRpcMessage): boolean {\n return 'id' in message && message.id !== undefined && message.id !== null && ('result' in message || 'error' in message)\n}\n\nexport function createPeerSend(target: SendTarget, limits: SendLimits): PeerSend {\n const { maxBuffered, maxMessage, log, label } = limits\n let replyReserve = 0\n let stuck = false\n const markStuck = (why: string): void => {\n if (stuck)\n return\n stuck = true\n limits.stuck(why)\n }\n const backlog = (): number => {\n const buffered = target.buffered()\n replyReserve = Math.min(replyReserve, buffered)\n return buffered - replyReserve\n }\n const send = (json: string, message: JsonRpcMessage): void => {\n if (stuck)\n return\n if (!isReply(message)) {\n if (!target.write(json) || backlog() > maxBuffered)\n markStuck(`more than ${maxBuffered} bytes of signals unsent`)\n return\n }\n let text = json\n let bytes = Buffer.byteLength(text)\n if (bytes > maxMessage) {\n const id = (message as { id: string | number }).id\n log(`${label} reply to ${String(id)} is ${bytes} bytes (> ${maxMessage}): answering with an error instead`)\n text = JSON.stringify(errorResponse(id, IpcErrorCode.ResponseTooLarge, `The reply is over ${maxMessage} bytes: ask for less (a transcript: a smaller page).`, { bytes, maxBytes: maxMessage }))\n bytes = Buffer.byteLength(text)\n }\n if (!target.write(text)) {\n markStuck('reply dropped by the transport')\n return\n }\n replyReserve += bytes\n if (target.buffered() > maxBuffered + 2 * maxMessage)\n markStuck(`more than ${maxBuffered + 2 * maxMessage} bytes unsent`)\n }\n return { backlog, send, markStuck }\n}\n","/**\n * The calling side of a worker RPC: request ids, a pending map, a timeout\n * per request, and crash recovery. A worker that crashes rejects what is\n * pending and is spawned again on the next use, after a backoff that doubles\n * up to a cap. A worker that cannot start (the factory throws, or it dies\n * before it said ready) or that crashes `maxCrashes` times in a row puts the\n * client in degraded mode: every request then rejects at once with a\n * {@link WorkerUnavailableError}, the caller's signal to do the work on its\n * own thread.\n *\n * Runtime-neutral: the factory returns a Bun / Web `Worker` or a Node\n * `worker_threads.Worker` ({@link WorkerLike}). The worker side is\n * `serveWorkerRpc` (`./rpc-serve.ts`); the wire is {@link WorkerCall} out,\n * {@link WorkerMessage} back.\n */\n\n/** A worker from either runtime: Bun / Web `Worker` (`addEventListener`) or Node `worker_threads.Worker` (`on`). */\nexport interface WorkerLike {\n /** Sends a {@link WorkerCall} to the worker. */\n postMessage: (message: unknown) => void\n /** Ends the worker. */\n terminate: () => unknown\n /** Lets the worker keep the process alive (while a reply is due). */\n ref?: () => void\n /** Stops the worker from keeping the process alive. */\n unref?: () => void\n /** Node's events: `message`, `error`, `exit`. */\n on?: (event: string, listener: (value: unknown) => void) => unknown\n /** Bun / Web events: `message`, `error`, `close`. */\n addEventListener?: (type: string, listener: (event: unknown) => void) => void\n}\n\n/** What the client posts: `init` once per spawn, then requests (`id` absent: a notification, no reply). */\nexport type WorkerCall = { init: unknown } | { id?: number, request: unknown }\n\n/** What the worker posts back. */\nexport type WorkerMessage\n = | { ready: true }\n | { fatal: string }\n | { id: number, ok: true, result: unknown }\n | { id: number, ok: false, error: { name: string, message: string } }\n\n/** No worker served the request: do the work on this thread. `degraded`: none will until the client is recreated. */\nexport class WorkerUnavailableError extends Error {\n /**\n * @param message - Why no worker served.\n * @param degraded - No worker will serve until the client is recreated.\n */\n constructor(message: string, readonly degraded: boolean) {\n super(message)\n this.name = 'WorkerUnavailableError'\n }\n}\n\n/** The worker's handler threw: `remoteName` and `message` are the thrown error's. */\nexport class WorkerRequestError extends Error {\n /**\n * @param remoteName - The thrown error's `name`.\n * @param message - The thrown error's `message`.\n */\n constructor(readonly remoteName: string, message: string) {\n super(message)\n this.name = 'WorkerRequestError'\n }\n}\n\n/** How {@link createWorkerRpcClient} spawns and supervises its worker. */\nexport interface WorkerRpcClientOptions {\n /** Spawns the worker. A throw puts the client in degraded mode. */\n create: () => WorkerLike\n /** Posted to every worker this client spawns, before any request (`serveWorkerRpc`'s `init`). */\n init?: unknown\n /** A request unanswered this long rejects, and the worker counts as crashed. Default 30 s. */\n timeoutMs?: number\n /** Crashes in a row before degraded mode. Default 3. */\n maxCrashes?: number\n /** Wait before spawning again after a crash: `base` doubled per crash in a row, at most `max`. Default 250 ms / 10 s. */\n backoffMs?: { base: number, max: number }\n /** What the worker is called in the errors it causes (`<name> unavailable: …`). Default `worker`. */\n name?: string\n /** Called once, with the reason, when the client goes degraded: from then on the caller does the work on its own thread. */\n onDegraded?: (reason: string) => void\n}\n\n/** The calling side of a worker RPC, from {@link createWorkerRpcClient}. */\nexport interface WorkerRpcClient<Req, Res> {\n /** Spawns the worker when none runs. Rejects {@link WorkerUnavailableError} when no worker can serve, {@link WorkerRequestError} when the handler threw. */\n request: (request: Req, options?: { timeoutMs?: number }) => Promise<Res>\n /** Fire-and-forget, only to a running worker (none: nothing to tell). */\n notify: (request: Req) => void\n /** True once no worker will serve (it could not start, or crashed `maxCrashes` times in a row). */\n isDegraded: () => boolean\n /** Terminates the worker and rejects what is pending; later requests reject. Idempotent. */\n close: () => void\n}\n\ninterface Pending {\n resolve: (value: unknown) => void\n reject: (error: Error) => void\n timer: ReturnType<typeof setTimeout>\n}\n\n/** Subscribes to a worker's messages, errors and exit, whichever event API it has. */\nfunction listen(worker: WorkerLike, on: { message: (data: unknown) => void, failed: (reason: string) => void }): void {\n if (typeof worker.on === 'function') {\n worker.on('message', data => on.message(data))\n worker.on('error', err => on.failed(err instanceof Error ? err.message : String(err)))\n worker.on('exit', code => on.failed(`exited with code ${String(code)}`))\n return\n }\n worker.addEventListener?.('message', event => on.message((event as MessageEvent).data))\n worker.addEventListener?.('error', event => on.failed((event as ErrorEvent).message || 'worker error'))\n // Bun's `close`: the worker exited.\n worker.addEventListener?.('close', event => on.failed(`exited with code ${(event as { code?: number }).code ?? '?'}`))\n}\n\n/**\n * A worker RPC client. The worker spawns on the first request.\n * @param options - How to spawn the worker, its `init`, the timeout and the crash policy.\n */\nexport function createWorkerRpcClient<Req, Res>(options: WorkerRpcClientOptions): WorkerRpcClient<Req, Res> {\n const timeoutMs = options.timeoutMs ?? 30_000\n const maxCrashes = options.maxCrashes ?? 3\n const backoff = options.backoffMs ?? { base: 250, max: 10_000 }\n const name = options.name ?? 'worker'\n const pending = new Map<number, Pending>()\n let nextId = 1\n let worker: WorkerLike | null = null\n let ready = false\n let crashes = 0\n let retryAt = 0\n let degraded: string | null = null\n let closed = false\n\n function degrade(reason: string): string {\n degraded = reason\n options.onDegraded?.(reason)\n return reason\n }\n\n function settleAll(reason: string): void {\n const error = new WorkerUnavailableError(reason, degraded !== null || closed)\n for (const [id, entry] of pending) {\n clearTimeout(entry.timer)\n pending.delete(id)\n entry.reject(error)\n }\n }\n\n /** The current worker is gone: a spawn failure degrades, a crash backs off. */\n function fail(failed: WorkerLike, reason: string): void {\n if (failed !== worker)\n return\n const wasReady = ready\n worker = null\n ready = false\n try {\n void failed.terminate()\n }\n catch {\n // Already gone.\n }\n crashes++\n if (!wasReady || crashes >= maxCrashes)\n degrade(`${name} unavailable: ${wasReady ? `${crashes} crashes in a row` : 'it did not start'} (${reason})`)\n retryAt = Date.now() + Math.min(backoff.base * 2 ** (crashes - 1), backoff.max)\n settleAll(degraded ?? `worker crashed: ${reason}`)\n }\n\n function onMessage(from: WorkerLike, data: unknown): void {\n if (from !== worker || typeof data !== 'object' || data === null)\n return\n const message = data as WorkerMessage\n if ('ready' in message) {\n ready = true\n return\n }\n if ('fatal' in message) {\n ready = false\n fail(from, message.fatal)\n return\n }\n const entry = pending.get(message.id)\n if (!entry)\n return\n pending.delete(message.id)\n clearTimeout(entry.timer)\n crashes = 0\n if (pending.size === 0)\n from.unref?.()\n if (message.ok)\n entry.resolve(message.result)\n else\n entry.reject(new WorkerRequestError(message.error.name, message.error.message))\n }\n\n function ensureWorker(): WorkerLike {\n if (closed)\n throw new WorkerUnavailableError('worker client closed', true)\n if (degraded !== null)\n throw new WorkerUnavailableError(degraded, true)\n if (worker)\n return worker\n if (Date.now() < retryAt)\n throw new WorkerUnavailableError('worker restarting after a crash', false)\n let spawned: WorkerLike\n try {\n spawned = options.create()\n }\n catch (err) {\n throw new WorkerUnavailableError(degrade(`${name} unavailable: ${err instanceof Error ? err.message : String(err)}`), true)\n }\n worker = spawned\n listen(spawned, { message: data => onMessage(spawned, data), failed: reason => fail(spawned, reason) })\n // Idle, it must not keep the process alive; `request` refs it while a reply is due.\n spawned.unref?.()\n spawned.postMessage({ init: options.init } satisfies WorkerCall)\n return spawned\n }\n\n return {\n request(request, requestOptions = {}) {\n return new Promise<Res>((resolve, reject) => {\n let target: WorkerLike\n try {\n target = ensureWorker()\n }\n catch (err) {\n reject(err instanceof Error ? err : new Error(String(err)))\n return\n }\n const id = nextId++\n const wait = requestOptions.timeoutMs ?? timeoutMs\n const timer = setTimeout(fail, wait, target, `no reply in ${wait} ms`)\n pending.set(id, { resolve: resolve as (value: unknown) => void, reject, timer })\n target.ref?.()\n try {\n target.postMessage({ id, request } satisfies WorkerCall)\n }\n catch (err) {\n // Not cloneable: this request only, the worker is fine.\n pending.delete(id)\n clearTimeout(timer)\n if (pending.size === 0)\n target.unref?.()\n reject(new WorkerUnavailableError(`could not post the request: ${err instanceof Error ? err.message : String(err)}`, false))\n }\n })\n },\n notify(request) {\n try {\n worker?.postMessage({ request } satisfies WorkerCall)\n }\n catch {\n // A worker going away takes its state with it.\n }\n },\n isDegraded: () => degraded !== null,\n close() {\n if (closed)\n return\n closed = true\n const current = worker\n worker = null\n settleAll('worker client closed')\n try {\n void current?.terminate()\n }\n catch {\n // Already gone.\n }\n },\n }\n}\n","/**\n * `sessions.loadEvents` pages served off the host's thread. A whole-session\n * replay (load every turn, replay them all) takes tens to hundreds of\n * milliseconds on a long session; on the host's event loop that stalls the\n * TUI in local mode, and every session's streaming on a daemon or a\n * zidane-server. The history worker (`./worker.ts`) runs the same replay\n * cache against its own read-only connection to the sessions database, so\n * pages are identical to the in-thread ones (same versioning by `getMeta`,\n * same bounds); only the thread differs.\n *\n * The pager falls back to the in-thread cache whenever the worker cannot\n * serve: a store that is not a SQLite file, `ZIDANE_NO_HISTORY_WORKER=1`,\n * a worker that cannot start or keeps crashing (degraded), or one request it\n * lost (a crash, a timeout).\n *\n * The worker also scans the usage summary's day buckets (`usage.summary`),\n * a read of every turn; without it, the scan runs here on a read-only\n * connection of its own.\n */\nimport type { SessionStore } from '../../session/index'\nimport type { SqliteStoreFile } from '../../session/sqlite-store'\nimport type { UsageBuckets } from '../../session/sqlite-usage'\nimport type { TranscriptReplayCache } from '../daemon/handlers/transcript-cache'\nimport type { HostSignal, LoadEventsPaging, SessionEventsPage } from '../protocol'\nimport type { WorkerLike, WorkerRpcClientOptions } from './rpc-client'\nimport { sqliteStoreFile } from '../../session/sqlite-store'\nimport { runUsageAggregates } from '../../session/sqlite-usage'\nimport { InvalidParamsError } from '../daemon/handlers/params'\nimport { changedSessionOf, createTranscriptReplayCache } from '../daemon/handlers/transcript-cache'\nimport { openReadonlySqlite } from './readonly-db'\nimport { createWorkerRpcClient, WorkerRequestError, WorkerUnavailableError } from './rpc-client'\n\n/** Kill switch: `1` pages on the host's thread, with no worker. */\nexport const HISTORY_WORKER_KILL_SWITCH = 'ZIDANE_NO_HISTORY_WORKER'\n\n/** What `./worker.ts` takes as `init`. */\nexport interface HistoryWorkerInit {\n /** The sessions database, opened read-only by the worker. */\n dbPath: string\n}\n\n/** The history worker's requests. */\nexport type HistoryWorkerRequest\n = | { op: 'page', sessionId: string, paging: LoadEventsPaging }\n | { op: 'drop', sessionId: string }\n | { op: 'usage' }\n\n/**\n * The history worker's module: the sibling source file in development, the\n * sibling `history-worker.js` entry in the published dist, and the entry\n * embedded under the binary's root in a compiled executable\n * (`scripts/build-executables.ts`, `scripts/build-server.ts`).\n */\nexport function historyWorkerUrl(): URL {\n if (typeof Bun !== 'undefined' && (Bun as unknown as { isStandaloneExecutable?: boolean }).isStandaloneExecutable)\n return new URL('./src/ipc/history/worker.ts', import.meta.url)\n return new URL(import.meta.url.endsWith('.ts') ? './worker.ts' : './history-worker.js', import.meta.url)\n}\n\n/** A Bun / Web `Worker` on the history worker module. */\nfunction spawnHistoryWorker(): WorkerLike {\n return new Worker(historyWorkerUrl().href, { type: 'module' })\n}\n\n/** A client of the history worker, from {@link createTranscriptHistoryWorker}. */\nexport interface TranscriptHistoryWorker {\n /**\n * One `sessions.loadEvents` page, from the worker. Rejects\n * {@link WorkerUnavailableError} when the worker could not serve it (page\n * in-thread then), {@link InvalidParamsError} for bad paging, and the\n * worker's error otherwise (an unknown session).\n */\n page: (sessionId: string, paging: LoadEventsPaging) => Promise<SessionEventsPage>\n /** The session changed or went away: the worker forgets its replay. */\n drop: (sessionId: string) => void\n /** The usage summary's day buckets (`runUsageAggregates`). Rejects {@link WorkerUnavailableError} when the worker could not serve them. */\n usage: () => Promise<UsageBuckets>\n /** True once the worker will not serve again (it could not start, or keeps crashing). */\n isDegraded: () => boolean\n /** Terminates the worker; later pages reject {@link WorkerUnavailableError}. */\n close: () => void\n}\n\n/**\n * A client of the history worker over `dbPath`. The worker spawns on the\n * first page.\n * @param options - The database, and (tests, a Node host) how to spawn the worker.\n */\nexport function createTranscriptHistoryWorker(options: {\n dbPath: string\n /** Default: a Bun / Web `Worker` on {@link historyWorkerUrl}. */\n create?: () => WorkerLike\n} & Pick<WorkerRpcClientOptions, 'timeoutMs' | 'maxCrashes' | 'backoffMs' | 'onDegraded'>): TranscriptHistoryWorker {\n const { dbPath, create = spawnHistoryWorker, ...rest } = options\n const client = createWorkerRpcClient<HistoryWorkerRequest, unknown>({ name: 'history worker', create, init: { dbPath } satisfies HistoryWorkerInit, ...rest })\n return {\n async page(sessionId, paging) {\n try {\n return await client.request({ op: 'page', sessionId, paging }) as SessionEventsPage\n }\n catch (err) {\n if (err instanceof WorkerRequestError)\n throw err.remoteName === 'InvalidParamsError' ? new InvalidParamsError(err.message) : new Error(err.message)\n throw err\n }\n },\n drop: sessionId => client.notify({ op: 'drop', sessionId }),\n usage: async () => await client.request({ op: 'usage' }) as UsageBuckets,\n isDegraded: client.isDegraded,\n close: client.close,\n }\n}\n\n/** Where a host's paged `sessions.loadEvents` are served: the history worker when it can, else the in-thread cache. */\nexport interface HostTranscriptPager {\n /** The in-thread cache: the fallback pages, and the host's other whole-session reads (`document`). */\n replays: TranscriptReplayCache\n /** One page of a session of `store` (the worker serves it when `store` is a SQLite file). */\n page: (store: SessionStore, sessionId: string, paging: LoadEventsPaging) => Promise<SessionEventsPage>\n /** A host signal: one that follows a change to a session drops its replay, here and in the worker. */\n observe: (signal: HostSignal) => void\n /** The session is gone: forget it here and in the worker. */\n forget: (sessionId: string) => void\n /** The usage summary's day buckets of `store`; `null` for a store that is not a SQLite file (it keeps no usage to scan). */\n usage: (store: SessionStore) => Promise<UsageBuckets | null>\n /** Terminates the worker (the host is shutting down); later pages are served in-thread. */\n close: () => void\n}\n\nconst debugFallback: (error: unknown) => void = process.env.ZIDANE_DEBUG\n ? error => console.error('[zidane/ipc] the history worker could not serve; the host thread does:', error)\n : () => {}\n\n/**\n * A host's pager. The worker is used only for a store that is a SQLite file\n * (`sqliteStoreFile`), with the kill switch off; it spawns lazily, on the\n * first page, for the first such file (one host, one store).\n * @param options - Options.\n * @param options.replays - The in-thread cache; default a new one.\n * @param options.worker - Makes the worker client (tests); default {@link createTranscriptHistoryWorker}.\n */\nexport function createHostTranscriptPager(options: {\n replays?: TranscriptReplayCache\n worker?: (dbPath: string) => TranscriptHistoryWorker\n} = {}): HostTranscriptPager {\n const replays = options.replays ?? createTranscriptReplayCache()\n const makeWorker = options.worker ?? (dbPath => createTranscriptHistoryWorker({ dbPath }))\n let worker: { client: TranscriptHistoryWorker, path: string } | null = null\n let closed = false\n\n const usable = (store: SessionStore): { client: TranscriptHistoryWorker, file: SqliteStoreFile } | null => {\n const file = sqliteStoreFile(store)\n if (closed || !file || process.env[HISTORY_WORKER_KILL_SWITCH] === '1')\n return null\n worker ??= { client: makeWorker(file.path), path: file.path }\n return worker.path === file.path && !worker.client.isDegraded() ? { client: worker.client, file } : null\n }\n const drop = (sessionId: string): void => worker?.client.drop(sessionId)\n\n return {\n replays,\n async page(store, sessionId, paging) {\n const target = usable(store)\n if (target) {\n // The worker reads on its own connection: let this one's queued writes land first, as an in-thread read would wait for them.\n await target.file.settled()\n try {\n return await target.client.page(sessionId, paging)\n }\n catch (err) {\n if (!(err instanceof WorkerUnavailableError))\n throw err\n debugFallback(err)\n }\n }\n return replays.page(store, sessionId, paging)\n },\n observe(signal) {\n replays.observe(signal)\n const sessionId = changedSessionOf(signal)\n if (sessionId !== undefined)\n drop(sessionId)\n },\n forget(sessionId) {\n replays.forget(sessionId)\n drop(sessionId)\n },\n async usage(store) {\n const file = sqliteStoreFile(store)\n if (!file)\n return null\n await file.settled()\n const target = usable(store)\n if (target) {\n try {\n return await target.client.usage()\n }\n catch (err) {\n if (!(err instanceof WorkerUnavailableError))\n throw err\n debugFallback(err)\n }\n }\n const db = await openReadonlySqlite(file.path)\n try {\n return runUsageAggregates(db)\n }\n finally {\n db.close()\n }\n },\n close() {\n closed = true\n worker?.client.close()\n worker = null\n },\n }\n}\n","/**\n * Secret redaction for what a host shows about its MCP servers\n * (`catalog.mcps`): command-line arguments and URLs, which config files\n * routinely fill with tokens. Over-redacting an ordinary argument is a\n * cosmetic loss; under-redacting leaks a credential to every client, so the\n * rules lean wide, but stay off file paths, package names and plain words.\n *\n * - URLs (`scheme://…`, as an argument or inside one): userinfo, query values,\n * fragment values, and secret-looking path segments.\n * - Values of secret-looking flags (`--token x`, `--api-key=x`), of header\n * flags (`-H \"Name: value\"`, `--header=Name: value`), of secret-looking\n * headers anywhere (`Authorization: Bearer …`), and of secret-looking\n * `KEY=VALUE` pairs (`-e GITHUB_TOKEN=…`, `env API_KEY=…`, `--pass x`).\n * - JSON arguments (`--config '{\"apiKey\":\"…\"}'`): the value of every\n * secret-named key at any depth; the other strings as values.\n * - Connection strings and form bodies (`Server=x;Password=…`,\n * `a=1&token=…`): each secret-named pair's value.\n * - Known token shapes anywhere in an argument (`sk-…`, `ghp_…`, `xoxb-…`,\n * `AKIA…`, `glpat-…`, `zds_…`), and whole high-entropy arguments.\n *\n * What counts as secret-looking is shared (`src/chat/secret-shapes`): the\n * remote host URL check refuses the same shapes in a URL's path.\n */\nimport { isSecretName, isSecretPathSegment, KNOWN_TOKEN, looksLikeSecret } from '../../chat/secret-shapes'\nimport { REDACTED } from '../protocol'\n\nconst HEADER_FLAGS = new Set(['-H', '--header', '--headers'])\nconst URL_SHAPED = /^[a-z][a-z0-9+.-]*:\\/\\//i\nconst HEADER = /^([\\w-]+):(\\s*)\\S.*$/s\nconst KEY_VALUE = /^([A-Z_][\\w.-]*)=(.*)$/is\n/** `k=v` pairs joined by `;` or `&` (a connection string, a form body): `Server=x;Password=y`, `a=1&token=x`. */\nconst DELIMITED_PAIRS = /^[a-z_][\\w .-]*=[^;&]*(?:[;&][a-z_][\\w .-]*=[^;&]*)+[;&]?$/i\n/** A JSON object or array argument (`--config '{\"apiKey\":\"…\"}'`). */\nconst JSON_SHAPED = /^\\s*[{[][\\s\\S]*[}\\]]\\s*$/\n\nconst scrubKnownTokens = (value: string): string => value.replace(KNOWN_TOKEN, REDACTED)\n\nfunction redactPairs(text: string): string {\n return text.split('&').map((pair) => {\n const eq = pair.indexOf('=')\n return eq < 0 ? pair : `${pair.slice(0, eq)}=${REDACTED}`\n }).join('&')\n}\n\n/**\n * `https://user:pw@host/p/<key>/sse?k=v#t=x` → `https://<redacted>@host/p/<redacted>/sse?k=<redacted>#t=<redacted>`;\n * an unparsable URL is redacted whole.\n */\nexport function redactUrl(raw: string): string {\n let url: URL\n try {\n url = new URL(raw)\n }\n catch {\n return REDACTED\n }\n const credentials = url.username !== '' || url.password !== '' ? `${REDACTED}@` : ''\n const path = url.pathname.split('/').map(segment => isSecretPathSegment(segment) ? REDACTED : segment).join('/')\n const keys = [...url.searchParams.keys()]\n const query = keys.length > 0 ? `?${keys.map(key => `${encodeURIComponent(key)}=${REDACTED}`).join('&')}` : ''\n const fragment = url.hash.slice(1)\n const hash = fragment === '' ? '' : fragment.includes('=') ? `#${redactPairs(fragment)}` : looksLikeSecret(fragment) ? `#${REDACTED}` : `#${fragment}`\n const authority = url.host !== '' || raw.includes('//') ? `//${credentials}${url.host}` : ''\n return scrubKnownTokens(`${url.protocol}${authority}${path}${query}${hash}`)\n}\n\nfunction redactHeader(value: string): string {\n const match = HEADER.exec(value)\n return match ? `${match[1]}:${match[2]}${REDACTED}` : REDACTED\n}\n\n/** One value standing on its own (a positional argument, or what follows `--flag=`). */\nfunction redactValue(value: string): string {\n if (URL_SHAPED.test(value))\n return redactUrl(value)\n const header = HEADER.exec(value)\n if (header && isSecretName(header[1]!))\n return redactHeader(value)\n const json = JSON_SHAPED.test(value) ? redactJson(value) : null\n if (json !== null)\n return json\n if (DELIMITED_PAIRS.test(value))\n return redactDelimitedPairs(value)\n const pair = KEY_VALUE.exec(value)\n if (pair)\n return `${pair[1]}=${isSecretName(pair[1]!) ? REDACTED : redactValue(pair[2]!)}`\n if (looksLikeSecret(value))\n return REDACTED\n return scrubKnownTokens(value)\n}\n\n/** `Server=x;Password=y` → `Server=x;Password=<redacted>`: each secret-named pair's value, the others' as values. */\nfunction redactDelimitedPairs(value: string): string {\n return value.split(/([;&])/).map((part) => {\n const eq = part.indexOf('=')\n if (eq < 0)\n return part\n const name = part.slice(0, eq)\n return `${name}=${isSecretName(name.trim()) ? REDACTED : redactValue(part.slice(eq + 1))}`\n }).join('')\n}\n\n/** A JSON argument with every secret-named key's value redacted (any depth), the other strings as values; `null` when not JSON. */\nfunction redactJson(value: string): string | null {\n let parsed: unknown\n try {\n parsed = JSON.parse(value)\n }\n catch {\n return null\n }\n if (parsed === null || typeof parsed !== 'object')\n return null\n const walk = (node: unknown): unknown => {\n if (typeof node === 'string')\n return redactValue(node)\n if (Array.isArray(node))\n return node.map(walk)\n if (node !== null && typeof node === 'object')\n return Object.fromEntries(Object.entries(node).map(([key, child]) => [key, isSecretName(key) ? REDACTED : walk(child)]))\n return node\n }\n return JSON.stringify(walk(parsed))\n}\n\n/** An MCP server's arguments with every secret-looking value replaced by {@link REDACTED}. */\nexport function redactArgs(args: readonly string[]): string[] {\n const out: string[] = []\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!\n if (!arg.startsWith('-')) {\n out.push(redactValue(arg))\n continue\n }\n const eq = arg.indexOf('=')\n const flag = eq > 0 ? arg.slice(0, eq) : arg\n if (eq > 0) {\n const value = arg.slice(eq + 1)\n out.push(`${flag}=${HEADER_FLAGS.has(flag) ? redactHeader(value) : isSecretName(flag) ? REDACTED : redactValue(value)}`)\n continue\n }\n out.push(scrubKnownTokens(arg))\n const next = args[i + 1]\n if (next === undefined || next.startsWith('-'))\n continue\n if (HEADER_FLAGS.has(flag)) {\n out.push(redactHeader(next))\n i++\n }\n else if (isSecretName(flag)) {\n out.push(REDACTED)\n i++\n }\n }\n return out\n}\n","/**\n * What a host discovered, as the settings tabs list it (`catalog.*`): the\n * same scans and gates the host's agents use (`composeSessionSkills`,\n * `discoverSessionMcpServers`, the plugin gates), each entry with whether\n * the host's settings enable it. Wire-safe and secret-free: an MCP server's\n * `env` / `headers` values never leave the host, and its URL and arguments\n * go through `./redact` (credentials, query / fragment values, header and\n * secret-flag values, secret `KEY=VALUE` pairs, token-shaped values).\n */\nimport type { McpServerStatus } from '../../chat/mcp-status'\nimport type { DiscoveredMcp, DiscoveryError } from '../../chat/mcps-discovery'\nimport type { DiscoveredPlugin } from '../../chat/plugins-discovery'\nimport type { LoadedExtension, LoadedPluginRecord } from '../../extensions/index'\nimport type { SkillConfig } from '../../skills/index'\nimport type { HostCatalogError, HostCatalogExtension, HostCatalogMcp, HostCatalogPlugin, HostCatalogSkill, HostSettings } from '../protocol'\nimport { REDACTED } from '../protocol'\nimport { redactArgs, redactUrl } from './redact'\n\nconst allows = (list: readonly string[] | undefined, name: string): boolean => list === undefined || list.includes(name)\n\n/**\n * Disk skills (gated by `enabledSkills`), then plugin and extension skills\n * (gated by their plugin / extension, so always on here), later ones winning\n * a name like the agent's own merge (`mergeSkillCatalog`).\n */\nexport function skillEntries(input: { disk: readonly SkillConfig[], plugin: readonly SkillConfig[], extension: readonly SkillConfig[], settings: HostSettings }): HostCatalogSkill[] {\n const byName = new Map<string, HostCatalogSkill>()\n const add = (skill: SkillConfig, origin: HostCatalogSkill['origin']): void => {\n const contributedBy = origin === 'plugin' ? skill.metadata?.['zidane.plugin'] : origin === 'extension' ? skill.metadata?.['zidane.extension'] : undefined\n byName.set(skill.name, {\n name: skill.name,\n description: skill.description,\n ...(skill.source ? { source: skill.source } : {}),\n ...(skill.location ? { location: skill.location } : {}),\n origin,\n ...(contributedBy ? { contributedBy } : {}),\n enabled: origin === 'disk' ? allows(input.settings.enabledSkills, skill.name) : true,\n toggleable: origin === 'disk',\n })\n }\n for (const skill of input.disk)\n add(skill, 'disk')\n for (const skill of input.plugin)\n add(skill, 'plugin')\n for (const skill of input.extension)\n add(skill, 'extension')\n return [...byName.values()].sort((a, b) => a.name.localeCompare(b.name))\n}\n\nfunction redactValues(record: Readonly<Record<string, string>> | undefined): Record<string, string> | undefined {\n if (!record)\n return undefined\n return Object.fromEntries(Object.keys(record).map(key => [key, REDACTED]))\n}\n\nexport function mcpEntries(servers: readonly DiscoveredMcp[], errors: readonly DiscoveryError[], settings: HostSettings, statuses: ReadonlyMap<string, McpServerStatus>): { servers: HostCatalogMcp[], errors: HostCatalogError[] } {\n return {\n servers: servers.map(({ config, source, path }) => {\n const env = redactValues(config.env)\n const headers = redactValues(config.headers)\n const status = statuses.get(config.name)\n return {\n name: config.name,\n transport: config.transport,\n source,\n path,\n enabled: allows(settings.enabledMcps, config.name),\n toggleable: true,\n ...(config.command !== undefined ? { command: config.command } : {}),\n ...(config.args ? { args: redactArgs(config.args) } : {}),\n ...(config.url !== undefined ? { url: redactUrl(config.url) } : {}),\n ...(config.cwd !== undefined ? { cwd: config.cwd } : {}),\n // Always said for a stdio server, so a client knows where it runs (and whether it can share it).\n ...(config.transport === 'stdio' ? { scope: config.scope === 'context' ? 'context' as const : 'host' as const } : {}),\n ...(config.shared !== undefined ? { shared: config.shared } : {}),\n ...(config.auth !== undefined ? { auth: config.auth } : {}),\n ...(env ? { env } : {}),\n ...(headers ? { headers } : {}),\n ...(status ? { status } : {}),\n }\n }),\n errors: errors.map(e => ({ path: e.path, source: e.source, message: e.message, ...(e.informational ? { informational: true } : {}) })),\n }\n}\n\nfunction capabilities(contributions: NonNullable<LoadedExtension['contributions']>): string[] {\n const labels: string[] = []\n const add = (label: string, present: boolean): void => {\n if (present)\n labels.push(label)\n }\n add('agents', Object.keys(contributions.agents).length > 0)\n add('providers', Object.keys(contributions.providers).length > 0)\n add('tools', Object.keys(contributions.tools).length > 0)\n add('hooks', Object.values(contributions.hooks).some(handlers => handlers !== undefined && handlers.length > 0))\n add('mcps', contributions.mcpServers.length > 0)\n add('skills', contributions.skills.length > 0)\n add('commands', contributions.commands.length > 0)\n add('completions', contributions.completionProviders.length > 0)\n add('themes', Object.keys(contributions.themes).length > 0)\n add('system', contributions.systemFragments.length > 0)\n return labels\n}\n\n/** Loaded, then inactive (disabled or broken), first one of a name wins. */\nexport function extensionEntries(loaded: readonly LoadedExtension[], inactive: readonly LoadedExtension[], settings: HostSettings): HostCatalogExtension[] {\n const rows = new Map<string, HostCatalogExtension>()\n for (const ext of [...loaded, ...inactive]) {\n if (rows.has(ext.name))\n continue\n rows.set(ext.name, {\n name: ext.name,\n source: ext.source,\n enabled: !ext.error && allows(settings.enabledExtensions, ext.name),\n toggleable: !ext.error,\n ...(ext.definition?.version ? { version: ext.definition.version } : {}),\n ...(ext.definition?.description ? { description: ext.definition.description } : {}),\n ...(ext.dir ? { dir: ext.dir } : {}),\n ...(ext.error ? { error: ext.error } : {}),\n ...(ext.contributions ? { capabilities: capabilities(ext.contributions) } : {}),\n })\n }\n return [...rows.values()].sort((a, b) => a.name.localeCompare(b.name))\n}\n\ninterface PluginSource { plugin: DiscoveredPlugin['plugin'], name: string, origin: HostCatalogPlugin['origin'] }\n\n/** Disk plugins, then the ones extensions loaded (a name on disk wins, as the agent's gate decides). */\nexport function pluginEntries(disk: readonly DiscoveredPlugin[], fromExtensions: readonly LoadedPluginRecord[], settings: HostSettings): HostCatalogPlugin[] {\n const sources: PluginSource[] = [\n ...disk.map(p => ({ plugin: p.plugin, name: p.name, origin: { kind: 'disk' as const, scope: p.source, dir: p.path } })),\n ...fromExtensions.map(r => ({ plugin: r.plugin, name: r.name, origin: { kind: 'extension' as const, extensionName: r.extensionName, dir: r.dir } })),\n ]\n const rows = new Map<string, HostCatalogPlugin>()\n for (const { plugin, name, origin } of sources) {\n if (rows.has(name))\n continue\n const error = plugin.ok ? undefined : plugin.diagnostics.find(d => d.severity === 'error')?.message\n rows.set(name, {\n name,\n origin,\n ok: plugin.ok,\n enabled: plugin.ok && allows(settings.enabledPlugins, name),\n toggleable: plugin.ok,\n ...(plugin.manifest?.version !== undefined ? { version: plugin.manifest.version } : {}),\n ...(plugin.manifest?.description !== undefined ? { description: plugin.manifest.description } : {}),\n skills: plugin.skills.map(s => s.name),\n mcpServers: plugin.mcpServers.map(s => s.name),\n ...(error ? { error } : {}),\n })\n }\n return [...rows.values()].sort((a, b) => a.name.localeCompare(b.name))\n}\n","/**\n * What the host discovered for its settings tabs (`catalog.*`), the agent\n * profiles a folder offers (`agents.list`) and the models its credentials\n * can run (`models.list`), so a window on a server lists the server's\n * skills, MCP servers, extensions, plugins, agents and providers, not its own.\n * An MCP server's row carries its state on the host (sign-in, tools, last\n * Test: `mcp.test`, `mcp.signOut`), and the server processes its sessions\n * share can be listed and restarted (`mcp.instances`, `mcp.restart`).\n */\nimport type { ProviderKey } from '../../../chat/auth'\nimport type { ResolvedConfig } from '../../../chat/config'\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { MachineProject } from '../../../chat/host/machines'\nimport type { McpStatusTracker } from '../../../chat/mcp-status'\nimport type { DiscoveredPlugin } from '../../../chat/plugins-discovery'\nimport type { HostModelProvider } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { Handlers } from './types'\nimport { availableAgents } from '../../../chat/agents'\nimport { detectAuth } from '../../../chat/auth'\nimport { listDecisionModels, testDecisionModel } from '../../../chat/decision-models'\nimport { machineDiscoveryCwd } from '../../../chat/host/machines'\nimport { createProviderBuilder } from '../../../chat/host/models/index'\nimport { listImageModels } from '../../../chat/image-models'\nimport { discoverProjectMcps } from '../../../chat/mcps-discovery'\nimport { testModel } from '../../../chat/model-test'\nimport { buildPluginContributions, discoverProjectPlugins } from '../../../chat/plugins-discovery'\nimport { scopeCwd } from '../../../chat/session-cwd'\nimport { discoverProjectSkills } from '../../../chat/skills-discovery'\nimport { filterRegistryPlugins } from '../../../extensions/index'\nimport { extensionEntries, mcpEntries, pluginEntries, skillEntries } from '../catalog-entries'\nimport { optionalString, requiredString } from './params'\n\ntype CatalogMethod = 'catalog.skills' | 'catalog.mcps' | 'catalog.extensions' | 'catalog.plugins' | 'agents.list' | 'models.list' | 'models.test' | 'decisions.test' | 'mcp.test' | 'mcp.signOut' | 'mcp.instances' | 'mcp.restart'\n\nconst kindOf = (kind: unknown): string | undefined => (typeof kind === 'string' ? kind : undefined)\n\n/**\n * The folder a catalog scans: `cwd` (inside the roots on a server), else the\n * host user's home. A machine's folder (`docs/MACHINES.md` § Folders) is\n * never read here: a folder of this host's stands in for the user scope.\n */\nexport function catalogFolder({ env, host }: { env: Pick<DaemonEnvironment, 'userDataDir'>, host: Pick<ChatHost, 'resolveFolder'> }, cwd: unknown, kind?: unknown): string {\n if (cwd !== undefined && typeof cwd !== 'string')\n throw new Error('cwd must be a string.')\n if (!cwd)\n return scopeCwd('')\n const folder = host.resolveFolder(cwd, kindOf(kind))\n return folder.machine ? machineDiscoveryCwd(env.userDataDir()) : scopeCwd(folder.cwd)\n}\n\nexport function createCatalogHandlers({ env, host, mcpStatus }: {\n env: DaemonEnvironment\n host: Pick<ChatHost, 'resolveFolder' | 'folderCatalog' | 'mcpServers'>\n mcpStatus: McpStatusTracker\n}): Handlers<CatalogMethod> {\n const folderOf = (cwd: unknown, kind?: unknown): string => catalogFolder({ env, host }, cwd, kind)\n /** User scope here, project scope read on the machine for a machine's folder. */\n const catalogOf = async (cwd: unknown, kind: unknown, prefix: string): Promise<{ dir: string, project?: MachineProject }> => {\n if (typeof cwd !== 'string' || !cwd || !host.resolveFolder(cwd, kindOf(kind)).machine)\n return { dir: folderOf(cwd, kind) }\n const { discoveryCwd, project } = await host.folderCatalog(cwd, kindOf(kind), prefix)\n return { dir: discoveryCwd, ...(project ? { project } : {}) }\n }\n const scanFlags = () => {\n const settings = env.readSettings()\n return { settings, foreignAgents: settings.importForeignConfigs === true, ruler: settings.importRulerConfigs !== false }\n }\n /** A folder's MCP servers: a machine's project ones first, as in its sessions. */\n const mcpsOf = async (cwd: unknown, kind: unknown) => {\n const { dir, project } = await catalogOf(cwd, kind, env.config.prefix)\n const config = await env.runtimeConfig(dir)\n const { foreignAgents, ruler } = scanFlags()\n const { servers: found, errors } = discoverProjectMcps({ cwd: dir, prefix: config.prefix, foreignAgents, ruler })\n const machineNames = new Set((project?.mcps ?? []).map(server => server.config.name))\n return { servers: [...(project?.mcps ?? []), ...found.filter(server => !machineNames.has(server.config.name))], errors }\n }\n const plugins = async (dir: string, config: ResolvedConfig): Promise<DiscoveredPlugin[]> => {\n const { plugins: found } = await discoverProjectPlugins({\n cwd: dir,\n prefix: config.prefix,\n ...(config.pluginScanPaths.length > 0 ? { extraRoots: config.pluginScanPaths } : {}),\n })\n return found\n }\n\n return {\n 'catalog.skills': async (p) => {\n const { dir, project } = await catalogOf(p?.cwd, p?.kind, env.config.prefix)\n const config = await env.runtimeConfig(dir)\n const { settings, foreignAgents, ruler } = scanFlags()\n const [found, discovered] = await Promise.all([\n discoverProjectSkills({ cwd: dir, prefix: config.prefix, foreignAgents, ruler }),\n plugins(dir, config),\n ])\n // A machine's project skills first: project beats user, as in its sessions.\n const machineNames = new Set((project?.skills ?? []).map(skill => skill.name))\n const disk = [...(project?.skills ?? []), ...found.filter(skill => !machineNames.has(skill.name))]\n const pluginSkills = buildPluginContributions({ discovered, ...(settings.enabledPlugins !== undefined ? { enabled: settings.enabledPlugins } : {}) }).skills\n const live = filterRegistryPlugins(config.extensions, settings.enabledPlugins, new Set(discovered.map(d => d.name)))\n return { skills: skillEntries({ disk, plugin: pluginSkills, extension: live.skills, settings }) }\n },\n 'catalog.mcps': async (p) => {\n const { servers, errors } = await mcpsOf(p?.cwd, p?.kind)\n return mcpEntries(servers, errors, env.readSettings(), mcpStatus.statuses(servers.map(server => server.config)))\n },\n 'mcp.test': async (p) => {\n const name = requiredString(p.name, 'name')\n const found = (await mcpsOf(p.cwd, p.kind)).servers.find(server => server.config.name === name)\n if (!found)\n throw new Error(`No MCP server \"${name}\" in that folder's catalog.`)\n await mcpStatus.test(found.config)\n return mcpStatus.statuses([found.config]).get(name)!\n },\n 'mcp.signOut': (p) => {\n mcpStatus.signOut(requiredString(p.name, 'name'))\n },\n 'mcp.instances': p => host.mcpServers.instances(optionalString(p?.cwd, 'cwd')),\n 'mcp.restart': async p => ({\n restarted: await host.mcpServers.restart(requiredString(p?.name, 'name'), optionalString(p?.cwd, 'cwd')),\n }),\n 'catalog.extensions': async (p) => {\n const config = await env.runtimeConfig(folderOf(p?.cwd, p?.kind))\n return { extensions: extensionEntries(config.extensions.loaded, config.extensions.inactive, env.readSettings()) }\n },\n 'catalog.plugins': async (p) => {\n const dir = folderOf(p?.cwd, p?.kind)\n const config = await env.runtimeConfig(dir)\n return { plugins: pluginEntries(await plugins(dir, config), config.extensions.plugins, env.readSettings()) }\n },\n // A profile a setting turns off (Codemode) is not offered.\n 'agents.list': async (p) => {\n const config = await env.runtimeConfig(folderOf(p.cwd))\n return Object.values(availableAgents(config.agents, env.readSettings())).map(a => ({ id: a.id, label: a.label, description: a.description, accent: a.accent ?? 'accent' }))\n },\n 'models.list': async (p) => {\n const config = p?.cwd ? await env.runtimeConfig(folderOf(p.cwd, p.kind)) : env.config\n const authed = detectAuth(env.userDataDir(), config.providers).filter(auth => auth.available)\n // Decision and image availability read stored API keys from the environment.\n env.applyAuthEnv?.()\n const decisionModels = listDecisionModels({ providers: config.providers, authed })\n const imageModels = listImageModels({ providers: config.providers, authed })\n const providers: HostModelProvider[] = authed.map((auth) => {\n const decisions = decisionModels\n .filter(entry => entry.providerKey === auth.key)\n .map(entry => ({ id: entry.modelId, available: entry.available, ...(entry.reason ? { reason: entry.reason } : {}) }))\n const images = imageModels\n .filter(entry => entry.providerKey === auth.key)\n .map(entry => ({\n id: entry.modelId,\n name: entry.modelName,\n references: entry.references,\n transparency: entry.transparency,\n available: entry.available,\n ...(entry.reason ? { reason: entry.reason } : {}),\n ...(entry.isDefault ? { isDefault: true } : {}),\n }))\n return {\n key: auth.key,\n label: config.providers[auth.key]?.label ?? auth.label,\n // JSON copies: `ModelInfo` is data, but a provider may hand out frozen or shared arrays.\n models: JSON.parse(JSON.stringify(config.modelsFor(auth.key))) as HostModelProvider['models'],\n ...(auth.accounts ? { accounts: auth.accounts.map(({ id, label, active }) => ({ id, label, active })) } : {}),\n ...(decisions.length > 0 ? { decisionModels: decisions } : {}),\n ...(images.length > 0 ? { imageModels: images } : {}),\n }\n })\n return { providers }\n },\n 'models.test': async (p) => {\n if (typeof p?.model !== 'string' || !p.model)\n throw new Error('model must be a \"provider/model\" string.')\n const config = p.cwd ? await env.runtimeConfig(folderOf(p.cwd, p.kind)) : env.config\n const build = createProviderBuilder(env)\n return testModel({\n providers: config.providers,\n buildProvider: (key, account) => build(config.providers, key as ProviderKey, account),\n model: p.model,\n })\n },\n 'decisions.test': async (p) => {\n const config = p?.cwd ? await env.runtimeConfig(folderOf(p.cwd, p.kind)) : env.config\n env.applyAuthEnv?.()\n const model = typeof p?.model === 'string' ? p.model : env.readSettings().decisionModel\n return testDecisionModel({\n providers: config.providers,\n buildProvider: (key) => {\n const descriptor = config.providers[key]\n if (!descriptor)\n throw new Error(`Provider \"${key}\" is not configured`)\n return descriptor.factory()\n },\n ...(model ? { decisionModel: model } : {}),\n })\n },\n }\n}\n","/**\n * Session artifacts: list, delete, upsert, re-resolve (a kind's `resolve()`,\n * run here with the extensions of the folder the artifact landed in), with\n * change fan-out, and the sidebar rows' badges.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { ExtensionRegistry } from '../../../extensions/index'\nimport type { SessionStore } from '../../../session/index'\nimport type { HostSignal } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { Handlers } from './types'\nimport { ARTIFACT_BADGES_MAX, refreshArtifact, sessionsBadges } from '../../../extensions/index'\nimport { normalizeArtifactInput } from '../../../session/artifacts'\nimport { catalogFolder } from './catalogs'\nimport { InvalidParamsError, sessionIdOf } from './params'\n\n/** Wire-supplied limit → sane positive integer capped at 1000, else `undefined` (no limit). */\nfunction boundedLimit(raw: unknown): number | undefined {\n return Number.isInteger(raw) && (raw as number) > 0 ? Math.min(raw as number, 1000) : undefined\n}\n\nexport function createArtifactHandlers({ store, broadcast, env, host }: {\n store: SessionStore\n broadcast: (signal: HostSignal) => void\n env: DaemonEnvironment\n host: Pick<ChatHost, 'resolveFolder'>\n}): Handlers<'sessions.artifacts' | 'artifacts.list' | 'artifacts.delete' | 'artifacts.upsert' | 'artifacts.refresh' | 'artifacts.badges'> {\n /** The registry of the folder an artifact landed in; `undefined` (the built-in kinds) when it can't be built (a folder gone, or outside the roots). */\n const registryOf = async (projectRoot: string | undefined): Promise<ExtensionRegistry | undefined> => {\n try {\n return (await env.runtimeConfig(catalogFolder({ env, host }, projectRoot ?? ''))).extensions\n }\n catch {\n return undefined\n }\n }\n return {\n 'sessions.artifacts': async (p) => {\n if (!store.listArtifacts)\n return []\n return store.listArtifacts({\n sessionId: p.sessionId,\n ...(typeof p.kind === 'string' ? { kind: p.kind } : {}),\n ...(boundedLimit(p.limit) !== undefined ? { limit: boundedLimit(p.limit) } : {}),\n })\n },\n 'artifacts.list': async (p) => {\n if (!store.listArtifacts)\n return []\n return store.listArtifacts({\n // Tri-state: `null` selects untagged sessions, omitted ignores the axis.\n ...(p.projectRoot === null || typeof p.projectRoot === 'string' ? { projectRoot: p.projectRoot } : {}),\n ...(typeof p.kind === 'string' ? { kind: p.kind } : {}),\n ...(typeof p.uri === 'string' ? { uri: p.uri } : {}),\n ...(typeof p.since === 'number' && Number.isFinite(p.since) ? { since: p.since } : {}),\n ...(boundedLimit(p.limit) !== undefined ? { limit: boundedLimit(p.limit) } : {}),\n })\n },\n 'artifacts.delete': async (p) => {\n if (!store.deleteArtifact)\n return false\n await store.deleteArtifact(p.sessionId, p.artifactId)\n broadcast({ kind: 'artifact:changed', sessionId: p.sessionId, op: 'delete', artifactId: p.artifactId })\n return true\n },\n 'artifacts.upsert': async (p) => {\n if (!store.upsertArtifact)\n return null\n // Wire input: re-normalize the presentation fields (bounds, kind\n // shape) before trusting them; identity fields pass through since\n // the store merges onto the existing row anyway.\n const normalized = normalizeArtifactInput(p.artifact)\n if (!normalized || typeof p.artifact?.sessionId !== 'string' || typeof p.artifact?.id !== 'string')\n return null\n const now = Date.now()\n const stored = await store.upsertArtifact({\n ...normalized,\n id: p.artifact.id,\n sessionId: p.artifact.sessionId,\n ...(typeof p.artifact.runId === 'string' ? { runId: p.artifact.runId } : {}),\n ...(typeof p.artifact.turnId === 'string' ? { turnId: p.artifact.turnId } : {}),\n createdAt: typeof p.artifact.createdAt === 'number' ? p.artifact.createdAt : now,\n updatedAt: now,\n })\n if (stored)\n broadcast({ kind: 'artifact:changed', sessionId: stored.sessionId, op: 'upsert', artifactId: stored.id, artifact: stored })\n return stored\n },\n 'artifacts.refresh': async (p) => {\n const sessionId = sessionIdOf(p)\n if (!store.listArtifacts || !store.upsertArtifact)\n return null\n const artifact = (await store.listArtifacts({ sessionId })).find(a => a.id === p.artifactId)\n if (!artifact)\n return null\n const updated = await refreshArtifact(artifact, await registryOf(artifact.projectRoot), p.force === true ? { force: true } : undefined)\n if (!updated)\n return null\n const stored = await store.upsertArtifact(updated)\n if (stored)\n broadcast({ kind: 'artifact:changed', sessionId: stored.sessionId, op: 'upsert', artifactId: stored.id, artifact: stored })\n return stored\n },\n 'artifacts.badges': async (p) => {\n const ids: unknown = p.sessionIds\n if (!Array.isArray(ids) || ids.length > ARTIFACT_BADGES_MAX || ids.some(id => typeof id !== 'string'))\n throw new InvalidParamsError(`sessionIds must be an array of at most ${ARTIFACT_BADGES_MAX} session ids.`)\n if (!store.listArtifacts)\n return {}\n const list = store.listArtifacts.bind(store)\n const lists = Object.fromEntries(await Promise.all([...new Set(ids as string[])].map(async sessionId => [sessionId, await list({ sessionId })] as const)))\n const roots = [...new Set(Object.values(lists).flat().map(a => a.projectRoot ?? ''))]\n const registries = new Map(await Promise.all(roots.map(async root => [root, await registryOf(root)] as const)))\n return sessionsBadges(lists, root => registries.get(root))\n },\n }\n}\n","/**\n * The host's provider credentials, managed by a client (Settings on a\n * window attached to a zidane-server): status, set an API key (with a\n * provider's custom fields: `auth.configure`), remove, pick the active\n * stored credential, rename an OAuth account.\n * Secrets go in, never out: statuses carry sources, labels and env var\n * names only, and nothing here logs a key.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { ProviderDescriptor } from '../../../chat/providers'\nimport type { HostProviderAuth } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { Handlers } from './types'\nimport { detectAuth } from '../../../chat/auth'\nimport { applyApiKeyEnv, configuredProviderFields, configureProviderCredential, providerFieldViews, readProviderCredentials, removeProviderCredential, removeStoredCredential, setCredentialLabel, setPreferredCredential, setProviderCredential } from '../../../chat/credentials'\nimport { InvalidParamsError } from './params'\n\n/** Longest API key accepted (keys are well under 1 KiB; this bounds a mistaken paste). */\nconst MAX_KEY_LENGTH = 8192\n/** Longest account name accepted. */\nconst MAX_LABEL_LENGTH = 200\n\nexport type ProviderAuth = ReturnType<typeof createProviderAuth>\n\n/** The host's providers and their credentials: lookups, statuses, and applying a change. */\nexport function createProviderAuth({ host, env }: { host: Pick<ChatHost, 'rebuildAllAgents'>, env: DaemonEnvironment }) {\n const registry = (): Readonly<Record<string, ProviderDescriptor>> => env.config.providers\n const dataDir = (): string => env.userDataDir()\n\n const descriptorOf = (provider: unknown): ProviderDescriptor => {\n const descriptor = typeof provider === 'string' ? registry()[provider] : undefined\n if (!descriptor)\n throw new Error(`Unknown provider \"${String(provider)}\".`)\n return descriptor\n }\n\n const statusOf = (key: string): HostProviderAuth => {\n const descriptor = registry()[key]!\n const auth = detectAuth(dataDir(), { [key]: descriptor })[0]!\n const customFields = providerFieldViews(descriptor)\n const configuredFields = configuredProviderFields(dataDir(), descriptor)\n return {\n key: auth.key,\n label: auth.label,\n configured: auth.available,\n oauth: registry()[key]?.oauthProvider !== undefined,\n ...(auth.envKey ? { envKey: auth.envKey } : {}),\n methods: auth.methods.map(m => ({\n source: m.source,\n active: m.active === true,\n ...(m.key !== undefined ? { key: m.key } : {}),\n ...(m.label !== undefined ? { label: m.label } : {}),\n detail: m.detail,\n })),\n ...(customFields ? { customFields } : {}),\n ...(configuredFields ? { configuredFields } : {}),\n }\n }\n\n /** The stored API key values of a provider (to clear them from the environment once removed). */\n const storedKeys = (descriptor: ProviderDescriptor): string[] =>\n readProviderCredentials(dataDir(), descriptor).flatMap(s => s.credential.kind === 'apikey' && s.credential.value ? [s.credential.value] : [])\n\n /** Make the change take effect: env re-applied, a removed key out of it, agents rebuilt. */\n const applied = (descriptor: ProviderDescriptor, removedKeys: readonly string[] = []): void => {\n if (env.applyAuthEnv)\n env.applyAuthEnv()\n else\n applyApiKeyEnv(dataDir(), registry(), { log: () => undefined })\n // `applyApiKeyEnv` leaves the env alone when nothing is stored; a key it\n // put there earlier must not outlive its removal.\n const envKey = descriptor.envKey\n if (envKey && removedKeys.includes(process.env[envKey] ?? '') && !storedKeys(descriptor).includes(process.env[envKey]!))\n delete process.env[envKey]\n void host.rebuildAllAgents().catch(() => undefined)\n }\n\n return { registry, dataDir, descriptorOf, statusOf, storedKeys, applied }\n}\n\nexport function createAuthHandlers({ auth }: { auth: ProviderAuth }): Handlers<'auth.status' | 'auth.setApiKey' | 'auth.configure' | 'auth.remove' | 'auth.setPreferred' | 'auth.rename'> {\n const { registry, dataDir, descriptorOf, statusOf, storedKeys, applied } = auth\n return {\n 'auth.status': () => ({ providers: Object.keys(registry()).map(statusOf) }),\n 'auth.setApiKey': (p) => {\n const descriptor = descriptorOf(p.provider)\n const key = typeof p.key === 'string' ? p.key.trim() : ''\n if (!key)\n throw new Error('The API key is empty.')\n if (key.length > MAX_KEY_LENGTH)\n throw new Error(`The API key is longer than ${MAX_KEY_LENGTH} characters.`)\n setProviderCredential(dataDir(), descriptor, { kind: 'apikey', value: key })\n applied(descriptor)\n return statusOf(descriptor.key)\n },\n 'auth.configure': (p) => {\n const descriptor = descriptorOf(p.provider)\n if (p.value !== undefined && (typeof p.value !== 'string' || p.value.length > MAX_KEY_LENGTH))\n throw new InvalidParamsError(`value must be a string of at most ${MAX_KEY_LENGTH} characters.`)\n const fields = p.customFields ?? {}\n if (typeof fields !== 'object' || Array.isArray(fields) || Object.values(fields).some(v => typeof v !== 'string' || v.length > MAX_KEY_LENGTH))\n throw new InvalidParamsError('customFields must map field keys to strings.')\n configureProviderCredential(dataDir(), descriptor, { ...(p.value !== undefined ? { value: p.value } : {}), customFields: fields })\n applied(descriptor)\n return statusOf(descriptor.key)\n },\n 'auth.remove': (p) => {\n const descriptor = descriptorOf(p.provider)\n const before = storedKeys(descriptor)\n let removed: boolean\n if (typeof p.account === 'string') {\n removed = removeStoredCredential(dataDir(), descriptor, p.account)\n }\n else {\n removed = readProviderCredentials(dataDir(), descriptor).length > 0\n removeProviderCredential(dataDir(), descriptor)\n }\n if (removed)\n applied(descriptor, before.filter(k => !storedKeys(descriptor).includes(k)))\n return { removed, provider: statusOf(descriptor.key) }\n },\n 'auth.setPreferred': (p) => {\n const descriptor = descriptorOf(p.provider)\n const target = p.target\n const key = typeof target === 'object' && target !== null ? (target as { key?: unknown }).key : undefined\n if (target !== 'apikey' && target !== 'oauth' && typeof key !== 'string')\n throw new InvalidParamsError('target must be \"apikey\", \"oauth\" or { key }.')\n const outcome = setPreferredCredential(dataDir(), descriptor, typeof key === 'string' ? { key } : target as 'apikey' | 'oauth')\n if (outcome === 'not-stored')\n throw new Error(`No stored ${typeof key === 'string' ? `credential ${key}` : `${String(target)} credential`} for ${descriptor.label}.`)\n if (outcome !== 'already-active')\n applied(descriptor)\n return statusOf(descriptor.key)\n },\n 'auth.rename': (p) => {\n const descriptor = descriptorOf(p.provider)\n if (typeof p.account !== 'string' || typeof p.label !== 'string' || p.label.length > MAX_LABEL_LENGTH)\n throw new InvalidParamsError(`account must be a string and label a string of at most ${MAX_LABEL_LENGTH} characters.`)\n if (!setCredentialLabel(dataDir(), descriptor, p.account, p.label))\n throw new Error(`No stored OAuth account ${p.account} for ${descriptor.label}.`)\n return statusOf(descriptor.key)\n },\n }\n}\n","/** Browser hosts a client registers to serve the agent's browser tool. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\n\nexport function createBrowserHandlers({ host }: { host: ChatHost }): {\n methods: Handlers<'browser.registerHost' | 'browser.unregisterHost' | 'browser.respond'>\n /** The peer dropped: release the browser hosts it registered. */\n releasePeer: (peer: HostPeer) => void\n} {\n return {\n methods: {\n 'browser.registerHost': (p, peer) => {\n ;(peer.browserHosts ??= new Set()).add(p.hostId)\n host.browser.registerHost(p.hostId)\n return { ok: true }\n },\n 'browser.unregisterHost': (p, peer) => {\n peer.browserHosts?.delete(p.hostId)\n host.browser.unregisterHost(p.hostId)\n return { ok: true }\n },\n 'browser.respond': (p, peer) => host.browser.respond(p.requestId, p.response, peer.browserHosts ?? new Set()),\n },\n releasePeer(peer) {\n for (const hostId of peer.browserHosts ?? [])\n host.browser.unregisterHost(hostId)\n },\n }\n}\n","/**\n * Installs and removals from a client (`catalog.install` / `remove` /\n * `update`, `mcp.upsert` / `remove`, a new extension's scaffold\n * `extensions.create`): the local Settings actions, run on the host for a\n * window attached to a zidane-server. The Claude Code import goes through\n * the same gate (`guardedInstall`, `./onboarding`).\n *\n * Scope: the host user's only (`~/.agents/*`, `~/.<prefix>/*`). A\n * project's skills, extensions and MCP servers are files in its folder,\n * which the agent and the files panel already edit; installing into one\n * from a client would run a package manager inside a workspace for no gain.\n *\n * Installs fetch code and may run package managers ON THE HOST, so a\n * zidane-server gates them (`allowRemoteInstalls`, on by default: a client\n * token already runs commands there) and audits every attempt, refused or\n * failed ones too, with the token. Specs are GitHub or npm only (a path is\n * refused), work is bounded in time, progress lines come back with the\n * result. MCP `env` / `headers` values go into the host's `mcps.json` and\n * never come back. After a change the host rebuilds what reads it and\n * every window gets `catalog:changed`.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostSettings } from '../../../chat/host/signals'\nimport type { InstallIo } from '../../../install/source'\nimport type { McpServerConfig } from '../../../types'\nimport type { HostCatalogName, HostSignal } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { existsSync, rmSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport { enabledMcpsWith, enabledMcpsWithout } from '../../../chat/mcp-allowlist'\nimport { createFileMcpCredentialStore } from '../../../chat/mcp-credentials'\nimport { isMcpServerName, mcpsWritePath, removeMcpServer, upsertMcpServer } from '../../../chat/mcps-write'\nimport { findGitRoot } from '../../../chat/project-root'\nimport { projectUserPaths } from '../../../chat/project-user-paths'\nimport { createExtension } from '../../../extension-authoring'\nimport { ExtensionInstallError, installExtensionFromSpec, removeInstalledExtension, updateInstalledExtension } from '../../../extensions/install'\nimport { abortableInstallIo } from '../../../install/source'\nimport { saveMcpClientSecret } from '../../../mcp/oauth-provider'\nimport { installSkillFromSpec } from '../../../skills/install'\nimport { InvalidParamsError } from './params'\n\nexport interface RemoteInstallsOptions {\n /** `allowRemoteInstalls`, read at each call. */\n allowed: () => boolean\n /** One audit line per attempt (the server adds the connection's token). */\n audit?: (peer: HostPeer, entry: Record<string, unknown>) => void\n /** Test seam: the installers' fetch / exec / which. */\n io?: InstallIo\n /** Bound on one install or update. Default 5 minutes. */\n timeoutMs?: number\n}\n\ntype InstallMethod = 'catalog.install' | 'catalog.remove' | 'catalog.update' | 'mcp.upsert' | 'mcp.remove' | 'extensions.create'\n\nconst DEFAULT_TIMEOUT_MS = 5 * 60_000\nconst MAX_SPEC_LENGTH = 500\nconst MAX_MCP_CONFIG_BYTES = 64 * 1024\nconst NAME_RE = /^[\\w@.-]{1,100}$/\nconst MCP_TRANSPORTS = new Set(['stdio', 'sse', 'streamable-http'])\n\nconst OFF_MESSAGE = 'Installs from clients are off on this server (allowRemoteInstalls is off).'\n\n/** A spec a server may fetch: GitHub or npm. Anything path-like is refused before the parsers see it. */\nfunction checkSpec(spec: unknown): string {\n if (typeof spec !== 'string' || spec.trim() === '')\n throw new InvalidParamsError('spec must be a non-empty string.')\n const value = spec.trim()\n if (value.length > MAX_SPEC_LENGTH)\n throw new InvalidParamsError(`spec is longer than ${MAX_SPEC_LENGTH} characters.`)\n const segments = value.split(/[/:#@]/)\n if (/^(?:[./~\\\\]|file:)/i.test(value) || value.includes('\\\\') || segments.includes('.') || segments.includes('..'))\n throw new InvalidParamsError(`\"${value}\" is a path: a server installs from GitHub (owner/repo, a GitHub URL) or npm only.`)\n return value\n}\n\nfunction checkName(name: unknown, what: string): string {\n if (typeof name !== 'string' || !NAME_RE.test(name) || name === '.' || name === '..')\n throw new InvalidParamsError(`${what} must be a plain name (letters, digits, ., _, -, @).`)\n return name\n}\n\nfunction checkMcpName(name: unknown): string {\n if (!isMcpServerName(name))\n throw new InvalidParamsError('name must be a plain name (letters, digits, ., _, -, @, single spaces inside).')\n return name\n}\n\nfunction checkKind(kind: unknown): 'skill' | 'extension' {\n if (kind !== 'skill' && kind !== 'extension')\n throw new InvalidParamsError('kind must be \"skill\" or \"extension\".')\n return kind\n}\n\nfunction isStringRecord(value: unknown): value is Record<string, string> {\n return typeof value === 'object' && value !== null && !Array.isArray(value) && Object.values(value).every(v => typeof v === 'string')\n}\n\nfunction checkMcpConfig(config: unknown): McpServerConfig {\n if (typeof config !== 'object' || config === null || Array.isArray(config))\n throw new InvalidParamsError('config must be an MCP server object.')\n if (JSON.stringify(config).length > MAX_MCP_CONFIG_BYTES)\n throw new InvalidParamsError(`config is larger than ${MAX_MCP_CONFIG_BYTES} bytes.`)\n const c = config as Record<string, unknown>\n checkMcpName(c.name)\n if (c.transport !== undefined && !MCP_TRANSPORTS.has(c.transport as string))\n throw new InvalidParamsError('transport must be stdio, sse or streamable-http.')\n const hasCommand = typeof c.command === 'string' && c.command.trim() !== ''\n let hasUrl = false\n if (typeof c.url === 'string') {\n try {\n hasUrl = ['http:', 'https:'].includes(new URL(c.url).protocol)\n }\n catch {}\n if (!hasUrl)\n throw new InvalidParamsError('url must be an http(s) URL.')\n }\n if (!hasCommand && !hasUrl)\n throw new InvalidParamsError('An MCP server needs a command (stdio) or a url.')\n if (c.args !== undefined && (!Array.isArray(c.args) || !c.args.every(a => typeof a === 'string')))\n throw new InvalidParamsError('args must be strings.')\n for (const key of ['env', 'headers'] as const) {\n if (c[key] !== undefined && !isStringRecord(c[key]))\n throw new InvalidParamsError(`${key} must map names to strings.`)\n }\n return c as unknown as McpServerConfig\n}\n\n/** How long a stopped install may take to roll back before the refusal is answered anyway. */\nconst ROLLBACK_GRACE_MS = 10_000\n\n/**\n * `run` bounded by `ms`: past it, its signal fires (children killed, no next\n * step: `abortableInstallIo`) and the refusal waits for the installer's own\n * rollback (staging dir, transactional target), up to {@link ROLLBACK_GRACE_MS}.\n */\nasync function bounded<T>(run: (signal: AbortSignal) => Promise<T>, ms: number, what: string): Promise<T> {\n const controller = new AbortController()\n const work = run(controller.signal)\n let timer: ReturnType<typeof setTimeout> | undefined\n try {\n return await Promise.race([work, new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n controller.abort()\n reject(new Error(`${what} took longer than ${Math.round(ms / 1000)}s and was stopped.`))\n }, ms)\n })])\n }\n catch (err) {\n if (controller.signal.aborted) {\n let grace: ReturnType<typeof setTimeout> | undefined\n await Promise.race([work.catch(() => undefined), new Promise((resolve) => {\n grace = setTimeout(resolve, ROLLBACK_GRACE_MS)\n })])\n clearTimeout(grace)\n }\n throw err\n }\n finally {\n clearTimeout(timer)\n }\n}\n\n/**\n * Gate, run, audit a client's install: refused unless the host takes them\n * (`allowRemoteInstalls`); every attempt leaves one line, refusals and\n * failures included.\n */\nexport async function guardedInstall<T>(options: RemoteInstallsOptions | undefined, peer: HostPeer, event: string, fields: Record<string, unknown>, run: () => Promise<T> | T): Promise<T> {\n if (!options)\n throw new Error('This host takes no installs from clients (a zidane-server does, with allowRemoteInstalls on).')\n if (!options.allowed()) {\n options.audit?.(peer, { event, ...fields, ok: false, refused: 'allowRemoteInstalls is off' })\n throw new Error(OFF_MESSAGE)\n }\n try {\n const result = await run()\n options.audit?.(peer, { event, ...fields, ok: true })\n return result\n }\n catch (err) {\n options.audit?.(peer, { event, ...fields, ok: false, error: err instanceof Error ? err.message : String(err) })\n throw err\n }\n}\n\nexport function createCatalogInstallHandlers({ host, env, broadcast, setSettings, options }: {\n host: Pick<ChatHost, 'rebuildAllAgents' | 'workspace' | 'mcpServers'>\n env: DaemonEnvironment\n broadcast: (signal: HostSignal) => void\n /** `settings.set`: writes, rebuilds what the change needs, tells every window. */\n setSettings: (patch: Partial<HostSettings>) => unknown\n options?: RemoteInstallsOptions\n}): Handlers<InstallMethod> {\n const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS\n const io = options?.io\n const prefix = (): string => env.config.prefix\n /** The host user's roots for `subPath` (`~/.agents/<sub>`, `~/.<prefix>/<sub>`), read at call time. */\n const userRoots = (subPath: string): string[] =>\n projectUserPaths({ subPath, cwd: homedir(), home: homedir(), prefix: prefix() }).filter(p => p.source === 'user').map(p => p.path)\n\n const guarded = <T>(peer: HostPeer, event: string, fields: Record<string, unknown>, run: () => Promise<T> | T): Promise<T> =>\n guardedInstall(options, peer, event, fields, run)\n\n const changed = (catalog: HostCatalogName): void => broadcast({ kind: 'catalog:changed', catalog })\n\n /** Skills and MCP servers are read when an agent is built. */\n const rebuild = (): void => {\n void host.rebuildAllAgents({ rediscover: true }).catch(() => undefined)\n }\n\n /** Extensions live in the runtime registry: forget it, rebuild, dispose the old one once idle (as `runtime.reload`). */\n const reloadExtensions = (): void => {\n const disposeOld = env.forgetRuntime()\n void host.rebuildAllAgents({ rediscover: true }).then(disposeOld, disposeOld)\n }\n\n /** `name` dropped from (or added to) an explicit allowlist; an absent list means \"all\", left alone. */\n const allowlist = (key: 'enabledExtensions' | 'enabledSkills', name: string, present: boolean): boolean => {\n const list = env.readSettings()[key]\n if (list === undefined || list.includes(name) === present)\n return false\n setSettings({ [key]: present ? [...list, name] : list.filter(n => n !== name) })\n return true\n }\n\n /** The user-scope install directory named `name` under `subPath`, if any. */\n const userDir = (subPath: string, name: string, marker?: string): string | undefined =>\n userRoots(subPath).map(root => join(root, name)).find(dir => existsSync(marker ? join(dir, marker) : dir))\n\n return {\n 'catalog.install': (p, peer) => guarded(peer, 'catalog.install', { kind: p.kind, spec: typeof p.spec === 'string' ? p.spec.slice(0, MAX_SPEC_LENGTH) : undefined }, async () => {\n const kind = checkKind(p.kind)\n const spec = checkSpec(p.spec)\n if (p.scope !== undefined && p.scope !== 'user')\n throw new InvalidParamsError('A server installs in its user scope only (scope: \"user\").')\n const progress: string[] = []\n const onProgress = (line: string): void => {\n if (progress.length < 200)\n progress.push(line)\n }\n const home = homedir()\n if (kind === 'skill') {\n const result = await bounded(signal => installSkillFromSpec({\n source: spec,\n scope: 'user',\n cwd: home,\n home,\n prefix: prefix(),\n onProgress,\n io: abortableInstallIo(io, signal),\n ...(Array.isArray(p.skills) ? { skills: p.skills.filter(s => typeof s === 'string') } : {}),\n ...(p.all === true ? { all: true } : {}),\n ...(p.overwrite === true ? { overwrite: true } : {}),\n }), timeoutMs, `Installing ${spec}`)\n rebuild()\n changed('skills')\n const skipped = result.skipped?.length ? `. Skipped existing: ${result.skipped.join(', ')}` : ''\n return { installed: [...result.installed], message: `installed ${result.installed.join(', ')} (${result.provenance ?? result.engine})${skipped}`, progress }\n }\n let result\n try {\n result = await bounded(signal => installExtensionFromSpec({\n source: spec,\n scope: 'user',\n cwd: home,\n home,\n prefix: prefix(),\n onProgress,\n io: abortableInstallIo(io, signal),\n ...(typeof p.extension === 'string' ? { extension: p.extension } : {}),\n ...(p.overwrite === true ? { overwrite: true } : {}),\n }), timeoutMs, `Installing ${spec}`)\n }\n catch (err) {\n if (err instanceof ExtensionInstallError && err.code === 'exists')\n throw new Error('already installed on the server: update or remove it first.')\n throw err\n }\n // Enabled in an explicit allowlist (that write reloads the registry); else reload here.\n if (!allowlist('enabledExtensions', result.name, true))\n reloadExtensions()\n changed('extensions')\n const warn = result.warnings.length > 0 ? `. ${result.warnings.join('. ')}` : ''\n return { installed: [result.name], message: `installed \"${result.name}\" (${result.provenance})${warn}`, progress }\n }),\n\n 'catalog.remove': (p, peer) => guarded(peer, 'catalog.remove', { kind: p.kind, name: p.name }, async () => {\n const kind = checkKind(p.kind)\n const name = checkName(p.name, 'name')\n if (kind === 'skill') {\n const dir = userDir('skills', name, 'SKILL.md')\n if (!dir)\n throw new Error(`No user-scope skill \"${name}\" on this server (project skills are files in their folder).`)\n rmSync(dir, { recursive: true, force: true })\n allowlist('enabledSkills', name, false)\n rebuild()\n changed('skills')\n return { removed: name, message: `deleted \"${name}\"` }\n }\n const dir = userDir('extensions', name)\n if (!dir)\n throw new Error(`No user-scope extension \"${name}\" on this server.`)\n removeInstalledExtension({ dir, cwd: homedir(), home: homedir(), prefix: prefix() })\n if (!allowlist('enabledExtensions', name, false))\n reloadExtensions()\n changed('extensions')\n return { removed: name, message: `removed \"${name}\"` }\n }),\n\n 'catalog.update': (p, peer) => guarded(peer, 'catalog.update', { kind: p.kind, name: p.name }, async () => {\n const kind = checkKind(p.kind)\n const name = checkName(p.name, 'name')\n if (kind === 'skill')\n throw new Error('Skills are not updated in place: install again with overwrite.')\n const dir = userDir('extensions', name)\n if (!dir)\n throw new Error(`No user-scope extension \"${name}\" on this server.`)\n const result = await bounded(signal => updateInstalledExtension({ dir, cwd: homedir(), home: homedir(), prefix: prefix(), io: abortableInstallIo(io, signal) }), timeoutMs, `Updating ${name}`)\n if (result.upToDate)\n return { updated: result.name, upToDate: true, message: `\"${result.name}\" is already up to date${result.commit ? ` (${result.commit.slice(0, 7)})` : ''}` }\n reloadExtensions()\n changed('extensions')\n return { updated: result.name, upToDate: false, message: `updated \"${result.name}\" → ${result.provenance}` }\n }),\n\n 'mcp.upsert': (p, peer) => guarded(peer, 'mcp.upsert', { name: (p.config as { name?: unknown } | undefined)?.name, scope: p.scope ?? 'user' }, () => {\n const config = checkMcpConfig(p.config)\n if (p.scope !== undefined && p.scope !== 'user' && p.scope !== 'project')\n throw new InvalidParamsError('scope must be \"user\" or \"project\".')\n if (p.clientSecret !== undefined && (typeof p.clientSecret !== 'string' || p.clientSecret.length > MAX_MCP_CONFIG_BYTES))\n throw new InvalidParamsError('clientSecret must be a string.')\n if (p.scope === 'project' && (typeof p.cwd !== 'string' || !p.cwd))\n throw new InvalidParamsError('A project MCP server needs the project\\'s cwd.')\n // The project's checkout, which must lie in the roots too.\n const folder = p.scope === 'project' ? host.workspace.resolveFolder(p.cwd!) : homedir()\n const cwd = p.scope === 'project' ? host.workspace.resolveFolder(findGitRoot(folder) ?? folder) : folder\n const result = upsertMcpServer(mcpsWritePath(p.scope ?? 'user', { home: homedir(), cwd, prefix: prefix() }), config)\n const store = env.mcpCredentialStore?.() ?? createFileMcpCredentialStore(env.userDataDir())\n // The secret stays out of mcps.json; an entry without an oauth client must not keep sending one.\n if (!config.oauth)\n saveMcpClientSecret(store, config.name, undefined)\n else if (p.clientSecret)\n saveMcpClientSecret(store, config.name, p.clientSecret)\n // Added from a client: on, like a server added in local Settings. An edit keeps its toggle.\n const enabled = result.action === 'added' ? enabledMcpsWith(env.readSettings().enabledMcps, config.name) : undefined\n if (enabled)\n setSettings({ enabledMcps: enabled })\n // An edited server must not keep running on its old config.\n host.mcpServers.retire(config.name)\n rebuild()\n changed('mcps')\n return { name: config.name, created: result.action === 'added' }\n }),\n\n 'mcp.remove': (p, peer) => guarded(peer, 'mcp.remove', { name: p.name }, () => {\n const name = checkMcpName(p.name)\n const path = mcpsWritePath('user', { home: homedir(), cwd: homedir(), prefix: prefix() })\n try {\n removeMcpServer(path, name)\n }\n catch (err) {\n // No file, or no entry of that name: nothing to remove. A malformed file is an error.\n if (!existsSync(path) || /no entry named/.test(err instanceof Error ? err.message : ''))\n return { removed: false }\n throw err\n }\n const enabled = enabledMcpsWithout(env.readSettings().enabledMcps, name)\n if (enabled)\n setSettings({ enabledMcps: enabled })\n host.mcpServers.retire(name)\n rebuild()\n changed('mcps')\n return { removed: true }\n }),\n\n 'extensions.create': (p, peer) => guarded(peer, 'extensions.create', { name: p.name, scope: p.scope ?? 'user' }, () => {\n if (p.scope !== undefined && p.scope !== 'user' && p.scope !== 'project')\n throw new InvalidParamsError('scope must be \"user\" or \"project\".')\n const project = p.scope === 'project'\n if (project && (typeof p.cwd !== 'string' || !p.cwd))\n throw new InvalidParamsError('A project extension needs the project\\'s cwd.')\n const result = createExtension({ name: typeof p.name === 'string' ? p.name : '', ...(project ? { scope: 'project', cwd: p.cwd } : {}) }, {\n userDir: join(homedir(), prefix()),\n // The checkout holding `cwd`, which must lie in the roots too: the session that writes the extension works there.\n resolveCheckoutRoot: (cwd) => {\n const folder = host.workspace.resolveFolder(cwd)\n return host.workspace.resolveFolder(findGitRoot(folder) ?? folder)\n },\n })\n // A project extension loads once its project is trusted; a user one is enabled now.\n if (project || !allowlist('enabledExtensions', result.name, true))\n reloadExtensions()\n changed('extensions')\n return result\n }),\n\n }\n}\n\n/** For `ipc.hello`: installs are offered when the server allows them. */\nexport function remoteInstallsAllowed(options: RemoteInstallsOptions | undefined): boolean {\n return options?.allowed() === true\n}\n","/**\n * Who or what a text block of a user turn comes from, when it is not the\n * session's own user typing in a window. Dependency-free, like\n * `thinking-levels.ts`, so any surface can read and check it.\n */\n\n/** Where a text block came from: the {@link SessionContentBlock} text member's `origin`. Absent: the session's own user. */\nexport interface TextOrigin {\n /** 'user': the session's user, through another surface; 'signal': someone else (a channel participant); 'event': something that happened (orchestration, a webhook). */\n kind: 'user' | 'signal' | 'event'\n /** Where it came from: 'slack', 'github', 'orchestration'… */\n source: string\n /** Who, when known: a provider id and a display name. */\n sender?: { id: string, name?: string }\n /** The client's id for this message (see clientMessageId), so a client can find it in the transcript after a restart. */\n messageId?: string\n}\n\n/** Longest string a {@link TextOrigin} field may hold. */\nconst MAX_FIELD_CHARS = 1024\n\nconst TEXT_ORIGIN_KINDS: readonly string[] = ['user', 'signal', 'event'] satisfies readonly TextOrigin['kind'][]\n\nfunction isField(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0 && value.length <= MAX_FIELD_CHARS\n}\n\n/**\n * Type guard for a {@link TextOrigin} read off the wire: a known `kind`, a\n * non-empty `source`, and well-formed optional fields, each string at most\n * 1024 characters.\n *\n * @param value - Any value, usually a peer's request param.\n */\nexport function isTextOrigin(value: unknown): value is TextOrigin {\n if (!value || typeof value !== 'object')\n return false\n const { kind, source, sender, messageId } = value as Record<string, unknown>\n if (typeof kind !== 'string' || !TEXT_ORIGIN_KINDS.includes(kind) || !isField(source))\n return false\n if (messageId !== undefined && !isField(messageId))\n return false\n if (sender === undefined)\n return true\n if (!sender || typeof sender !== 'object')\n return false\n const { id, name } = sender as Record<string, unknown>\n return isField(id) && (name === undefined || isField(name))\n}\n","/**\n * Idempotent sends: the optional `requestId` of `chat.send`,\n * `chat.pushQueued` and `queue.add`.\n *\n * A client that lost a send's reply retries with the same `requestId`. Per\n * session, the first send with an id runs; a later one with the same id and\n * the same content gets the first one's result without running again, and\n * one with other content is refused. The claim and the result live in the\n * session store (`claimSendRequest`), so this holds across a host restart.\n *\n * - A duplicate of a send still running in this process waits for it and\n * gets its result (or its error).\n * - A send that failed drops its claim: nothing ran, so the retry runs.\n * - A claim with no result and no send running here (still running in another\n * process, or its process died before it settled) answers\n * {@link SendRequestPendingError}: the prompt may have been accepted, so it\n * is not submitted again.\n * - If dropping a failed send's claim fails too, this process remembers it, so\n * a retry here still runs.\n * - A store without `claimSendRequest` deduplicates in this process only.\n */\nimport type { SessionStore } from '../../session'\nimport type { SendRequestClaim } from '../../session/send-requests'\nimport type { JsonValue } from '../../types'\nimport { createHash } from 'node:crypto'\nimport { createSendRequestBook } from '../../session/send-requests'\nimport { InvalidParamsError } from './handlers/params'\n\n/** Longest `requestId` accepted (a UUID is 36 characters). */\nconst MAX_REQUEST_ID_LENGTH = 128\n\n/** Params that never change what a send submits: left out of its fingerprint. */\nconst NOT_CONTENT = new Set(['sessionId', 'requestId', 'keepDraft', 'wake'])\n\n/** A retried `requestId` whose first send was accepted but has not settled (still running elsewhere, or its host stopped first). */\nexport class SendRequestPendingError extends Error {\n constructor(requestId: string) {\n super(`Send request \"${requestId}\" was already accepted; its outcome is unknown (it may still be running in another host process, or its host stopped before it settled), so it was not submitted again.`)\n this.name = 'SendRequestPendingError'\n }\n}\n\nexport interface SendDedup {\n /** Run `call` for the send `params` of `method`, or answer the first outcome of its `requestId`. Without one, just runs `call`. */\n run: <T>(method: string, params: { sessionId: string, requestId?: unknown }, call: () => Promise<T>) => Promise<T>\n /** The content hash a send's `requestId` is bound to. */\n fingerprint: (method: string, params: object) => string\n}\n\nexport function createSendDedup({ store }: { store: SessionStore }): SendDedup {\n const local = createSendRequestBook()\n const claim = async (sessionId: string, requestId: string, fp: string): Promise<SendRequestClaim> =>\n store.claimSendRequest ? store.claimSendRequest(sessionId, requestId, fp) : local.claim(sessionId, requestId, fp)\n const settle = async (sessionId: string, requestId: string, result: JsonValue | null): Promise<void> => {\n if (store.settleSendRequest)\n await store.settleSendRequest(sessionId, requestId, result)\n else\n local.settle(sessionId, requestId, result)\n }\n /** Sends running here, by `sessionId \\0 requestId`: a duplicate waits for the first. */\n const running = new Map<string, { fingerprint: string, outcome: Promise<unknown> }>()\n /** Failed sends whose claim could not be dropped from the store, by key: a retry here runs anyway. */\n const failedHere = new Set<string>()\n\n const fingerprint = (method: string, params: object): string => {\n const content = Object.fromEntries(Object.entries(params).filter(([key]) => !NOT_CONTENT.has(key)))\n return createHash('sha256').update(stableJson({ method, ...content })).digest('hex')\n }\n\n const refuse = (requestId: string): never => {\n throw new InvalidParamsError(`requestId \"${requestId}\" was already used for a different send in this session; use a new requestId for new content.`)\n }\n\n return {\n fingerprint,\n async run<T>(method: string, params: { sessionId: string, requestId?: unknown }, call: () => Promise<T>): Promise<T> {\n const { sessionId, requestId } = params\n if (requestId === undefined)\n return call()\n if (typeof requestId !== 'string' || requestId.length === 0 || requestId.length > MAX_REQUEST_ID_LENGTH)\n throw new InvalidParamsError(`requestId must be a non-empty string of at most ${MAX_REQUEST_ID_LENGTH} characters.`)\n const fp = fingerprint(method, params)\n const key = `${sessionId}\\0${requestId}`\n\n const live = running.get(key)\n if (live) {\n if (live.fingerprint !== fp)\n refuse(requestId)\n return live.outcome as Promise<T>\n }\n\n // Registered before the first await, so a concurrent duplicate waits\n // here instead of racing the store claim.\n const outcome = (async () => {\n const claimed = await claim(sessionId, requestId, fp)\n if (!claimed.claimed) {\n if (claimed.record.fingerprint !== fp)\n refuse(requestId)\n if (claimed.record.result !== undefined)\n return claimed.record.result as T\n if (!failedHere.has(key))\n throw new SendRequestPendingError(requestId)\n }\n failedHere.delete(key)\n let result: T\n try {\n result = await call()\n }\n catch (err) {\n // Nothing ran: drop the claim so a retry runs. Retried once; if it still fails, a retry here re-runs anyway.\n const dropped = await settle(sessionId, requestId, null).then(() => true, () => false)\n || await settle(sessionId, requestId, null).then(() => true, () => false)\n if (!dropped)\n failedHere.add(key)\n throw err\n }\n // The send ran: a store failure here must not turn it into an error the client would retry.\n await settle(sessionId, requestId, result as JsonValue).catch(() => undefined)\n return result\n })()\n running.set(key, { fingerprint: fp, outcome })\n try {\n return await outcome\n }\n finally {\n running.delete(key)\n }\n },\n }\n}\n\nconst dedupByStore = new WeakMap<SessionStore, SendDedup>()\n\n/** The one dedup of `store`: every send method of a host shares it (and its in-process waits). */\nexport function sendDedupFor(store: SessionStore): SendDedup {\n let dedup = dedupByStore.get(store)\n if (!dedup) {\n dedup = createSendDedup({ store })\n dedupByStore.set(store, dedup)\n }\n return dedup\n}\n\n/** `dedup.run`, or just `call` without a dedup. */\nexport async function deduped<T>(dedup: SendDedup | undefined, method: string, params: { sessionId: string, requestId?: unknown }, call: () => Promise<T>): Promise<T> {\n return dedup ? dedup.run(method, params, call) : call()\n}\n\n/** JSON with object keys sorted, so a fingerprint does not depend on key order. */\nfunction stableJson(value: unknown): string {\n return JSON.stringify(value, (_key, v: unknown) => {\n if (!v || typeof v !== 'object' || Array.isArray(v))\n return v\n return Object.fromEntries(Object.entries(v).sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0)))\n })\n}\n","/** Runs: send, interrupt, steer, follow-up, running work, and slash-command discovery. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { QueuedPromptFields } from '../../../chat/host/signals'\nimport type { TextOrigin } from '../../../text-origin'\nimport type { SendOptions } from '../../protocol'\nimport type { HostPeer } from '../peers'\nimport type { SendDedup } from '../send-requests'\nimport type { Handlers } from './types'\nimport { isTextOrigin } from '../../../text-origin'\nimport { deduped } from '../send-requests'\nimport { InvalidParamsError } from './params'\n\ntype ChatMethod\n = | 'chat.send' | 'chat.interrupt' | 'chat.steer' | 'chat.followUp' | 'chat.pushQueued'\n | 'chat.isRunning' | 'chat.rebuildAgent' | 'chat.listWork' | 'chat.cancelWork'\n | 'commands.list' | 'commands.completeArgs'\n\nexport function createChatHandlers({ host, clearDraft, dedup }: {\n host: ChatHost\n clearDraft: (sessionId: string, origin: HostPeer | null) => void\n /** Answers a retried `requestId` with its first outcome (`../send-requests`). Absent: `requestId` is ignored. */\n dedup?: SendDedup\n}): Handlers<ChatMethod> {\n return {\n 'chat.send': async (p, peer) => {\n // `wake` is host-internal: a wire peer must not run a session with\n // the `user-prompt` broadcast suppressed (params are unchecked JSON\n // — the Omit<> in the method type is not a runtime guarantee).\n const { wake: _stripped, keepDraft, requestId: _id, origin: _origin, literal: _literal, clientMessageId: _clientMessageId, ...params } = p as SendOptions & { requestId?: string }\n const result = await deduped(dedup, 'chat.send', p, () => host.sendPrompt({ ...params, ...promptFields(p) }))\n // A composer submit consumed the shared draft — clear it everywhere\n // else (the sender's input is already empty; excluding it means a user\n // already typing their NEXT message is never clobbered). A prompt sent\n // from elsewhere (Continue, Retry, the palette) did not.\n if (!keepDraft)\n clearDraft(p.sessionId, peer)\n return result\n },\n 'chat.interrupt': p => host.interrupt(p.sessionId),\n 'chat.steer': p => host.steer(p.sessionId, p.message, clientMessageId(p.clientMessageId)),\n 'chat.followUp': p => host.followUp(p.sessionId, p.message, clientMessageId(p.clientMessageId)),\n 'chat.pushQueued': async (p, peer) => {\n const result = await deduped(dedup, 'chat.pushQueued', p, () => host.pushQueued(p.sessionId, p.message, p.activatedSkills, promptFields(p)))\n if (!p.keepDraft)\n clearDraft(p.sessionId, peer)\n return result\n },\n 'chat.isRunning': p => host.isSessionRunning(p.sessionId),\n 'chat.rebuildAgent': p => host.disposeAgentForRebuild(p.sessionId),\n 'chat.listWork': p => host.listRunningWork(p.sessionId, p.children === true ? { children: true } : undefined),\n 'chat.cancelWork': p => host.cancelRunningWork(p.sessionId, p.id, p.reason),\n\n 'commands.list': p => host.listCommands(p.cwd, typeof p.kind === 'string' ? p.kind : undefined),\n 'commands.completeArgs': p => host.completeCommandArgs(p.cwd, p.name, p.argsPrefix, typeof p.kind === 'string' ? p.kind : undefined),\n }\n}\n\n/** A peer's `origin` / `literal` / `clientMessageId` params, checked (params are unchecked JSON): a malformed origin or id is refused. */\nexport function promptFields(p: { origin?: unknown, literal?: unknown, clientMessageId?: unknown }): QueuedPromptFields {\n if (p.origin !== undefined && !isTextOrigin(p.origin))\n throw new InvalidParamsError('origin: must be { kind: \\'user\\' | \\'signal\\' | \\'event\\', source, sender?: { id, name? }, messageId? } with non-empty strings of at most 1024 characters.')\n const id = clientMessageId(p.clientMessageId)\n return {\n ...(p.origin !== undefined ? { origin: knownOriginFields(p.origin) } : {}),\n ...(p.literal === true ? { literal: true } : {}),\n ...(id !== undefined ? { clientMessageId: id } : {}),\n }\n}\n\n/** A checked origin with only its known fields: it is stored with the turn, so a peer's extra keys are not. */\nfunction knownOriginFields({ kind, source, sender, messageId }: TextOrigin): TextOrigin {\n return {\n kind,\n source,\n ...(sender ? { sender: { id: sender.id, ...(sender.name !== undefined ? { name: sender.name } : {}) } } : {}),\n ...(messageId !== undefined ? { messageId } : {}),\n }\n}\n\n/** A peer's `clientMessageId`, checked: absent, or a non-empty string of at most 256 characters. */\nfunction clientMessageId(value: unknown): string | undefined {\n if (value === undefined)\n return undefined\n if (typeof value !== 'string' || value.length === 0 || value.length > 256)\n throw new InvalidParamsError('clientMessageId: must be a non-empty string of at most 256 characters.')\n return value\n}\n","/**\n * What a host keeps for its clients' apps in its `state.json`, so a web app\n * finds it again in any browser: the picks remembered across apps\n * (`prefs.*`: effort and options per model, the next chat's model chain)\n * and the sidebar's view (`sidebar.*`: each space's filters, checked by the\n * client when read, and the space on show).\n */\nimport type { HostComposerPrefs } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { Handlers } from './types'\nimport { isThinkingLevel } from '../../../types'\nimport { InvalidParamsError } from './params'\n\ntype ClientStateMethod = 'prefs.get' | 'prefs.set' | 'sidebar.getViews' | 'sidebar.setView' | 'sidebar.getSpace' | 'sidebar.setSpace'\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n/** Each pref's shape: `state.json` is read by every app on the host, a client's junk must not reach it. */\nconst PREF_CHECKS: { [K in keyof Required<HostComposerPrefs>]: (value: unknown) => boolean } = {\n lastEffortByModel: v => isRecord(v) && Object.values(v).every(isThinkingLevel),\n lastModelOptionsByModel: v => isRecord(v) && Object.values(v).every(options => isRecord(options) && Object.values(options).every(on => typeof on === 'boolean')),\n lastModelChain: v => Array.isArray(v) && v.every(entry => isRecord(entry) && typeof entry.provider === 'string' && typeof entry.model === 'string' && (entry.account === undefined || typeof entry.account === 'string')),\n}\nconst PREF_KEYS = Object.keys(PREF_CHECKS) as (keyof HostComposerPrefs)[]\n\n/** Space ids are short slugs (`default`, `space-1`). */\nconst MAX_SPACE_ID = 200\n/** A view is five short fields. */\nconst MAX_VIEW_JSON = 4096\n/** Spaces with a saved view; a client can't grow `state.json` without bound. */\nconst MAX_VIEWS = 100\n\nfunction spaceIdOf(value: unknown): string {\n if (typeof value !== 'string' || value.length === 0 || value.length > MAX_SPACE_ID)\n throw new InvalidParamsError(`spaceId must be a non-empty string of at most ${MAX_SPACE_ID} characters.`)\n return value\n}\n\nexport function createClientStateHandlers({ env }: { env: Pick<DaemonEnvironment, 'config'> }): Handlers<ClientStateMethod> {\n const { stateStore } = env.config\n return {\n 'prefs.get': () => {\n const state = stateStore.load()\n const prefs: HostComposerPrefs = Object.fromEntries(PREF_KEYS.flatMap(key => (state[key] === undefined ? [] : [[key, state[key]]])))\n return Object.keys(prefs).length > 0 ? prefs : null\n },\n 'prefs.set': (p) => {\n const patch: unknown = p.patch\n if (!isRecord(patch))\n throw new InvalidParamsError('patch must be an object.')\n const bad = PREF_KEYS.find(key => key in patch && !PREF_CHECKS[key](patch[key]))\n if (bad)\n throw new InvalidParamsError(`patch.${bad} has the wrong shape.`)\n stateStore.save({ ...stateStore.load(), ...Object.fromEntries(PREF_KEYS.flatMap(key => (key in patch ? [[key, patch[key]]] : []))) })\n },\n 'sidebar.getViews': () => stateStore.load().sidebarViews ?? {},\n 'sidebar.setView': (p) => {\n const spaceId = spaceIdOf(p.spaceId)\n if (!isRecord(p.view))\n throw new InvalidParamsError('view must be an object.')\n if (JSON.stringify(p.view).length > MAX_VIEW_JSON)\n throw new InvalidParamsError(`view must be at most ${MAX_VIEW_JSON} characters of JSON.`)\n const state = stateStore.load()\n const views = state.sidebarViews ?? {}\n if (!(spaceId in views) && Object.keys(views).length >= MAX_VIEWS)\n throw new Error(`This host keeps the views of ${MAX_VIEWS} spaces at most.`)\n stateStore.save({ ...state, sidebarViews: { ...views, [spaceId]: p.view } })\n },\n 'sidebar.getSpace': () => stateStore.load().sidebarSpaceId ?? null,\n 'sidebar.setSpace': (p) => {\n const sidebarSpaceId = spaceIdOf(p.spaceId)\n stateStore.save({ ...stateStore.load(), sidebarSpaceId })\n },\n }\n}\n","/** What a session's model sees: context breakdown and segments, the session's system prompt override, and its prompt cache. */\nimport type { CacheImpactChange, ChatHost } from '../../../chat/host/engine'\nimport type { ThinkingLevel } from '../../../types'\nimport type { Handlers } from './types'\nimport { THINKING_LEVELS } from '../../../types'\nimport { InvalidParamsError, nonNegativeInt, optionalString } from './params'\n\nexport function createContextHandlers({ host }: { host: ChatHost }): Handlers<'sessions.contextBreakdown' | 'sessions.contextSegments' | 'sessions.createSystemOverride' | 'sessions.systemMd' | 'sessions.cacheImpact' | 'sessions.cacheReport'> {\n return {\n 'sessions.systemMd': p => host.sessionSystemMd(p.sessionId),\n 'sessions.contextSegments': p => host.getContextSegments(p.sessionId),\n 'sessions.createSystemOverride': p => host.createSystemOverride(p.sessionId),\n 'sessions.contextBreakdown': p => host.getContextBreakdown(p.sessionId),\n 'sessions.cacheImpact': p => host.cacheImpact(p.sessionId, cacheImpactChange(p.change)),\n 'sessions.cacheReport': p => host.cacheReport(p.sessionId, nonNegativeInt(p.limit, 'limit')),\n }\n}\n\nfunction cacheImpactChange(value: unknown): CacheImpactChange {\n if (typeof value !== 'object' || value === null || Array.isArray(value))\n throw new InvalidParamsError('change must be an object.')\n const raw = value as Record<string, unknown>\n const change: CacheImpactChange = {}\n const modelId = optionalString(raw.modelId, 'change.modelId')\n const providerKey = optionalString(raw.providerKey, 'change.providerKey')\n const agentId = optionalString(raw.agentId, 'change.agentId')\n const effort = optionalString(raw.effort, 'change.effort')\n if (effort !== undefined && !(THINKING_LEVELS as readonly string[]).includes(effort))\n throw new InvalidParamsError('change.effort must be a thinking level.')\n if (modelId !== undefined)\n change.modelId = modelId\n if (providerKey !== undefined)\n change.providerKey = providerKey\n if (agentId !== undefined)\n change.agentId = agentId\n if (effort !== undefined)\n change.effort = effort as ThinkingLevel\n return change\n}\n","/** The daemon process itself: identity, the processes it started for its own work and for each session, and shutdown. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HelloResult } from '../../protocol'\nimport type { Handlers } from './types'\nimport { listOwnedProcesses } from '../../../contexts/owned-processes'\nimport { listSessionProcesses } from '../../../contexts/session-processes'\nimport { IPC_PROTOCOL_VERSION } from '../../protocol'\n\nexport function createDaemonHandlers({ host, appVersion, startedAt, lifecycle, identity }: {\n host: ChatHost\n appVersion: string\n startedAt: number\n lifecycle: { shutdown: () => void, retireWhenIdle: () => void, isRetiring?: () => boolean }\n /** The host identity fields `ipc.hello` reports. */\n identity: Pick<HelloResult, 'hostId' | 'hostKind' | 'hostName'>\n}): Handlers<'daemon.info' | 'daemon.ownedProcesses' | 'daemon.sessionProcesses' | 'daemon.shutdown'> {\n return {\n 'daemon.info': (): HelloResult => ({\n protocolVersion: IPC_PROTOCOL_VERSION,\n appVersion,\n pid: process.pid,\n startedAt,\n ...identity,\n activeWork: host.hasActiveRuns(),\n // Live, unlike the hello: a daemon starts retiring after windows attached (a newer install landed).\n ...(lifecycle.isRetiring?.() ? { retiring: true } : {}),\n }),\n 'daemon.ownedProcesses': () => listOwnedProcesses(),\n 'daemon.sessionProcesses': () => listSessionProcesses(),\n 'daemon.shutdown': async (p) => {\n // Version-skew retirement never aborts live work: exit once idle.\n if (p?.whenIdle === true && host.hasActiveWork()) {\n lifecycle.retireWhenIdle()\n return { deferred: true }\n }\n // Reply first (return), then drain on the next tick.\n setImmediate(lifecycle.shutdown)\n },\n }\n}\n","/**\n * Shared per-session composer state: prompt drafts, draft attachments, and\n * transcript-search state, synced across windows. Ephemeral by design —\n * in-memory only, cleared when any window submits, gone on daemon restart.\n */\nimport type { HostSignal, PromptAttachment } from '../../protocol'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\n\ninterface DraftEntry { text?: string, shell?: boolean, attachments?: PromptAttachment[], search?: { active: boolean, query: string } }\n\n/**\n * Bound a peer-supplied attachment list: shape-guarded entries only,\n * 24 MiB of base64 per list. Shared by `queue.add` and\n * `drafts.setAttachments`.\n */\nexport function boundAttachments(list: unknown[]): PromptAttachment[] {\n let budget = 24 * 1024 * 1024\n const out: PromptAttachment[] = []\n for (const entry of list) {\n const a = entry as Partial<PromptAttachment>\n if (typeof a?.mediaType !== 'string' || typeof a?.data !== 'string')\n continue\n budget -= a.data.length\n if (budget < 0)\n break\n // Names render in every window's UI — cap them so a hostile peer\n // can't pin megabytes of \"name\" per attachment.\n out.push({ mediaType: a.mediaType, data: a.data, ...(typeof a.name === 'string' ? { name: a.name.slice(0, 256) } : {}) })\n }\n return out\n}\n\nexport function createDraftHandlers({ broadcastExcept }: {\n broadcastExcept: (origin: HostPeer | null, signal: HostSignal) => void\n}): {\n methods: Handlers<'drafts.get' | 'drafts.set' | 'drafts.setAttachments' | 'search.set'>\n /** Consume the draft after a submit — every window except the sender clears. */\n clearDraft: (sessionId: string, origin: HostPeer | null) => void\n /** The session was deleted: drop its draft silently. */\n forget: (sessionId: string) => void\n} {\n /**\n * Shared per-session prompt drafts. Ephemeral by design — in-memory\n * only, cleared when any window submits, gone on daemon restart.\n */\n const drafts = new Map<string, DraftEntry>()\n\n /** Total base64 bytes currently pinned by ALL draft attachments. */\n function draftAttachmentBytes(): number {\n let total = 0\n for (const entry of drafts.values()) {\n for (const attachment of entry.attachments ?? [])\n total += attachment.data.length\n }\n return total\n }\n\n function clearDraft(sessionId: string, origin: HostPeer | null): void {\n const entry = drafts.get(sessionId)\n if (!entry)\n return\n drafts.delete(sessionId)\n if (entry.text)\n broadcastExcept(origin, { kind: 'draft:changed', sessionId, text: '' })\n if (entry.attachments?.length)\n broadcastExcept(origin, { kind: 'draft:attachments', sessionId, attachments: [] })\n }\n\n /** Drop empty draft entries so the map only holds live composing state. */\n function compactDraft(sessionId: string, entry: DraftEntry): void {\n if (!entry.text && !entry.shell && !entry.attachments?.length && !entry.search?.active)\n drafts.delete(sessionId)\n else\n drafts.set(sessionId, entry)\n }\n\n const methods: Handlers<'drafts.get' | 'drafts.set' | 'drafts.setAttachments' | 'search.set'> = {\n 'drafts.get': (p) => {\n const entry = drafts.get(p.sessionId)\n return {\n text: entry?.text ?? '',\n ...(entry?.shell ? { shell: true } : {}),\n ...(entry?.attachments?.length ? { attachments: entry.attachments } : {}),\n ...(entry?.search?.active ? { search: entry.search } : {}),\n }\n },\n 'drafts.set': (p, peer) => {\n // Bound the ephemeral draft store: a buggy/looping client must not\n // grow daemon memory without limit (drafts only evict on submit or\n // session delete). 64 KiB is far above any real prompt.\n const text = typeof p.text === 'string' ? p.text.slice(0, 64 * 1024) : ''\n // When the cap actually truncated, INCLUDE the origin in the fan-out\n // so its local buffer converges to the stored truth — otherwise the\n // origin silently diverges from what every other window (and a\n // remote submit) sees.\n const truncated = typeof p.text === 'string' && p.text.length > text.length\n // Also bound the KEY count: drafts only evict on submit / session\n // delete, so a client writing under many bogus session ids could\n // otherwise grow the map unbounded. 256 concurrent drafts is far\n // beyond any real multi-window session set.\n if (!drafts.has(p.sessionId) && drafts.size >= 256)\n return\n const entry = drafts.get(p.sessionId) ?? {}\n entry.text = text.length > 0 ? text : undefined\n // Shell mode rides out of band — never sniffed from the text.\n entry.shell = p.shell === true ? true : undefined\n compactDraft(p.sessionId, entry)\n broadcastExcept(truncated ? null : peer, { kind: 'draft:changed', sessionId: p.sessionId, text, ...(p.shell === true ? { shell: true } : {}) })\n },\n 'search.set': (p, peer) => {\n // Shared transcript-search state — same lifecycle + caps as drafts.\n const active = p.active === true\n const query = typeof p.query === 'string' ? p.query.slice(0, 4 * 1024) : ''\n if (!drafts.has(p.sessionId) && drafts.size >= 256)\n return\n const entry = drafts.get(p.sessionId) ?? {}\n entry.search = active || query.length > 0 ? { active, query } : undefined\n compactDraft(p.sessionId, entry)\n broadcastExcept(peer, { kind: 'search:changed', sessionId: p.sessionId, active, query })\n },\n 'drafts.setAttachments': (p, peer) => {\n /*\n * Composing attachments (payloads included, so a remote window can\n * submit the shared draft attachments-and-all). Bounded three ways:\n * shape-guarded entries, 24 MiB of base64 per session, and a 96 MiB\n * GLOBAL budget across every draft — the per-session cap times the\n * 256-key cap would otherwise let a looping client pin gigabytes.\n */\n const bounded = Array.isArray(p.attachments) ? boundAttachments(p.attachments) : []\n if (!drafts.has(p.sessionId) && drafts.size >= 256)\n return\n const current = drafts.get(p.sessionId)?.attachments ?? []\n const currentBytes = current.reduce((sum, a) => sum + a.data.length, 0)\n const incomingBytes = bounded.reduce((sum, a) => sum + a.data.length, 0)\n if (draftAttachmentBytes() - currentBytes + incomingBytes > 96 * 1024 * 1024)\n return\n const entry = drafts.get(p.sessionId) ?? {}\n entry.attachments = bounded.length > 0 ? bounded : undefined\n compactDraft(p.sessionId, entry)\n broadcastExcept(peer, { kind: 'draft:attachments', sessionId: p.sessionId, attachments: bounded })\n },\n }\n\n return {\n methods,\n clearDraft,\n forget: (sessionId) => {\n drafts.delete(sessionId)\n },\n }\n}\n","/** Execution environments: the catalog, verification, settings, and a session's provisioning and actions. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostSettings } from '../../../chat/index'\nimport type { DaemonEnvironment } from '../environment'\nimport type { Handler, Handlers } from './types'\nimport { applyEnvironmentSettingsChange } from '../../../chat/environment-settings'\nimport { loadOrThrow } from './session-load'\n\ntype EnvironmentMethod\n = | 'environments.list' | 'environments.verify' | 'environments.update'\n | 'sessions.retryEnvironment' | 'sessions.moveEnvironment' | 'sessions.environmentActions' | 'sessions.runEnvironmentAction'\n\nexport function createEnvironmentHandlers({ host, env, setSettings }: {\n host: ChatHost\n env: DaemonEnvironment\n /** The `settings.set` handler, so an environment edit fans out like any settings edit. */\n setSettings: Handler<'settings.set'>\n}): Handlers<EnvironmentMethod> {\n return {\n 'sessions.retryEnvironment': async (p) => {\n await loadOrThrow(env.store, p.sessionId)\n // Provisioning can take minutes (a sandbox, a clone): respond once the\n // row shows `provisioning` (a poller must not read the old failure) and\n // let `prepare` run in the background, announced as `sessions:changed`.\n await host.retryEnvironment(p.sessionId, { background: true })\n },\n 'sessions.moveEnvironment': async (p) => {\n await loadOrThrow(env.store, p.sessionId)\n return host.moveSessionEnvironment(p.sessionId, p.environment, typeof p.cwd === 'string' ? p.cwd : undefined, p.removeOldWorktree === true ? { removeOldWorktree: true } : undefined)\n },\n 'sessions.environmentActions': p => host.listEnvironmentActions(p.sessionId),\n 'sessions.runEnvironmentAction': p => host.runEnvironmentAction(p.sessionId, p.actionId),\n 'environments.list': p => host.listEnvironments(p.cwd ?? '', typeof p.kind === 'string' ? p.kind : undefined),\n 'environments.verify': p => host.verifyEnvironment(p.kind),\n 'environments.update': async (p, peer) => {\n const write = applyEnvironmentSettingsChange(host.environments, env.readSettings(), p)\n for (const secret of write.secrets)\n host.environmentSecrets.set(p.kind, secret.key, secret.value)\n // Through `settings.set` so the change fans out (and tears down what a\n // bound key like `sandbox` requires) exactly like any settings edit.\n await setSettings({ patch: write.settingsPatch as Partial<HostSettings> }, peer)\n },\n }\n}\n","/**\n * What an extension adds to a client's app, run here and answered as data:\n * composer completions (`completions.*`: the providers, a provider's items,\n * the submit hooks), text references in prose (`references.*`: the\n * providers' patterns, then the views of the keys a client found), badge\n * menu items (`badges.*`), and Settings › Extensions (`extensions.*`: the\n * options a folder's extensions declare, their action rows, the actions'\n * status probes, a run). A badge item runs outside any session's scope: its\n * `ctx.artifacts` reads nothing.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { CompletionRunner, ExtensionRegistry, ReferenceResolver } from '../../../extensions/index'\nimport type { DaemonEnvironment } from '../environment'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport {\n completionProviderSummaries,\n createCompletionRunner,\n createReferenceResolver,\n extensionBadgeActions,\n listActionSummaries,\n normalizeBadgeTarget,\n probeActionStatuses,\n referenceProviderWires,\n runBadgeAction,\n runExtensionAction,\n toWireConfigSchema,\n} from '../../../extensions/index'\nimport { catalogFolder } from './catalogs'\nimport { InvalidParamsError } from './params'\n\ntype ExtensionUiMethod\n = | 'completions.providers' | 'completions.suggest' | 'completions.submit'\n | 'references.providers' | 'references.resolve' | 'badges.actions' | 'badges.run'\n | 'extensions.configSchema' | 'extensions.actions' | 'extensions.actionStatuses' | 'extensions.runAction'\n\n/** Keys per `references.resolve` call. */\nconst RESOLVE_MAX = 50\n/** Longest reference key resolved. */\nconst MAX_KEY_LENGTH = 512\n\n/** The text and cursor of a completion call. */\nfunction composerText(p: { text?: unknown, cursor?: unknown }): { text: string, cursor: number } {\n if (typeof p.text !== 'string' || typeof p.cursor !== 'number' || !Number.isSafeInteger(p.cursor) || p.cursor < 0 || p.cursor > p.text.length)\n throw new InvalidParamsError('text must be a string and cursor a position in it.')\n return { text: p.text, cursor: p.cursor }\n}\n\n/** One value per owner (a connection, a registry), dropped with it. */\nfunction weakMemo<K extends object, V>(make: (owner: K) => V): (owner: K) => V {\n const memo = new WeakMap<K, V>()\n return (owner) => {\n let value = memo.get(owner)\n if (value === undefined) {\n value = make(owner)\n memo.set(owner, value)\n }\n return value\n }\n}\n\nexport function createExtensionUiHandlers({ host, env }: {\n host: Pick<ChatHost, 'resolveFolder'>\n env: DaemonEnvironment\n}): Handlers<ExtensionUiMethod> {\n const folderOf = (cwd: unknown): string => catalogFolder({ env, host }, cwd)\n const configOf = (cwd: unknown) => env.runtimeConfig(folderOf(cwd))\n const registryOf = async (cwd: unknown): Promise<ExtensionRegistry> => (await configOf(cwd)).extensions\n /** One completion runner per connection: a newer suggest aborts only that window's older one. */\n const runnerOf = weakMemo<HostPeer, CompletionRunner>(() => createCompletionRunner())\n /** One reference resolver (and so one view cache) per registry: a rebuilt registry starts fresh. */\n const resolverOf = weakMemo<ExtensionRegistry, ReferenceResolver>(registry => createReferenceResolver(registry))\n /** Actions running now, by folder, extension and key: a second click waits for the first. */\n const running = new Set<string>()\n\n return {\n 'completions.providers': async p => completionProviderSummaries((await registryOf(p.cwd)).completionProviders),\n 'completions.suggest': async (p, peer) => {\n const context = composerText(p)\n if (typeof p.providerId !== 'string' || typeof p.query !== 'string')\n throw new InvalidParamsError('providerId and query must be strings.')\n const cwd = folderOf(p.cwd)\n const provider = (await env.runtimeConfig(cwd)).extensions.completionProviders.find(c => c.id === p.providerId)\n if (!provider || typeof provider.suggest !== 'function')\n return []\n return runnerOf(peer).suggest(`${cwd}\\u001E${provider.id}`, provider, p.query, context)\n },\n 'completions.submit': async (p, peer) => {\n const { text, cursor } = composerText(p)\n await runnerOf(peer).submit((await registryOf(p.cwd)).completionProviders, text, cursor)\n },\n\n 'references.providers': async (p) => {\n if (p.peek !== true)\n return referenceProviderWires(await registryOf(p.cwd))\n const cached = env.peekRuntimeConfig?.(folderOf(p.cwd))\n return cached ? referenceProviderWires((await cached).extensions) : null\n },\n 'references.resolve': async (p) => {\n const asked = Array.isArray(p.items) ? p.items.slice(0, RESOLVE_MAX) : []\n const resolver = resolverOf(await registryOf(p.cwd))\n return Promise.all(asked.map((item) => {\n const { providerId, key } = (item ?? {}) as { providerId?: unknown, key?: unknown }\n if (typeof providerId !== 'string' || typeof key !== 'string' || key.length > MAX_KEY_LENGTH)\n return null\n return resolver.resolve(providerId, key)\n }))\n },\n 'badges.actions': async (p) => {\n const target = normalizeBadgeTarget(p.target)\n return target ? extensionBadgeActions(target, await registryOf(p.cwd)) : []\n },\n 'badges.run': async (p) => {\n const target = normalizeBadgeTarget(p.target)\n if (!target || typeof p.source !== 'string' || typeof p.id !== 'string')\n return { notice: 'Unknown badge.' }\n const ctx = {\n ...(target.sessionId ? { sessionId: target.sessionId } : {}),\n ...(typeof p.cwd === 'string' && p.cwd ? { cwd: p.cwd } : {}),\n }\n return runBadgeAction(p.source, p.id, target, await registryOf(p.cwd), ctx)\n },\n\n 'extensions.configSchema': async (p) => {\n const config = await configOf(p.cwd)\n return toWireConfigSchema({ configCategories: config.extensionConfigCategories, configItems: config.extensionConfigItems })\n },\n 'extensions.actions': async (p) => {\n const config = await configOf(p.cwd)\n return listActionSummaries(config.extensionConfigCategories, config.extensionConfigItems)\n },\n 'extensions.actionStatuses': async p => probeActionStatuses((await configOf(p.cwd)).extensionConfigItems),\n 'extensions.runAction': async (p) => {\n if (typeof p.extension !== 'string' || typeof p.key !== 'string')\n throw new InvalidParamsError('extension and key must be strings.')\n const cwd = folderOf(p.cwd)\n const guard = `${cwd}\\u001E${p.extension}\\u001E${p.key}`\n if (running.has(guard))\n throw new Error('action is already running.')\n running.add(guard)\n try {\n return await runExtensionAction((await env.runtimeConfig(cwd)).extensionConfigItems, p.extension, p.key)\n }\n finally {\n running.delete(guard)\n }\n },\n }\n}\n","/** Extension bus emits from clients whose extensions run client-side, and the extensions' HUD the host holds. */\nimport type { HostSignal } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { EXTENSION_BUS_MAX_PAYLOAD_BYTES, serializedPayloadBytes } from '../../../extensions/index'\nimport { loadOrThrow } from './session-load'\n\nexport function createExtensionHandlers({ env, broadcastExcept }: {\n env: DaemonEnvironment\n broadcastExcept: (origin: HostPeer | null, signal: HostSignal) => void\n}): Handlers<'extension.emit' | 'hud.get'> {\n return {\n 'hud.get': () => env.hudState?.() ?? { statuses: {}, banners: {}, sessions: {}, badges: {} },\n 'extension.emit': async (p, peer) => {\n /*\n * Extension bus emit from a client whose extensions run client-side\n * (TUI daemon mode). Trust boundary: params are unchecked JSON —\n * same cheap shape guards as `drafts.set`, the payload cap\n * re-enforced daemon-side, and the extension id validated against\n * the session cwd's registry (spoof-resistance: a hand-rolled peer\n * can't ride an id that isn't a loaded, `'ipc'`-permitted extension).\n */\n const extensionId = typeof p.extensionId === 'string' ? p.extensionId : ''\n if (extensionId.length === 0 || extensionId.length > 256)\n return\n if (typeof p.seq !== 'number' || !Number.isFinite(p.seq))\n return\n const sessionId = typeof p.sessionId === 'string' ? p.sessionId : undefined\n const bytes = serializedPayloadBytes(p.payload)\n if (bytes === null || bytes > EXTENSION_BUS_MAX_PAYLOAD_BYTES)\n return\n // Registry for the session's cwd (same derivation as `suggest.resolve`);\n // sessionless emits validate against the boot-config registry.\n let registry = env.config.extensions\n if (sessionId !== undefined) {\n try {\n const data = await loadOrThrow(env.store, sessionId)\n const meta = data.metadata ?? {}\n const cwd = typeof meta.cwd === 'string' ? meta.cwd : (data.projectRoot ?? '')\n registry = (await env.runtimeConfig(cwd)).extensions\n }\n catch {\n return // Unknown session — nothing to validate against, drop.\n }\n }\n const known = registry.loaded.some(ext =>\n !ext.error && ext.name === extensionId && ext.definition?.permissions?.includes('ipc') === true)\n if (!known)\n return\n const nonce = typeof p.nonce === 'string' ? p.nonce : undefined\n const envelope = { extensionId, ...(sessionId !== undefined ? { sessionId } : {}), payload: p.payload, seq: p.seq, ...(nonce !== undefined ? { nonce } : {}) }\n // Daemon-side subscribers first (loopback for extensions living in\n // per-cwd daemon registries), then every OTHER window — the origin\n // already delivered to its local subscribers at emit.\n env.extensionBus?.deliver(envelope)\n broadcastExcept(peer, { kind: 'extension:signal', ...envelope })\n },\n }\n}\n","/**\n * A folder's files beyond a session's workspace (`files.*`): the files `@`\n * completes and where the folder sits, search in files, what prose names on disk, the project's own diagnostics, and the ticket a\n * connection's media play under (a zidane-server serves them over HTTP,\n * `src/server/media.ts`). The work is the desktop app's own\n * (`src/chat/workspace`); this slice confines every folder to the host's\n * workspace roots.\n */\nimport type { HostPeer } from '../peers'\nimport type { WorkspaceRoots } from '../workspace-roots'\nimport type { Handlers } from './types'\nimport { randomUUID } from 'node:crypto'\nimport { listProjectFiles } from '../../../chat/files-discovery'\nimport { folderLocation } from '../../../chat/project-root'\nimport { invalidateDiagnostics, listDiagnosticsTools, runDiagnostics } from '../../../chat/workspace/diagnostics/runner'\nimport { resolvePaths } from '../../../chat/workspace/path-resolve'\nimport { searchWorkspace } from '../../../chat/workspace/search'\nimport { InvalidParamsError, optionalString } from './params'\n\ntype FilesMethod = 'files.list' | 'files.location' | 'files.search' | 'files.resolvePaths' | 'files.diagnostics' | 'files.diagnosticsInvalidate' | 'files.diagnosticsTools' | 'files.mediaTicket'\n\n/** The connections' media tickets: a zidane-server's (`src/server/media.ts`). */\nexport interface MediaTicketRegistry {\n /** Lets `peer`'s media play under `ticket`, replacing its previous one. Throws when another connection holds it. */\n register: (ticket: string, peer: HostPeer) => void\n /** Drops `peer`'s ticket (its connection closed). */\n release: (peer: HostPeer) => void\n}\n\n/** A media ticket: random, URL-safe, long enough not to be guessed. */\nconst MEDIA_TICKET = /^[\\w-]{32,128}$/\n\n/** Longest query searched; the rest is cut. */\nconst MAX_QUERY_LENGTH = 500\n/** Most texts one `files.resolvePaths` resolves. */\nconst MAX_TEXTS = 500\n\nfunction stringList(value: unknown, name: string, max = Infinity): string[] {\n if (!Array.isArray(value) || value.length > max || value.some(v => typeof v !== 'string'))\n throw new InvalidParamsError(`${name} must be an array of at most ${max} strings.`)\n return value\n}\n\nexport function createFilesHandlers({ workspace, media, onClose }: {\n workspace: WorkspaceRoots\n /** Absent: this host serves no media (`files.mediaTicket` refuses). */\n media?: MediaTicketRegistry\n onClose: (release: (peer: HostPeer) => void) => void\n}): Handlers<FilesMethod> {\n if (media)\n onClose(peer => media.release(peer))\n const folder = (cwd: unknown): string => {\n if (typeof cwd !== 'string' || cwd.length === 0)\n throw new InvalidParamsError('cwd must be a non-empty string.')\n return workspace.resolveFolder(cwd)\n }\n // Search ids are per connection: one client's search never cancels another's.\n const connectionIds = new WeakMap<HostPeer, string>()\n const connectionId = (peer: HostPeer): string => {\n let id = connectionIds.get(peer)\n if (!id)\n connectionIds.set(peer, id = randomUUID())\n return id\n }\n return {\n 'files.list': p => listProjectFiles({ cwd: folder(p.cwd) }),\n 'files.location': p => folderLocation(folder(p.cwd)),\n 'files.search': (p, peer) => {\n if (typeof p.query !== 'string')\n throw new InvalidParamsError('query must be a string.')\n return searchWorkspace(folder(p.cwd), p.query.slice(0, MAX_QUERY_LENGTH), {\n caseSensitive: p.caseSensitive === true,\n searchId: `${connectionId(peer)}:${optionalString(p.searchId, 'searchId') ?? ''}`,\n })\n },\n 'files.resolvePaths': p => resolvePaths(folder(p.cwd), stringList(p.texts, 'texts', MAX_TEXTS)),\n 'files.diagnostics': p => runDiagnostics(folder(p.cwd), stringList(p.paths, 'paths'), {\n disabled: p.disabled === undefined ? [] : stringList(p.disabled, 'disabled'),\n ...(typeof p.timeoutMs === 'number' ? { timeoutMs: p.timeoutMs } : {}),\n }),\n 'files.diagnosticsInvalidate': (p) => {\n invalidateDiagnostics(folder(p.cwd))\n },\n 'files.diagnosticsTools': p => listDiagnosticsTools(folder(p.cwd)),\n 'files.mediaTicket': (p, peer) => {\n if (!media)\n throw new Error('This host serves no media (only a zidane-server does).')\n if (typeof p.ticket !== 'string' || !MEDIA_TICKET.test(p.ticket))\n throw new InvalidParamsError('ticket must be 32 to 128 URL-safe characters.')\n media.register(p.ticket, peer)\n },\n }\n}\n","/**\n * The host's machine: folders within its workspace roots (`fs.roots`,\n * `fs.listDirs`, `fs.searchDirs`, and `fs.mkdir` while `createFolders`\n * allows it) and what it can do (`host.capabilities`).\n */\nimport type { HostCapabilities } from '../../../chat/capabilities'\nimport type { EnvironmentDescriptor } from '../../../chat/environment-settings'\nimport type { WorkspaceRoots } from '../workspace-roots'\nimport type { Handlers } from './types'\nimport { createCapabilityProbe } from '../../../chat/capabilities-probe'\nimport { optionalString, requiredString } from './params'\n\n/** What `fs.mkdir` answers while a zidane-server's `allowCreateFolders` is off. */\nexport const CREATE_FOLDERS_OFF_MESSAGE = 'Creating folders is off on this server (allowCreateFolders).'\n\nexport function createFsHandlers({ workspace, environments, allows, createFolders = () => true }: {\n workspace: WorkspaceRoots\n /** The host's environment kinds (`environments.list`). */\n environments?: () => Promise<EnvironmentDescriptor[]>\n /** What it lets clients do (the hello flags). */\n allows?: () => HostCapabilities['allows']\n /** Clients may create folders (`fs.mkdir`): a zidane-server's `allowCreateFolders`. Default: yes. */\n createFolders?: () => boolean\n}): Handlers<'fs.roots' | 'fs.listDirs' | 'fs.mkdir' | 'fs.searchDirs' | 'host.capabilities'> {\n const probe = createCapabilityProbe({\n environments: async () => (await (environments?.() ?? Promise.resolve([])))\n .filter(d => d.enabled)\n .map(d => ({ kind: d.kind, label: d.label, available: d.available, ...(d.reason ? { reason: d.reason } : {}) })),\n roots: () => workspace.describe().roots,\n allows: allows ?? (() => ({ remoteInstalls: false, asMachine: false, sync: false, clone: true, createFolders: createFolders() })),\n })\n return {\n 'fs.roots': () => workspace.describe(),\n 'fs.listDirs': p => workspace.list(optionalString(p?.path, 'path')),\n 'fs.mkdir': (p) => {\n if (!createFolders())\n throw new Error(CREATE_FOLDERS_OFF_MESSAGE)\n return workspace.mkdir(requiredString(p.parent, 'parent'), requiredString(p.name, 'name'))\n },\n 'fs.searchDirs': p => workspace.search(requiredString(p.query, 'query'), optionalString(p.path, 'path')),\n 'host.capabilities': p => probe(p?.refresh === true),\n }\n}\n","/**\n * The wire checks of a session's rules (`sessions.create`'s `policy`,\n * `sessions.setPolicy`): the shape (`chat/session-policy`), and the scope\n * loosening needs. A client whose token can't approve calls may only tighten\n * the session's current rules: a looser `approvalMode` ('ask' > 'decide' > 'off'), or\n * removing or weakening a rule, lets the agent do more, so it needs a token\n * that may approve calls itself. A local connection (no grant) reaches\n * everything.\n */\nimport type { SessionPolicy } from '../../../chat/session-policy'\nimport type { ClientScope } from '../../scopes'\nimport type { HostPeer } from '../peers'\nimport { parseSessionPolicy, policyLoosening, SessionPolicyError } from '../../../chat/session-policy'\nimport { IpcErrorCode } from '../../protocol'\nimport { scopeAllows } from '../../scopes'\nimport { InvalidParamsError } from './params'\n\n/** A policy the connection's token may not set, worded like the dispatcher's scope refusal. */\nexport class PolicyScopeError extends Error {\n readonly code = IpcErrorCode.Forbidden\n readonly data: { required: ClientScope, granted: ClientScope }\n /**\n * @param method - The refused method.\n * @param what - The loosening, as {@link policyLoosening} words it.\n * @param granted - The connection's scope.\n */\n constructor(method: string, what: string, granted: ClientScope) {\n super(`\"${method}\" ${what} needs an approve token; this connection's token is ${granted}.`)\n this.name = 'PolicyScopeError'\n this.data = { required: 'approve', granted }\n }\n}\n\n/**\n * `value` as a clean policy that `peer` may set in place of `previous`.\n *\n * @param value - The `policy` param, untrusted.\n * @param peer - The calling connection (`null` for a host-internal call).\n * @param method - The method, named in the refusal.\n * @param previous - The session's current policy, read only when the token can't approve (default: none, a new session).\n * @throws {InvalidParamsError} When the policy does not validate.\n * @throws {PolicyScopeError} When it loosens `previous` and the token can't approve.\n */\nexport async function checkPolicyParam(\n value: unknown,\n peer: HostPeer | null | undefined,\n method: string,\n previous: () => SessionPolicy | Promise<SessionPolicy> = () => ({}),\n): Promise<SessionPolicy> {\n let policy: SessionPolicy\n try {\n policy = parseSessionPolicy(value, 'policy')\n }\n catch (err) {\n throw err instanceof SessionPolicyError ? new InvalidParamsError(err.message) : err\n }\n const grant = peer?.grant\n if (grant && !scopeAllows(grant, 'approve')) {\n const loosened = policyLoosening(await previous(), policy)\n if (loosened !== undefined)\n throw new PolicyScopeError(method, loosened, grant)\n }\n return policy\n}\n","/** Session rows: list, create, delete, and metadata edits (title, archive, agent, model, folder, policy). */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { SessionPolicy } from '../../../chat/session-policy'\nimport type { SessionData, SessionStore } from '../../../session/index'\nimport type { CreateSessionParams, HostSignal, IpcParams, SessionRow } from '../../protocol'\nimport type { WorkspaceRoots } from '../workspace-roots'\nimport type { Handlers } from './types'\nimport { TITLE_SOURCE_KEY } from '../../../chat/auto-title'\nimport { isStaleRunMarker } from '../../../chat/host/engine'\nimport { readSessionAccount, sessionModelFallbacks } from '../../../chat/model-chain-metadata'\nimport { isMainSession, isSideSession, sideSessionParent } from '../../../chat/orchestration'\nimport { PINNED_SKILLS_META_KEY, pinnedSkillsValue, readPinnedSkills } from '../../../chat/pinned-skills'\nimport { SESSION_POLICY_KEY, sessionPolicyOf } from '../../../chat/session-policy'\nimport { DEFAULT_SPACE_ID, readSessionSpaceId, SPACE_METADATA_KEY } from '../../../chat/spaces'\nimport { deriveSessionTitle, runInProgress, sessionEnvironmentSummary } from '../../../chat/store'\nimport { loadOrThrow } from './session-load'\nimport { checkPolicyParam } from './session-policy'\n\ntype SessionMethod\n = | 'sessions.list' | 'sessions.create' | 'sessions.delete' | 'sessions.sideSession' | 'sessions.setTitle' | 'sessions.setArchived' | 'sessions.setFavorite' | 'sessions.setSpace'\n | 'sessions.setAgentId' | 'sessions.setEffort' | 'sessions.setModel' | 'sessions.setModelOptions' | 'sessions.setFolder'\n | 'sessions.setPolicy'\n\nexport function createSessionHandlers({ host, store, broadcast, forgetSession, hostId, workspace }: {\n host: ChatHost\n store: SessionStore\n broadcast: (signal: HostSignal) => void\n /** Drop the per-session wire state other handlers keep, before the host deletes the session. */\n forgetSession: (sessionId: string) => void\n /** Stamped on every returned row (`SessionRow.hostId`). */\n hostId: string | undefined\n /** Where session folders may be (a server confines them to its workspace roots). */\n workspace?: WorkspaceRoots\n}): Handlers<SessionMethod> {\n const stamp = (row: SessionRow): SessionRow => hostId ? { ...row, hostId } : row\n /** Each session's last `sessions.setPolicy`: the next one checks against what it wrote, not against what was there before it. */\n const policyWrites = new Map<string, Promise<unknown>>()\n /**\n * Apply a metadata-only patch. Prefers the host's live-session path (safe\n * mid-run — routes through the in-memory `Session` whose turns are the\n * source of truth); only falls back to a store-level full-document\n * `save()` when the session is idle, where no run is appending turns so\n * `load → mutate → save` can't drop concurrently-persisted turns.\n *\n * `bumpUpdatedAt: false` skips the recency bump so a rename doesn't yank\n * the row to the top of recency-sorted lists (mirrors the GUI).\n */\n async function patchSessionMeta(\n sessionId: string,\n patch: Record<string, unknown>,\n opts: { bumpUpdatedAt?: boolean } = {},\n ): Promise<void> {\n /*\n * Live path: route through the in-memory `Session` so the full-document\n * save() re-persists the CURRENT turns; `bumpUpdatedAt` holds there too.\n */\n await host.patchSessionMeta(sessionId, patch, opts)\n broadcast({ kind: 'sessions:changed', op: 'update', sessionId })\n }\n\n async function patchSession(\n sessionId: string,\n mutate: (data: SessionData) => void,\n ): Promise<void> {\n const data = await loadOrThrow(store, sessionId)\n mutate(data)\n data.updatedAt = Date.now()\n await store.save(data)\n broadcast({ kind: 'sessions:changed', op: 'update', sessionId })\n }\n\n async function createSessionRow(params: CreateSessionParams, policy?: SessionPolicy): Promise<SessionRow> {\n // Creation lives in the host (shared with the embedded GUI host and\n // orchestration); this adds only the wire row + the change broadcast.\n // Forward the wire fields by name: the host factory also accepts an\n // explicit `id` and raw `metadata`, which a wire client must not set\n // (only the validated keys below).\n const metadata = policy && Object.keys(policy).length > 0 ? { ...creationMetadata(params), [SESSION_POLICY_KEY]: policy } : creationMetadata(params)\n // A machine's folder (`local@<machine>`) is not on this host: the host checks it against the machine's roots instead.\n const onMachine = params.environment?.kind ? host.environments.get(params.environment.kind)?.checkFolder !== undefined : false\n const cwd = workspace?.describe().confined && !onMachine ? workspace.sessionFolder(params.cwd ?? '') : params.cwd\n const id = await host.createSession({\n cwd,\n ...(metadata ? { metadata } : {}),\n ...(params.title ? { title: params.title } : {}),\n ...(params.agentId ? { agentId: params.agentId } : {}),\n ...(params.providerKey && params.modelId ? { providerKey: params.providerKey, modelId: params.modelId } : {}),\n ...(params.providerKey && params.modelId && typeof params.account === 'string' && params.account ? { account: params.account } : {}),\n ...(params.fallbacks ? { fallbacks: params.fallbacks } : {}),\n ...(params.extensionEdit ? { extensionEdit: true } : {}),\n ...(params.skillEdit?.name ? { skillEdit: { name: params.skillEdit.name } } : {}),\n ...(typeof params.spaceId === 'string' && params.spaceId ? { spaceId: params.spaceId } : {}),\n ...(typeof params.sideOf === 'string' && params.sideOf ? { sideOf: params.sideOf } : {}),\n ...(params.environment?.kind\n ? {\n environment: {\n kind: params.environment.kind,\n ...(params.environment.branch ? { branch: params.environment.branch } : {}),\n ...(params.environment.base ? { base: params.environment.base } : {}),\n },\n }\n : {}),\n })\n const data = await loadOrThrow(store, id)\n broadcast({ kind: 'sessions:changed', op: 'create', sessionId: id })\n return stamp(toRow(host, data))\n }\n\n return {\n 'sessions.list': async p => (await listSessionRows(host, store, p)).map(stamp),\n // Awaited, not returned: a rejection handed back unawaited reaches Bun's unhandled-rejection check first.\n 'sessions.create': async (p, peer) => await createSessionRow(p, p.policy === undefined ? undefined : await checkPolicyParam(p.policy, peer, 'sessions.create')),\n 'sessions.delete': async (p) => {\n forgetSession(p.sessionId)\n // Agent retirement + environment + row + on-disk artifacts: the shared host delete.\n const { environment } = await host.deleteSession(p.sessionId)\n broadcast({ kind: 'sessions:changed', op: 'delete', sessionId: p.sessionId })\n return environment.removed && !environment.reason ? {} : { environment }\n },\n 'sessions.sideSession': async (p) => {\n const rowOf = async (id: string | undefined): Promise<SessionRow | null> => {\n const data = id ? await store.load(id) : null\n return data ? stamp(toRow(host, data)) : null\n }\n const [side, parent] = await Promise.all([rowOf(await newestSideSession(store, p.sessionId)), rowOf(p.sessionId)])\n return { side, parent }\n },\n // Rename skips the recency bump so it doesn't yank the row to the top\n // of recency-sorted lists (mirrors the GUI).\n // A typed title: auto-titling never replaces it (`metadata.titleSource`).\n 'sessions.setTitle': p => patchSessionMeta(p.sessionId, { title: p.title, [TITLE_SOURCE_KEY]: 'user' }, { bumpUpdatedAt: false }),\n 'sessions.setArchived': async (p) => {\n await patchSessionMeta(p.sessionId, { archived: p.archived })\n // An archived session's shells on this machine end (in the background:\n // archiving never waits on a slow one); its environment's are left to idle suspension.\n if (p.archived)\n void host.terminals.archiveSession(p.sessionId)\n },\n // Like a rename: not activity, so the row keeps its place by recency.\n 'sessions.setFavorite': p => patchSessionMeta(p.sessionId, { favorite: p.favorite }, { bumpUpdatedAt: false }),\n // Replaces the whole policy; `{}` clears it. Not activity: no recency bump.\n 'sessions.setPolicy': (p, peer) => {\n const write = async (): Promise<void> => {\n // Live metadata first: it is what the host enforces.\n const current = async () => sessionPolicyOf((host.getLiveSession(p.sessionId) ?? await loadOrThrow(store, p.sessionId)).metadata)\n const policy = await checkPolicyParam(p.policy, peer, 'sessions.setPolicy', current)\n return patchSessionMeta(p.sessionId, { [SESSION_POLICY_KEY]: Object.keys(policy).length > 0 ? policy : undefined }, { bumpUpdatedAt: false })\n }\n const next = (policyWrites.get(p.sessionId) ?? Promise.resolve()).then(write, write)\n const settled = next.catch(() => undefined)\n policyWrites.set(p.sessionId, settled)\n void settled.then(() => {\n if (policyWrites.get(p.sessionId) === settled)\n policyWrites.delete(p.sessionId)\n })\n return next\n },\n // Default is stored as its id rather than deleted: the patch is a shallow\n // spread, and every reader maps the Default id to \"no space\".\n // A move is not activity: no recency bump.\n 'sessions.setSpace': p => patchSessionMeta(\n p.sessionId,\n { [SPACE_METADATA_KEY]: typeof p.spaceId === 'string' && p.spaceId ? p.spaceId : DEFAULT_SPACE_ID },\n { bumpUpdatedAt: false },\n ),\n 'sessions.setAgentId': async (p) => {\n /*\n * `agentId` is a top-level field (not metadata) and rebuilds the\n * agent. Patch the LIVE document when the host holds one — a bare\n * store patch loads a stale copy whose full save would clobber\n * mid-run turn appends, and the untouched live doc would revert the\n * label on its next save. Idle sessions take the store patch (no\n * concurrent writer). Then retire the agent (deferred to run end\n * while running) so a swap doesn't abort a shared run mid-stream —\n * unless the live agent's composition fits the new profile\n * (`ChatHost.agentSwitchRebuilds`).\n */\n const rebuild = host.agentSwitchRebuilds(p.sessionId, p.agentId)\n if (await host.setLiveSessionAgentId(p.sessionId, p.agentId)) {\n broadcast({ kind: 'sessions:changed', op: 'update', sessionId: p.sessionId })\n }\n else {\n await patchSession(p.sessionId, (d) => {\n d.agentId = p.agentId\n })\n }\n if (rebuild)\n host.disposeAgentForRebuild(p.sessionId)\n },\n 'sessions.setEffort': p => patchSessionMeta(p.sessionId, { effort: p.effort }),\n 'sessions.setModel': async (p) => {\n // The one model-swap contract (`ChatHost.setSessionModel`): patch\n // race-free, replace the chain, reset effort/options, retire the agent\n // (run-end deferred mid-run). Documented in protocol.ts.\n await host.setSessionModel(p.sessionId, {\n providerKey: p.providerKey,\n modelId: p.modelId,\n ...(typeof p.account === 'string' && p.account ? { account: p.account } : {}),\n ...(p.fallbacks ? { fallbacks: p.fallbacks } : {}),\n ...(p.effort ? { effort: p.effort } : {}),\n ...(p.modelOptions ? { modelOptions: p.modelOptions } : {}),\n })\n broadcast({ kind: 'sessions:changed', op: 'update', sessionId: p.sessionId })\n },\n 'sessions.setModelOptions': p => patchSessionMeta(p.sessionId, { modelOptions: p.options }),\n 'sessions.setFolder': (p) => {\n const cwd = typeof p.cwd === 'string' ? p.cwd : ''\n // The host checks it: against this host's roots, or a machine session's machine's (`docs/MACHINES.md` § Folders).\n return host.setSessionFolder(p.sessionId, cwd)\n },\n }\n}\n\n/** The creation-time metadata a client may stamp: the pick's effort and options, pinned skills. */\nfunction creationMetadata(params: CreateSessionParams): Record<string, unknown> | undefined {\n const metadata: Record<string, unknown> = {}\n if (typeof params.effort === 'string')\n metadata.effort = params.effort\n if (params.modelOptions && typeof params.modelOptions === 'object') {\n const options = Object.fromEntries(Object.entries(params.modelOptions).filter(([, on]) => typeof on === 'boolean'))\n if (Object.keys(options).length > 0)\n metadata.modelOptions = options\n }\n if (Array.isArray(params.pinnedSkills)) {\n const pins = readPinnedSkills(params.pinnedSkills.slice(0, 64))\n if (pins.size > 0)\n metadata[PINNED_SKILLS_META_KEY] = pinnedSkillsValue(pins)\n }\n return Object.keys(metadata).length > 0 ? metadata : undefined\n}\n\nexport async function listSessionRows(host: ChatHost, store: SessionStore, p: IpcParams<'sessions.list'>): Promise<SessionRow[]> {\n const filter\n = p?.projectRoot !== undefined ? { projectRoot: p.projectRoot as string | null } : undefined\n\n const applyArchive = (rows: SessionRow[]): SessionRow[] => {\n const filtered = rows.filter((row) => {\n if (p?.archive === 'active')\n return !row.archived\n if (p?.archive === 'archived')\n return row.archived\n return true\n })\n filtered.sort((a, b) => b.updatedAt - a.updatedAt)\n return filtered\n }\n\n /*\n * Fast path: `listMeta` returns header rows without materializing\n * turn arrays — O(sessions), not O(total turns). Falls back to the\n * load-per-id path for stores that don't implement it.\n */\n if (store.listMeta) {\n const metas = await store.listMeta(filter)\n return applyArchive(metas.filter(meta => !isSideSession(meta.metadata)).map((meta) => {\n const md = meta.metadata\n // Canonical derivation — the same helper the TUI list uses, so\n // daemon-fed rows can't render a different title for the same\n // session (the hand-rolled fallback had its own truncation).\n const title = deriveSessionTitle(meta.firstUserTurn ? [meta.firstUserTurn] : [], md)\n const running = host.isSessionRunning(meta.id)\n return {\n id: meta.id,\n title,\n projectRoot: meta.projectRoot ?? null,\n cwd: typeof md.cwd === 'string' ? md.cwd : (meta.projectRoot ?? ''),\n ...(meta.agentId ? { agentId: meta.agentId } : {}),\n // A crashed process's leftover 'running' marker must not render\n // forever — apply the same freshness bound the run guard uses.\n status: running\n ? 'running' as const\n : isStaleRunMarker(meta.status, meta.updatedAt, Date.now(), meta.runOwner)\n ? 'idle' as const\n : (meta.status ?? 'idle'),\n ...(running ? runStartOf(host, meta.id) : {}),\n createdAt: meta.createdAt ?? 0,\n updatedAt: meta.updatedAt,\n archived: md.archived === true,\n ...(md.favorite === true ? { favorite: true } : {}),\n ...(() => {\n const environment = sessionEnvironmentSummary(md)\n return environment ? { environment } : {}\n })(),\n ...(typeof md.providerKey === 'string' ? { providerKey: md.providerKey } : {}),\n ...(typeof md.modelId === 'string' ? { modelId: md.modelId } : {}),\n ...(readSessionAccount(md) ? { account: readSessionAccount(md) } : {}),\n ...(typeof md.effort === 'string' ? { effort: md.effort as SessionRow['effort'] } : {}),\n ...(md.modelOptions && typeof md.modelOptions === 'object'\n ? { modelOptions: md.modelOptions as Record<string, boolean> }\n : {}),\n ...(() => {\n const fallbacks = sessionModelFallbacks(md)\n return fallbacks ? { modelFallbacks: fallbacks } : {}\n })(),\n }\n }))\n }\n\n const ids = await store.list(filter)\n const rows: SessionRow[] = []\n for (const id of ids) {\n const data = await store.load(id)\n if (!data || isSideSession(data.metadata))\n continue\n rows.push(toRow(host, data))\n }\n return applyArchive(rows)\n}\n\n/** The newest `/side` session of `parentId` (`metadata.sideOf`). */\nasync function newestSideSession(store: SessionStore, parentId: string): Promise<string | undefined> {\n const rows = store.listMeta\n ? (await store.listMeta()).map(row => ({ id: row.id, metadata: row.metadata, updatedAt: row.updatedAt }))\n : (await Promise.all((await store.list()).map(async (id) => {\n const data = await store.load(id)\n return { id, metadata: data?.metadata, updatedAt: data?.updatedAt ?? 0 }\n })))\n return rows\n .filter(row => row.id !== parentId && sideSessionParent(row.metadata) === parentId)\n .sort((a, b) => b.updatedAt - a.updatedAt)[0]\n ?.id\n}\n\n/** A running session's `runStartedAt`: its top-level run in progress, as the agent recorded it. */\nfunction runStartOf(host: ChatHost, sessionId: string): { runStartedAt?: number } {\n const run = runInProgress(host.getLiveSession(sessionId)?.runs ?? [])\n return run ? { runStartedAt: run.startedAt } : {}\n}\n\nfunction toRow(host: ChatHost, data: SessionData): SessionRow {\n const meta = data.metadata ?? {}\n // Canonical derivation — same helper as the TUI list (see the\n // listMeta fast path above).\n const title = deriveSessionTitle(data.turns, meta)\n const running = host.isSessionRunning(data.id)\n\n return {\n id: data.id,\n title,\n ...(isMainSession(meta) ? { isMain: true } : {}),\n ...(readSessionSpaceId(meta) ? { spaceId: readSessionSpaceId(meta) } : {}),\n projectRoot: data.projectRoot ?? null,\n cwd: typeof meta.cwd === 'string' ? meta.cwd : (data.projectRoot ?? ''),\n ...(typeof data.agentId === 'string' ? { agentId: data.agentId } : {}),\n status: running\n ? 'running'\n : isStaleRunMarker(data.status, data.updatedAt, Date.now(), data.runOwner)\n ? 'idle'\n : data.status,\n ...(running ? runStartOf(host, data.id) : {}),\n createdAt: data.createdAt,\n updatedAt: data.updatedAt,\n archived: meta.archived === true,\n ...(meta.favorite === true ? { favorite: true } : {}),\n ...(() => {\n const environment = sessionEnvironmentSummary(meta)\n return environment ? { environment } : {}\n })(),\n ...(typeof meta.providerKey === 'string' ? { providerKey: meta.providerKey } : {}),\n ...(typeof meta.modelId === 'string' ? { modelId: meta.modelId } : {}),\n ...(readSessionAccount(meta) ? { account: readSessionAccount(meta) } : {}),\n ...(typeof meta.effort === 'string' ? { effort: meta.effort as SessionRow['effort'] } : {}),\n ...(meta.modelOptions && typeof meta.modelOptions === 'object'\n ? { modelOptions: meta.modelOptions as Record<string, boolean> }\n : {}),\n ...(() => {\n const fallbacks = sessionModelFallbacks(meta)\n return fallbacks ? { modelFallbacks: fallbacks } : {}\n })(),\n }\n}\n","import type { CloneRun } from '../../../chat/git/clone'\n/**\n * A folder's git checkout (`git.*`): the composer's git bar, the branch menu,\n * the Files tab's changed marks and working-tree diffs, a commit chip's facts,\n * sync, the repository import (while `clone` allows it), and a checkout's refs moving (`git.watch`:\n * `git:refs` to the connections that follow it). The git and `gh` work is\n * the desktop app's own (`src/chat/git`, `src/chat/workspace/files`); this\n * slice confines every folder to the host's workspace roots and finds the\n * sessions in a checkout.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { SessionStore } from '../../../session/index'\nimport type { HostPeer } from '../peers'\nimport type { WorkspaceRoots } from '../workspace-roots'\nimport type { Handlers } from './types'\nimport { realpathSync } from 'node:fs'\nimport { cloneRepository } from '../../../chat/git/clone'\nimport { forgetGitCaches, gitBranches, gitCommit, gitCreateBranch, gitInfo, gitPr, gitPrList, gitSwitch } from '../../../chat/git/info'\nimport { parseRepoInput } from '../../../chat/git/repo-url'\nimport { gitSync } from '../../../chat/git/sync'\nimport { createGitWatches } from '../../../chat/git/watch'\nimport { findGitRoot } from '../../../chat/project-root'\nimport { isInside } from '../../../chat/workspace-confinement'\nimport { gitDiff, gitStatus } from '../../../chat/workspace/files'\nimport { InvalidParamsError, optionalString, requiredString } from './params'\nimport { listSessionRows } from './sessions'\n\n/** What `git.clone` answers while a zidane-server's `allowClone` is off. */\nexport const CLONE_OFF_MESSAGE = 'Cloning is off on this server (allowClone).'\n\ntype GitMethod\n = | 'git.status' | 'git.branches' | 'git.pullRequests' | 'git.branchPullRequest' | 'git.commit' | 'git.fileStatus'\n | 'git.diff' | 'git.checkout' | 'git.createBranch' | 'git.sync' | 'git.clone' | 'git.cloneCancel' | 'git.watch' | 'git.unwatch'\n\n/** The checkout holding `folder` (a nested worktree or repository is its own), or the folder outside git. */\nfunction checkoutOf(folder: string): string | null {\n try {\n const real = realpathSync.native(folder)\n return findGitRoot(real) ?? real\n }\n catch {\n return null\n }\n}\n\nexport function createGitHandlers({ host, store, workspace, isConnected, onClose, clone = () => true }: {\n host: ChatHost\n store: SessionStore\n workspace: WorkspaceRoots\n isConnected: (peer: HostPeer) => boolean\n /** Registers a peer-close hook: a dropped connection's clone is cancelled, its watches released. */\n onClose: (release: (peer: HostPeer) => void) => void\n /** Clients may clone (`git.clone`): a zidane-server's `allowClone`. Default: yes. */\n clone?: () => boolean\n}): Handlers<GitMethod> {\n const clones = new Map<HostPeer, CloneRun>()\n onClose(peer => clones.get(peer)?.cancel())\n // Keyed by the folder as each client names it: `git:refs` carries that name back.\n const refs = createGitWatches<HostPeer>((cwd, change) => {\n forgetGitCaches(cwd, change === 'refs' ? 'git:refs' : 'git:config')\n if (change === 'refs') {\n for (const peer of refs.owners(cwd))\n peer.send({ kind: 'git:refs', cwd })\n }\n })\n onClose(peer => refs.release(peer))\n const folder = (cwd: unknown): string => workspace.resolveFolder(requiredString(cwd, 'cwd'))\n /** `folder`, when the checkout holding it is inside the roots too: git reports on the whole repository, not the folder it runs in. */\n const repoFolder = (cwd: unknown): string => {\n const at = folder(cwd)\n workspace.resolveFolder(findGitRoot(at) ?? at)\n return at\n }\n\n /** The unarchived sessions working in `cwd`'s checkout, `except` left out. */\n async function sessionsInCheckout(cwd: string, except?: string): Promise<string[]> {\n const checkout = checkoutOf(cwd)\n if (!checkout)\n return []\n const rows = await listSessionRows(host, store, { archive: 'active' })\n return rows.filter(row => row.id !== except && row.cwd && checkoutOf(row.cwd) === checkout).map(row => row.id)\n }\n\n /** An agent runs in `cwd`'s checkout (the asking session included). */\n async function agentRunsIn(cwd: string, sessionId: string | undefined): Promise<boolean> {\n if (sessionId && host.isSessionRunning(sessionId))\n return true\n return (await sessionsInCheckout(cwd, sessionId)).some(id => host.isSessionRunning(id))\n }\n\n return {\n 'git.status': p => gitInfo(folder(p.cwd)),\n 'git.branches': p => gitBranches(folder(p.cwd)),\n 'git.pullRequests': p => gitPrList(folder(p.cwd), optionalString(p.search, 'search'), p.fresh === true),\n 'git.branchPullRequest': p => gitPr(folder(p.cwd), requiredString(p.branch, 'branch'), p.fresh === true),\n 'git.commit': p => gitCommit(repoFolder(p.cwd), requiredString(p.sha, 'sha')),\n 'git.fileStatus': p => gitStatus(repoFolder(p.cwd)),\n 'git.diff': (p) => {\n if (p.context !== undefined && p.context !== null && (typeof p.context !== 'number' || p.context < 0))\n throw new InvalidParamsError('context must be a non-negative number or null.')\n return gitDiff(repoFolder(p.cwd), optionalString(p.path, 'path'), p.context === null ? Infinity : p.context)\n },\n 'git.checkout': async (p) => {\n const cwd = folder(p.cwd)\n const target = p.target as unknown\n const pr = typeof target === 'object' && target !== null ? (target as { pr?: unknown }).pr : undefined\n if (typeof target !== 'string' && typeof pr !== 'number')\n throw new InvalidParamsError('target must be a branch name or { pr: number }.')\n const sessionId = optionalString(p.sessionId, 'sessionId')\n const result = await gitSwitch(cwd, typeof target === 'string' ? target : { pr: pr as number }, await agentRunsIn(cwd, sessionId))\n if (result.ok || !result.worktree)\n return result\n // git names the worktree resolved: only one inside the roots is told apart by its sessions.\n const inRoots = workspace.describe().roots.some(root => isInside(root, result.worktree!))\n return { ...result, chats: inRoots ? await sessionsInCheckout(result.worktree, sessionId) : [] }\n },\n 'git.createBranch': async (p) => {\n const cwd = folder(p.cwd)\n return gitCreateBranch(cwd, requiredString(p.name, 'name'), await agentRunsIn(cwd, optionalString(p.sessionId, 'sessionId')))\n },\n 'git.sync': async (p) => {\n const cwd = folder(p.cwd)\n return gitSync(cwd, await agentRunsIn(cwd, optionalString(p.sessionId, 'sessionId')))\n },\n 'git.clone': async (p, peer) => {\n if (!clone())\n throw new Error(CLONE_OFF_MESSAGE)\n const input = requiredString(p.input, 'input')\n const parent = workspace.resolveFolder(requiredString(p.parent, 'parent'))\n // A `file://` source is a folder on this machine: confined like `parent`, or a client copies out what the roots keep from it.\n const spec = parseRepoInput(input)\n if (spec && /^file:/i.test(spec.cloneUrl)) {\n const source = new URL(spec.cloneUrl)\n if (source.host && source.host !== 'localhost')\n throw new InvalidParamsError('A file:// source must be on this machine.')\n workspace.resolveFolder(decodeURIComponent(source.pathname))\n }\n if (clones.has(peer))\n return { ok: false, error: 'A clone is already running.' }\n const run = cloneRepository(input, parent, ({ phase, percent }) => {\n if (isConnected(peer))\n peer.send({ kind: 'git:clone:progress', phase, percent })\n })\n clones.set(peer, run)\n try {\n return await run.result\n }\n finally {\n clones.delete(peer)\n }\n },\n 'git.cloneCancel': (_p, peer) => {\n clones.get(peer)?.cancel()\n },\n 'git.watch': (p, peer) => {\n folder(p.cwd)\n return refs.watch(p.cwd, peer)\n },\n 'git.unwatch': (p, peer) => {\n refs.unwatch(peer, requiredString(p.cwd, 'cwd'))\n },\n }\n}\n","/** Transcript history search, per session and across sessions, over one shared index cache. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { SessionHistoryMatch, SessionSearchIndex } from '../../../chat/index'\nimport type { SessionStore } from '../../../session/index'\nimport type { SessionTurn } from '../../../types'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { buildSessionSearchIndexAsync, searchSessionHistoryIndexAsync, searchSessionIndexAsync } from '../../../chat/history-search'\n\n/*\n * Daemon-side history search — one index cache shared by EVERY window,\n * so repeat queries (and other windows' queries) pay match cost only.\n * Off the UI thread by construction (this process has no renderer), so\n * no Worker indirection is needed. Live sessions index the host's\n * in-memory turns (fresh mid-run); idle sessions index store turns.\n * LRU-bounded — full-text indexes can reach 512k chars per turn.\n */\nconst SEARCH_INDEX_CACHE_MAX = 64\n\nexport function createHistoryHandlers({ host, store }: {\n host: ChatHost\n store: SessionStore\n}): Handlers<'history.searchSession' | 'history.searchAll'> {\n /** Latest `history.searchAll` generation per peer — see the handler. */\n const searchGenerations = new WeakMap<HostPeer, number>()\n const searchIndexCache = new Map<string, { key: string, index: SessionSearchIndex }>()\n\n async function sessionSearchIndex(sessionId: string): Promise<SessionSearchIndex | null> {\n const liveTurns = host.getLiveTurns(sessionId)\n let turns: readonly SessionTurn[]\n let key: string\n if (liveTurns) {\n /*\n * SNAPSHOT before the async index build — the agent may append\n * mid-build and the builder yields between turns. The cache key\n * folds in the last turn id so a same-count content change (e.g.\n * compaction replacing turns) can't serve a stale index.\n */\n turns = [...liveTurns]\n key = `live:${turns.length}:${turns.at(-1)?.id ?? ''}`\n }\n else {\n const data = await store.load(sessionId)\n if (!data)\n return null\n turns = data.turns\n key = `store:${data.updatedAt}:${data.turns.length}`\n }\n\n const cached = searchIndexCache.get(sessionId)\n if (cached?.key === key) {\n // Refresh LRU recency (Map preserves insertion order).\n searchIndexCache.delete(sessionId)\n searchIndexCache.set(sessionId, cached)\n return cached.index\n }\n\n const index = await buildSessionSearchIndexAsync(turns)\n searchIndexCache.set(sessionId, { key, index })\n while (searchIndexCache.size > SEARCH_INDEX_CACHE_MAX) {\n const oldest = searchIndexCache.keys().next().value\n if (oldest === undefined)\n break\n searchIndexCache.delete(oldest)\n }\n return index\n }\n\n return {\n 'history.searchSession': async (p) => {\n const index = await sessionSearchIndex(p.sessionId)\n if (!index)\n return []\n // Wire-supplied limit: unchecked JSON — coerce to a sane positive\n // integer bounded by the corpus (same policy as queue/draft bounds).\n const limit = Number.isInteger(p.limit) && (p.limit as number) > 0\n ? Math.min(p.limit as number, index.turns.length)\n : index.turns.length\n const matches = await searchSessionIndexAsync(index, p.query, { limit })\n // Turn order, not relevance — search is a transcript filter, and\n // sorting here spares clients from re-fetching the turn list.\n const order = new Map(index.turns.map((entry, i) => [entry.turn.id, i]))\n matches.sort((a, b) => (order.get(a.turn.id) ?? 0) - (order.get(b.turn.id) ?? 0))\n return matches\n },\n 'history.searchAll': async (p, peer) => {\n /*\n * Per-peer supersession: search fires per debounced keystroke and\n * the client discards stale responses, but without this the daemon\n * would still run every superseded full-corpus pass to completion —\n * stacked CPU that delays signal fan-out for every window. A newer\n * query from the same peer makes older loops bail at the next\n * session boundary (partial result; the client ignores it anyway).\n */\n const generation = (searchGenerations.get(peer) ?? 0) + 1\n searchGenerations.set(peer, generation)\n\n const results: Record<string, SessionHistoryMatch> = {}\n // Bound the per-request corpus: `store.load` materializes full turn\n // arrays, and supersession only cancels SAME-peer re-queries — one\n // oversized request must not run the shared daemon to completion.\n const ids = Array.isArray(p.sessionIds) ? p.sessionIds.slice(0, 500) : []\n for (const sessionId of ids) {\n if (searchGenerations.get(peer) !== generation)\n break\n try {\n const index = await sessionSearchIndex(sessionId)\n if (!index)\n continue\n const match = await searchSessionHistoryIndexAsync(index, p.query, p.excerptLimit ?? 3)\n if (match)\n results[sessionId] = match\n }\n catch {\n // One bad session must not sink the whole cross-session search.\n }\n }\n return results\n },\n }\n}\n","/**\n * Human-in-the-loop: tool approvals and interactions (questions, plans)\n * awaiting an answer, and the \"Always allow\" entries approvals saved (the\n * host user's `projects.json`).\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { PendingInteraction } from '../../../chat/host/signals'\nimport type { SessionStore } from '../../../session/index'\nimport type { Handlers } from './types'\nimport { pendingInteractionsFromTurns } from '../../../chat/interactions-protocol'\nimport { listSafelists, removeFromSafelist } from '../../../chat/safe-mode'\nimport { requiredString } from './params'\n\ntype HitlMethod\n = | 'interactions.list' | 'interactions.respond' | 'interactions.cancel' | 'interactions.rehydrate' | 'interactions.rehydrateSessions'\n | 'approvals.resolve' | 'approvals.denyAll' | 'approvals.listPending'\n | 'safelist.list' | 'safelist.remove'\n\n/** Turns read back from a session's end to find a question its run stopped on (notes may follow it). */\nconst OPEN_PROMPT_TAIL = 20\n\n/**\n * Whether the session's last turns hold a question or plan with no answer,\n * read without loading the session. A store with no header index answers\n * `true`: it is loaded, as a window opening it would.\n */\nasync function endsOnOpenPrompt(store: SessionStore, sessionId: string): Promise<boolean> {\n if (!store.getMeta)\n return true\n const meta = await store.getMeta(sessionId)\n if (!meta)\n return false\n // `turnCount` leaves out system turns: from there, the tail still reaches the last turn.\n const tail = await store.getTurns(sessionId, Math.max(0, (meta.turnCount ?? 0) - OPEN_PROMPT_TAIL))\n return pendingInteractionsFromTurns(tail).length > 0\n}\n\nexport function createHitlHandlers({ host, store, userDataDir }: { host: ChatHost, store: SessionStore, userDataDir: () => string }): Handlers<HitlMethod> {\n return {\n 'interactions.list': p => host.interactions.list(p?.sessionId),\n 'interactions.respond': p => host.interactions.respond(p.requestId, p.response),\n 'interactions.cancel': p => host.interactions.cancel(p.requestId, p.reason),\n // A window opening a session: a durable run a dead process left resumes, or its question goes up first, so the list below has it.\n 'interactions.rehydrate': async (p) => {\n await host.resumePending({ sessionId: p.sessionId }).catch(() => undefined)\n return host.interactions.rehydrate(p.sessionId)\n },\n // A channel start, over every conversation it ever had: a session is loaded only when its run waits to resume or its last turns ask.\n 'interactions.rehydrateSessions': async (p) => {\n const out: PendingInteraction[] = []\n for (const sessionId of Array.isArray(p.sessionIds) ? p.sessionIds : []) {\n if (typeof sessionId !== 'string' || host.isSessionRunning(sessionId))\n continue\n await host.resumePending({ sessionId }).catch(() => undefined)\n if (await endsOnOpenPrompt(store, sessionId).catch(() => false))\n out.push(...await host.interactions.rehydrate(sessionId))\n }\n return out\n },\n\n 'approvals.resolve': p => host.approvals.resolve(p.requestId, p.decision),\n 'approvals.denyAll': p => host.approvals.denyAll(p?.sessionId),\n 'approvals.listPending': () => host.approvals.listPending(),\n\n 'safelist.list': () => ({ projects: listSafelists(userDataDir()) }),\n 'safelist.remove': p => ({ removed: removeFromSafelist(userDataDir(), requiredString(p.project, 'project'), requiredString(p.entry, 'entry')) }),\n }\n}\n","/** Per-client launch overrides: each window's own, the latest connected setter's applied. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { SessionLaunchOverrides } from '../../../chat/host/launch-overrides'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { normalizeLaunchOverrides } from '../../../chat/host/launch-overrides'\n\n/**\n * A confined host (a server) drops a `cwd` outside its workspace roots\n * itself (`ChatHost.setLaunchOverrides`): a window's own folder is a path on\n * ITS machine, which the session must not move to.\n */\nexport function createLaunchOverrideHandlers({ host }: { host: ChatHost }): {\n methods: Handlers<'sessions.setLaunchOverrides'>\n /** The peer dropped: forget its overrides, so the previous setter's apply again. */\n releasePeer: (peer: HostPeer) => void\n /** The session was deleted: forget every setter's overrides. */\n forget: (sessionId: string) => void\n} {\n /**\n * Each client's launch overrides per session, oldest setter first. The\n * session runs the most recent connected setter's; a client clearing, or\n * disconnecting, drops only its own, and the previous setter's apply again.\n */\n const launchOverridesByPeer = new Map<string, Map<HostPeer, SessionLaunchOverrides>>()\n\n /** Run the latest connected setter's overrides (see `launchOverridesByPeer`). */\n const applyLaunchOverrides = (sessionId: string): void => {\n const setters = launchOverridesByPeer.get(sessionId)\n const latest = setters ? [...setters.values()].at(-1) : undefined\n if (!latest)\n launchOverridesByPeer.delete(sessionId)\n host.setLaunchOverrides(sessionId, latest ?? null)\n }\n\n return {\n methods: {\n 'sessions.setLaunchOverrides': (p, peer) => {\n const { sessionId, ...rest } = p\n const next = normalizeLaunchOverrides(rest)\n const setters = launchOverridesByPeer.get(sessionId) ?? new Map<HostPeer, SessionLaunchOverrides>()\n // Re-inserted, so a client setting again becomes the latest setter.\n setters.delete(peer)\n if (next)\n setters.set(peer, next)\n launchOverridesByPeer.set(sessionId, setters)\n applyLaunchOverrides(sessionId)\n },\n },\n releasePeer(peer) {\n for (const [sessionId, setters] of launchOverridesByPeer) {\n if (setters.delete(peer))\n applyLaunchOverrides(sessionId)\n }\n },\n forget(sessionId) {\n launchOverridesByPeer.delete(sessionId)\n },\n }\n}\n","/**\n * Reverse direction (`docs/MACHINES.md` § Reverse direction): this server\n * lends itself as a machine to a client's host over that client's own\n * connection, because a local host (a laptop) has no listener to be dialed.\n * The client sends `machine.attach`, then one `machine.call` per\n * host→machine request; the server's confined executor\n * (`../../machine/executor`, loaded on first attach) answers them inside the\n * server's workspace roots. Machine notifications go back to that connection\n * only, as `machine:notification` signals.\n *\n * Off unless the server allows it (`allowAsMachine`). It does not widen what a\n * client token can do: `sessions.workspaceExec` and terminals already run\n * commands in the same roots with the same token.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { MachineRegisterParams } from '../../../chat/machine-protocol'\nimport type { LooseSandboxSettings } from '../../../chat/sandbox-settings'\nimport type { JsonValue } from '../../../types'\nimport type { MachineExecutor } from '../../machine/executor'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { join } from 'node:path'\nimport { MACHINE_PROTOCOL_VERSION, MachineErrorCode, toMachineName } from '../../../chat/machine-protocol'\nimport { ZIDANE_VERSION } from '../../../version'\n\n/**\n * Executors kept between their connections (tasks, terminals), keyed by the\n * token that attached them and the host id it named: a host id is the\n * client's word, so another token naming it gets an executor of its own,\n * never the first one's tasks, terminals or exits. Each token holds at most\n * {@link MAX_PER_PRINCIPAL} and evicts only its own idle ones.\n */\nconst MAX_PER_PRINCIPAL = 4\nconst MAX_ATTACHED_HOSTS = 32\n\nexport interface MachineServeOptions {\n /** `allowAsMachine`: read per attach, so a restart is not needed to turn it off for new links. */\n allowed: () => boolean\n}\n\nclass MachineServeError extends Error {\n readonly code: number = MachineErrorCode.MethodNotAllowed\n}\n\n/** A capacity limit: the client retries later (`../../machine/reverse.ts`). */\nclass MachineServeBusyError extends MachineServeError {\n override readonly code: number = MachineErrorCode.Busy\n}\n\ninterface Served {\n executor: MachineExecutor\n peer: HostPeer | null\n principal: string\n}\n\n/** Who attached: the token's id (`''` on a host without auth, a loopback test server). */\nconst principalOf = (peer: HostPeer): string => peer.principal ?? ''\n\nexport function createMachineServeHandlers(input: {\n host: ChatHost\n dataDir: () => string\n hostName: string\n settings: () => LooseSandboxSettings\n options?: MachineServeOptions\n isConnected: (peer: HostPeer) => boolean\n}): { methods: Handlers<'machine.attach' | 'machine.call' | 'machine.detach'>, releasePeer: (peer: HostPeer) => void, allowed: () => boolean } {\n const { host } = input\n const allowed = (): boolean => input.options?.allowed() === true\n const served = new Map<string, Served>()\n const byPeer = new Map<HostPeer, string>()\n\n const roots = (): string[] => {\n const { roots: list, confined } = host.workspace\n if (!confined || list.length === 0)\n throw new MachineServeError('This host has no workspace roots to lend.')\n return [...list]\n }\n\n /** Make room for one more of `principal`'s: its own idle executor goes, never another token's. */\n const makeRoom = (principal: string): void => {\n const own = [...served].filter(([, entry]) => entry.principal === principal)\n if (own.length < MAX_PER_PRINCIPAL && served.size < MAX_ATTACHED_HOSTS)\n return\n const idle = own.find(([, entry]) => entry.peer === null)\n if (!idle)\n throw new MachineServeBusyError(own.length >= MAX_PER_PRINCIPAL ? `This token already has ${MAX_PER_PRINCIPAL} hosts attached here.` : `This server already lends itself to ${MAX_ATTACHED_HOSTS} hosts.`)\n served.delete(idle[0])\n void idle[1].executor.close()\n }\n\n async function executorFor(hostId: string, peer: HostPeer): Promise<MachineExecutor> {\n const principal = principalOf(peer)\n const key = `${principal}:${hostId}`\n const existing = served.get(key)\n if (existing) {\n const previous = existing.peer\n if (previous && previous !== peer)\n byPeer.delete(previous)\n existing.peer = peer\n return existing.executor\n }\n makeRoom(principal)\n const { createMachineExecutor } = await import('../../machine/executor')\n const entry: Served = { peer, principal, executor: undefined as unknown as MachineExecutor }\n entry.executor = createMachineExecutor({\n roots: roots().map(path => ({ path })),\n dataDir: join(input.dataDir(), 'machine-self'),\n // The server's own sandbox settings apply to what it runs as a machine, as to its own sessions.\n sandbox: input.settings(),\n credentialsDataDir: input.dataDir(),\n notify: (method, params) => {\n const target = entry.peer\n if (!target || !input.isConnected(target))\n return false\n target.send({ kind: 'machine:notification', method, params: params as JsonValue })\n return true\n },\n })\n served.set(key, entry)\n return entry.executor\n }\n\n const attachedOf = (peer: HostPeer): Served => {\n const key = byPeer.get(peer)\n const entry = key ? served.get(key) : undefined\n if (!entry || entry.peer !== peer)\n throw new MachineServeError('Send machine.attach first on this connection.')\n return entry\n }\n\n return {\n allowed,\n methods: {\n 'machine.attach': async (p, peer) => {\n if (!allowed())\n throw new MachineServeError('This server does not lend itself as a machine (allowAsMachine is off).')\n if (typeof p.hostId !== 'string' || !/^[\\w-]{1,64}$/.test(p.hostId))\n throw new MachineServeError('machine.attach: \"hostId\" must be 1 to 64 letters, digits, \"-\" or \"_\".')\n const executor = await executorFor(p.hostId, peer)\n byPeer.set(peer, `${principalOf(peer)}:${p.hostId}`)\n executor.linkUp()\n const { machineIdentity } = await import('../../machine/identity')\n const result: MachineRegisterParams = {\n machineId: machineIdentity(join(input.dataDir(), 'machine-self')),\n name: toMachineName(input.hostName),\n roots: roots().map(path => ({ path })),\n capabilities: { shell: true, terminals: typeof (globalThis as { Bun?: unknown }).Bun !== 'undefined', background: true, worktrees: true, stream: true, sandboxed: executor.sandbox.on },\n version: ZIDANE_VERSION,\n protocolVersion: MACHINE_PROTOCOL_VERSION,\n }\n return result\n },\n 'machine.call': async (p, peer) => {\n if (!allowed())\n throw new MachineServeError('This server does not lend itself as a machine (allowAsMachine is off).')\n if (typeof p.method !== 'string')\n throw new MachineServeError('machine.call: \"method\" must be a string.')\n return (await attachedOf(peer).executor.handle(p.method, p.params ?? {})) as JsonValue\n },\n 'machine.detach': (_p, peer) => {\n const key = byPeer.get(peer)\n if (!key)\n return { detached: false }\n byPeer.delete(peer)\n const entry = served.get(key)\n if (entry?.peer === peer) {\n entry.peer = null\n entry.executor.linkLost()\n }\n return { detached: true }\n },\n },\n releasePeer(peer) {\n const key = byPeer.get(peer)\n if (!key)\n return\n byPeer.delete(peer)\n const entry = served.get(key)\n if (entry?.peer === peer) {\n entry.peer = null\n entry.executor.linkLost()\n }\n },\n }\n}\n","/**\n * OAuth sign-in over the wire (`auth.oauth.*`): the browser on the client,\n * the tokens on the host.\n *\n * `begin` runs the login HERE (a provider's `runOAuthLogin`, an MCP server's\n * `loginMcpServer`), so the PKCE verifier, `state` and the token exchange\n * never leave the host, and answers with the authorization URL as soon as\n * the login produces it. The redirect lands on the client's loopback (a\n * provider's fixed `redirect_uri`, or the loopback URI the client chose for\n * an MCP server; a browser client's MCP sign-in comes back to this server's\n * own callback instead: `deliverCallback`); the client sends the code back with `complete`, which\n * checks `state` here and hands the code to the waiting login: zidane's\n * providers read it through their manual-input path (`callbackServer:\n * false`: nothing listens on this machine), an MCP login through an\n * injected callback. Paste-back and device-code flows ride the same calls.\n *\n * A provider's questions (a choice between flows, a free-text prompt) are\n * the client's to answer, never picked here: `begin` answers with a `step`\n * when one comes before the URL, `complete` when one comes after, and\n * `respond` delivers the answer. A provider that would listen on this\n * machine for the redirect (one that ignores `callbackServer: false`) is\n * refused: the client's browser could never reach that port.\n *\n * A flow is bound to the connection that began it, takes one code, and\n * expires; a dropped connection abandons its flows. Codes and tokens are\n * never logged nor returned.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { McpStatusTracker } from '../../../chat/mcp-status'\nimport type { McpServerConfig } from '../../../types'\nimport type { HostOAuthBegin, HostOAuthComplete, HostOAuthStep } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { HostPeer } from '../peers'\nimport type { ProviderAuth } from './auth'\nimport type { Handlers } from './types'\nimport { randomBytes } from 'node:crypto'\nimport { setProviderCredential } from '../../../chat/credentials'\nimport { createFileMcpCredentialStore } from '../../../chat/mcp-credentials'\nimport { discoverProjectMcps } from '../../../chat/mcps-discovery'\nimport { runOAuthLogin } from '../../../chat/oauth'\nimport { canSignInRemotely } from '../../../chat/oauth-page/server'\nimport { loginMcpServer } from '../../../mcp/login'\nimport { pinnedMcpRedirectUri } from '../../../mcp/server-config'\nimport { SERVER_OAUTH_CALLBACK_PATH } from '../../browser'\nimport { catalogFolder } from './catalogs'\nimport { InvalidParamsError } from './params'\n\n/** How long a flow waits for its code. */\nexport const OAUTH_FLOW_TTL_MS = 10 * 60_000\n/** Open flows per connection. */\nconst MAX_FLOWS_PER_PEER = 4\n/** How long a login may take to produce its URL. */\nconst BEGIN_TIMEOUT_MS = 30_000\n\ntype Delivery = { code: string, state?: string } | { input: string }\n\ninterface Flow {\n id: string\n peer: HostPeer\n expiresAt: number\n /** The `state` the authorization URL carries; a code must come back with it. */\n expectedState?: string\n /** Where the browser is sent back (rebuilds a callback URL from a code + state). */\n redirectUri?: string\n /** The code comes back to this server's own callback (`deliverCallback`): the MCP server signed in to. */\n held?: string\n delivered: boolean\n deliver: (delivery: Delivery) => void\n result: Promise<HostOAuthComplete>\n abort: AbortController\n timer: ReturnType<typeof setTimeout>\n /** The provider's questions (absent: an MCP sign-in, which asks none). */\n steps?: StepChannel\n /** Where the flow stands for `respond`: its URL once known. */\n started?: Promise<Omit<HostOAuthBegin, 'flowId' | 'expiresAt'>>\n /** Set once the URL was handed out: later questions come through `complete`. */\n begun?: Omit<HostOAuthBegin, 'flowId' | 'expiresAt'>\n}\n\ntype StepInput = { kind: 'select', message: string, options: Array<{ id: string, label: string }> } | { kind: 'prompt', message: string, placeholder?: string, allowEmpty?: boolean }\n\n/** A provider's questions, one at a time: asked by its login, answered by the client. */\ninterface StepChannel {\n ask: (step: StepInput) => Promise<string | undefined>\n /** The question waiting for its answer. */\n pending: () => HostOAuthStep | undefined\n /** The next question (the pending one, if any). */\n next: () => Promise<HostOAuthStep>\n answer: (stepId: string, value: string | undefined) => void\n}\n\nfunction stepChannel(signal: AbortSignal): StepChannel {\n let current: { step: HostOAuthStep, resolve: (value: string | undefined) => void } | undefined\n const waiters: Array<(step: HostOAuthStep) => void> = []\n return {\n ask: step => new Promise((resolve, reject) => {\n if (signal.aborted)\n return reject(new Error('The sign-in was cancelled.'))\n const full = { ...step, id: randomBytes(9).toString('base64url') } as HostOAuthStep\n current = { step: full, resolve }\n signal.addEventListener('abort', () => reject(new Error('The sign-in was cancelled.')), { once: true })\n for (const waiter of waiters.splice(0))\n waiter(full)\n }),\n pending: () => current?.step,\n next: () => (current ? Promise.resolve(current.step) : new Promise(resolve => waiters.push(resolve))),\n answer(stepId, value) {\n const step = current?.step\n if (!step || step.id !== stepId)\n throw new Error('That sign-in is not waiting on this question (answered already, or another one).')\n if (step.kind === 'select' && value !== undefined && !step.options.some(option => option.id === value))\n throw new InvalidParamsError(`\"${value}\" is not one of the choices.`)\n if (step.kind === 'prompt' && (value === undefined || (value.trim() === '' && !step.allowEmpty)))\n throw new InvalidParamsError('That question needs an answer.')\n const { resolve } = current!\n current = undefined\n resolve(value)\n },\n }\n}\n\ninterface Deferred<T> {\n promise: Promise<T>\n resolve: (value: T) => void\n}\n\nfunction deferred<T>(): Deferred<T> {\n let resolve!: (value: T) => void\n const promise = new Promise<T>((r) => {\n resolve = r\n })\n return { promise, resolve }\n}\n\nconst LOOPBACK_HOSTS = new Set(['127.0.0.1', 'localhost', '[::1]', '::1'])\n\n/**\n * Where an MCP sign-in may send the browser: `http://<loopback>:<port>/<path>`\n * on the client, or (`held`) this server's own callback at the origin the\n * client reaches it by, when it serves one. Nothing else.\n */\nfunction mcpRedirect(raw: unknown, serverCallback: boolean): { uri: string, held: boolean } {\n let url: URL | undefined\n try {\n url = typeof raw === 'string' ? new URL(raw) : undefined\n }\n catch {}\n const plain = url !== undefined && !url.username && !url.password && !url.search && !url.hash\n if (plain && serverCallback && (url!.protocol === 'https:' || url!.protocol === 'http:') && url!.pathname === SERVER_OAUTH_CALLBACK_PATH)\n return { uri: url!.toString(), held: true }\n if (!plain || url!.protocol !== 'http:' || !LOOPBACK_HOSTS.has(url!.hostname) || !url!.port)\n throw new InvalidParamsError(`redirectUri must be a loopback URL on the client (http://127.0.0.1:<port>/callback)${serverCallback ? ` or this server's ${SERVER_OAUTH_CALLBACK_PATH}` : ''}.`)\n return { uri: url!.toString(), held: false }\n}\n\n/** `state` in what a user pasted: a callback URL, a `code=…&state=…` query, or Anthropic's `code#state`. */\nfunction stateIn(input: string): string | undefined {\n const value = input.trim()\n try {\n return new URL(value).searchParams.get('state') ?? undefined\n }\n catch {}\n if (value.includes('#'))\n return value.split('#', 2)[1]\n if (value.includes('state='))\n return new URLSearchParams(value).get('state') ?? undefined\n return undefined\n}\n\n/** The code in a pasted callback URL / query / `code#state`. */\nfunction codeIn(input: string): string | undefined {\n const value = input.trim()\n try {\n return new URL(value).searchParams.get('code') ?? undefined\n }\n catch {}\n if (value.includes('#'))\n return value.split('#', 2)[0]\n if (value.includes('code='))\n return new URLSearchParams(value).get('code') ?? undefined\n return value || undefined\n}\n\nfunction isLoopbackUrl(raw: string | null): raw is string {\n if (!raw)\n return false\n try {\n const url = new URL(raw)\n return url.protocol === 'http:' && LOOPBACK_HOSTS.has(url.hostname)\n }\n catch {\n return false\n }\n}\n\n/** What a provider's manual-input path reads: the pasted text, or the callback URL rebuilt from a code + state. */\nfunction manualInput(delivery: Delivery, redirectUri: string | undefined): string {\n if ('input' in delivery)\n return delivery.input\n const query = new URLSearchParams({ code: delivery.code, ...(delivery.state !== undefined ? { state: delivery.state } : {}) }).toString()\n return redirectUri ? `${redirectUri}?${query}` : query\n}\n\n/** First of: what the login produced, its early end, a timeout, the abort. */\nasync function firstOf<T>(started: Promise<T>, login: Promise<unknown>, signal: AbortSignal): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined\n try {\n return await Promise.race([\n started,\n login.then(() => {\n throw new Error('The sign-in finished without a browser step (already signed in?).')\n }),\n new Promise<never>((_, reject) => {\n timer = setTimeout(reject, BEGIN_TIMEOUT_MS, new Error(`The sign-in did not produce an authorization URL within ${BEGIN_TIMEOUT_MS / 1000}s.`))\n signal.addEventListener('abort', () => reject(new Error('The sign-in was cancelled.')), { once: true })\n }),\n ])\n }\n finally {\n clearTimeout(timer)\n }\n}\n\n/**\n * A provider's login, running here for a client: its URL (once known), its\n * questions, the code the client delivers, its stored result. Refused for a\n * provider that would listen on this machine (see the module header).\n */\nfunction startProviderLogin(auth: ProviderAuth, provider: unknown) {\n const descriptor = auth.descriptorOf(provider)\n if (!descriptor.oauthProvider)\n throw new Error(`OAuth not supported for ${descriptor.label} (${descriptor.key}). Use an API key instead.`)\n if (!canSignInRemotely(descriptor.oauthProvider))\n throw new Error(`${descriptor.label}'s sign-in can't run from another computer: it waits for the browser on a port of the server's own machine. Sign in on the server machine or use an API key.`)\n const abort = new AbortController()\n const code = deferred<string>()\n const steps = stepChannel(abort.signal)\n const url = deferred<{ url: string, instructions?: string, userCode?: string, device?: true }>()\n const login = runOAuthLogin(descriptor, {\n onUrl: (u, instructions) => url.resolve({ url: u, ...(instructions ? { instructions } : {}) }),\n onDeviceCode: info => url.resolve({ url: info.verificationUri, userCode: info.userCode, device: true }),\n // The loopback's callback URL, or what the user pasted.\n onManualCodeInput: () => code.promise,\n // The provider's own questions go to the client (never answered here).\n onPrompt: prompt => steps.ask({ kind: 'prompt', message: prompt.message, ...(prompt.placeholder ? { placeholder: prompt.placeholder } : {}), ...(prompt.allowEmpty ? { allowEmpty: true } : {}) }).then(value => value ?? ''),\n onSelect: prompt => steps.ask({ kind: 'select', message: prompt.message, options: prompt.options.map(option => ({ id: option.id, label: option.label })) }),\n signal: abort.signal,\n callbackServer: false,\n openBrowser: false,\n })\n login.catch(() => undefined)\n // Where the flow stands once it has its URL (the loopback redirect the code is rebuilt for).\n let redirectUri: string | undefined\n const started = url.promise.then((first): Omit<HostOAuthBegin, 'flowId' | 'expiresAt'> => {\n if (!first.device) {\n const redirect = new URL(first.url).searchParams.get('redirect_uri')\n if (isLoopbackUrl(redirect))\n redirectUri = redirect\n }\n return {\n url: first.url,\n mode: first.device ? 'device' : redirectUri ? 'loopback' : 'browser',\n ...(redirectUri ? { redirectUri } : {}),\n ...(first.userCode ? { userCode: first.userCode } : {}),\n ...(first.instructions ? { instructions: first.instructions } : {}),\n }\n })\n started.catch(() => undefined)\n const result = login.then((credentials): HostOAuthComplete => {\n setProviderCredential(auth.dataDir(), descriptor, { kind: 'oauth', ...credentials })\n auth.applied(descriptor)\n return { provider: auth.statusOf(descriptor.key) }\n })\n return { login, abort, result, steps, started, deliver: (delivery: Delivery) => code.resolve(manualInput(delivery, redirectUri)) }\n}\n\n/** The flow `flowId` names, if it exists and belongs to this connection. */\nfunction flowOf(flows: ReadonlyMap<string, Flow>, flowId: unknown, peer: HostPeer): Flow {\n const flow = typeof flowId === 'string' ? flows.get(flowId) : undefined\n if (!flow)\n throw new Error('No sign-in with that id: it finished, expired or was cancelled. Start it again.')\n if (flow.peer !== peer)\n throw new Error('That sign-in belongs to another connection.')\n return flow\n}\n\n/** Hand the flow its code (from the client's loopback) or pasted input, once, after checking its `state`. */\nfunction deliverCode(flow: Flow, p: { code?: unknown, state?: unknown, input?: unknown }, end: (flow: Flow, reason: string) => void): void {\n const code = typeof p.code === 'string' && p.code !== '' ? p.code : undefined\n const input = typeof p.input === 'string' && p.input.trim() !== '' ? p.input : undefined\n if (code === undefined && input === undefined)\n return\n if (flow.delivered)\n throw new Error('That sign-in already received its code.')\n const state = code !== undefined ? (typeof p.state === 'string' ? p.state : undefined) : stateIn(input!)\n // A code from the loopback must carry the flow's state; a pasted bare code (Anthropic's page) may omit it.\n if (flow.expectedState !== undefined && (state !== undefined || code !== undefined) && state !== flow.expectedState) {\n end(flow, 'OAuth state mismatch.')\n throw new Error('OAuth state mismatch: the sign-in was refused. Start it again.')\n }\n flow.delivered = true\n flow.deliver(code !== undefined ? { code, ...(state !== undefined ? { state } : {}) } : { input: input! })\n}\n\n/** The browser back at the server's callback: the code to the held flow its `state` names (or the refusal ends it). */\nfunction deliverCallback(flows: ReadonlyMap<string, Flow>, query: URLSearchParams, end: (flow: Flow, reason: string) => void): string | undefined {\n const state = query.get('state')\n const flow = state ? [...flows.values()].find(f => f.held && f.expectedState === state) : undefined\n if (!flow?.held || flow.delivered)\n return undefined\n const code = query.get('code')\n if (!code) {\n end(flow, query.get('error_description') ?? query.get('error') ?? 'The sign-in was refused.')\n return flow.held\n }\n flow.delivered = true\n flow.deliver({ code, state: state! })\n return flow.held\n}\n\nexport function createOAuthFlowHandlers({ host, env, auth, mcpStatus, isConnected, serverCallback = false, ttlMs = OAUTH_FLOW_TTL_MS }: {\n host: Pick<ChatHost, 'resolveFolder' | 'rebuildAllAgents'>\n env: DaemonEnvironment\n auth: ProviderAuth\n /** Follows each MCP sign-in, so the MCP servers page shows it. */\n mcpStatus: McpStatusTracker\n isConnected: (peer: HostPeer) => boolean\n /** This host serves {@link SERVER_OAUTH_CALLBACK_PATH} (a zidane-server): a browser client's MCP sign-in may redirect there. */\n serverCallback?: boolean\n ttlMs?: number\n}): {\n methods: Handlers<'auth.oauth.begin' | 'auth.oauth.complete' | 'auth.oauth.respond' | 'auth.oauth.cancel'>\n releasePeer: (peer: HostPeer) => void\n /** The browser came back to the server's callback: hands the code to the flow its `state` names. The MCP server it signs in to; `undefined`: no such flow waits. */\n deliverCallback: (query: URLSearchParams) => string | undefined\n} {\n const flows = new Map<string, Flow>()\n\n const end = (flow: Flow, reason: string): void => {\n clearTimeout(flow.timer)\n flows.delete(flow.id)\n if (!flow.abort.signal.aborted)\n flow.abort.abort(new Error(reason))\n }\n\n /** Register a flow whose login is already running; it ends at expiry, on cancel, or once settled and collected. */\n function register(peer: HostPeer, parts: { abort: AbortController, deliver: Flow['deliver'], result: Promise<HostOAuthComplete>, expectedState?: string, redirectUri?: string, held?: string, steps?: StepChannel, started?: Flow['started'] }): Flow {\n const id = randomBytes(24).toString('base64url')\n const flow: Flow = {\n id,\n peer,\n expiresAt: Date.now() + ttlMs,\n delivered: false,\n ...parts,\n timer: undefined as unknown as ReturnType<typeof setTimeout>,\n }\n flow.timer = setTimeout(end, ttlMs, flow, 'The sign-in expired.')\n flow.timer.unref?.()\n // Nobody may be waiting on it (expired, abandoned): never an unhandled rejection.\n flow.result.catch(() => undefined)\n flows.set(id, flow)\n return flow\n }\n\n const ownFlows = (peer: HostPeer): Flow[] => [...flows.values()].filter(flow => flow.peer === peer)\n /** MCP begins in flight per connection: counted against the cap before their flow registers. */\n const startingMcp = new Map<HostPeer, number>()\n\n async function beginProvider(peer: HostPeer, provider: unknown): Promise<HostOAuthBegin> {\n const { login, ...parts } = startProviderLogin(auth, provider)\n const flow = register(peer, parts)\n try {\n return await stateOf(flow, login)\n }\n catch (err) {\n end(flow, 'The sign-in did not start.')\n throw err\n }\n }\n\n /** The flow's URL, or the question it waits on first; its `state` and redirect recorded once the URL is known. */\n async function stateOf(flow: Flow, login: Promise<unknown>): Promise<HostOAuthBegin> {\n const steps = flow.steps!\n const next = await firstOf<{ step: HostOAuthStep } | { begin: Omit<HostOAuthBegin, 'flowId' | 'expiresAt'> }>(\n Promise.race([flow.started!.then(begin => ({ begin })), steps.next().then(step => ({ step }))]),\n login,\n flow.abort.signal,\n )\n if ('step' in next)\n return { flowId: flow.id, url: '', mode: 'step', step: next.step, expiresAt: flow.expiresAt }\n const begin = next.begin\n flow.begun = begin\n if (begin.mode !== 'device') {\n const authorize = new URL(begin.url)\n flow.expectedState = authorize.searchParams.get('state') ?? undefined\n if (begin.redirectUri)\n flow.redirectUri = begin.redirectUri\n }\n return { flowId: flow.id, ...begin, expiresAt: flow.expiresAt }\n }\n\n async function beginMcp(peer: HostPeer, p: { mcpServer: string, cwd?: string, kind?: string, redirectUri?: string }): Promise<HostOAuthBegin> {\n const asked = mcpRedirect(p.redirectUri, serverCallback)\n const dir = catalogFolder({ env, host }, p.cwd, p.kind)\n const config = await env.runtimeConfig(dir)\n const settings = env.readSettings()\n const { servers } = discoverProjectMcps({ cwd: dir, prefix: config.prefix, foreignAgents: settings.importForeignConfigs === true, ruler: settings.importRulerConfigs !== false })\n const entry: McpServerConfig | undefined = servers.find(server => server.config.name === p.mcpServer)?.config\n if (!entry)\n throw new Error(`No MCP server \"${p.mcpServer}\" in that folder's catalog.`)\n // A pre-registered client's redirect is the one registered with the\n // provider; the client rebinds its listener to it (`redirectUri` below),\n // or a browser client has the user paste it.\n const redirectUri = pinnedMcpRedirectUri(entry) ?? asked.uri\n const held = redirectUri === asked.uri && asked.held ? entry.name : undefined\n const abort = new AbortController()\n const state = randomBytes(24).toString('base64url')\n const callbackCode = deferred<{ code: string, state?: string }>()\n const started = deferred<{ url: string }>()\n const login = loginMcpServer(entry, {\n store: env.mcpCredentialStore?.() ?? createFileMcpCredentialStore(env.userDataDir()),\n signal: abort.signal,\n state,\n timeoutMs: ttlMs,\n // The client's loopback; the code comes back through `complete`.\n callback: { redirectUri, promise: callbackCode.promise, close: async () => undefined },\n onAuthorizationUrl: url => started.resolve({ url: url.toString() }),\n })\n login.catch(() => undefined)\n const first = await firstOf(started.promise, login, abort.signal).catch((err) => {\n abort.abort()\n throw err\n })\n const result = login.then(() => {\n void host.rebuildAllAgents({ rediscover: true }).catch(() => undefined)\n return { mcpServer: entry.name }\n })\n void mcpStatus.signingIn(entry.name, login, abort.signal)\n const flow = register(peer, {\n abort,\n result,\n expectedState: state,\n redirectUri,\n ...(held ? { held } : {}),\n deliver: (delivery) => {\n if ('input' in delivery) {\n const code = codeIn(delivery.input)\n const pastedState = stateIn(delivery.input)\n if (code)\n callbackCode.resolve({ code, ...(pastedState !== undefined ? { state: pastedState } : {}) })\n return\n }\n callbackCode.resolve(delivery)\n },\n })\n return { flowId: flow.id, url: first.url, ...(held ? { mode: 'browser' } : { mode: 'loopback', redirectUri }), expiresAt: flow.expiresAt }\n }\n\n return {\n methods: {\n 'auth.oauth.begin': async (p, peer) => {\n const target = [p.provider, p.mcpServer].filter(value => value !== undefined)\n if (target.length !== 1 || typeof target[0] !== 'string' || target[0] === '')\n throw new InvalidParamsError('auth.oauth.begin needs exactly one of \"provider\" or \"mcpServer\".')\n if (ownFlows(peer).length + (startingMcp.get(peer) ?? 0) >= MAX_FLOWS_PER_PEER)\n throw new Error(`This connection already has ${MAX_FLOWS_PER_PEER} sign-ins open: finish or cancel one first.`)\n let begun: HostOAuthBegin\n if (p.provider !== undefined) {\n begun = await beginProvider(peer, p.provider)\n }\n else {\n // An MCP flow registers only once its URL is known; hold its slot meanwhile.\n startingMcp.set(peer, (startingMcp.get(peer) ?? 0) + 1)\n try {\n begun = await beginMcp(peer, { mcpServer: p.mcpServer!, ...(p.cwd !== undefined ? { cwd: p.cwd } : {}), ...(p.kind !== undefined ? { kind: p.kind } : {}), ...(p.redirectUri !== undefined ? { redirectUri: p.redirectUri } : {}) })\n }\n finally {\n const left = (startingMcp.get(peer) ?? 1) - 1\n if (left > 0)\n startingMcp.set(peer, left)\n else\n startingMcp.delete(peer)\n }\n }\n // Dropped while it started: nobody will finish it.\n if (!isConnected(peer)) {\n const flow = flows.get(begun.flowId)\n if (flow)\n end(flow, 'The connection closed.')\n }\n return begun\n },\n\n 'auth.oauth.complete': async (p, peer) => {\n const flow = flowOf(flows, p.flowId, peer)\n deliverCode(flow, p, end)\n let asking = false\n try {\n // The login may ask something first: the client answers (`respond`), then calls again.\n const outcome = await (flow.steps\n ? Promise.race([flow.result, flow.steps.next().then(step => ({ step }))])\n : flow.result)\n asking = outcome.step !== undefined\n return outcome\n }\n catch (err) {\n throw new Error(flow.abort.signal.aborted && flow.abort.signal.reason instanceof Error ? flow.abort.signal.reason.message : err instanceof Error ? err.message : String(err))\n }\n finally {\n if (!asking)\n end(flow, 'The sign-in finished.')\n }\n },\n\n 'auth.oauth.respond': async (p, peer) => {\n const flow = flowOf(flows, p.flowId, peer)\n if (!flow.steps || typeof p.stepId !== 'string')\n throw new InvalidParamsError('auth.oauth.respond needs the flow\\'s \"stepId\".')\n if (p.value !== undefined && typeof p.value !== 'string')\n throw new InvalidParamsError('\"value\" must be a string.')\n const cancelled = p.value === undefined && flow.steps.pending()?.kind === 'select'\n flow.steps.answer(p.stepId, p.value)\n if (cancelled) {\n end(flow, 'The sign-in was cancelled.')\n throw new Error('The sign-in was cancelled (no choice made).')\n }\n // After the URL: where it stands (`complete` again waits for the rest).\n return flow.begun ? { flowId: flow.id, ...flow.begun, expiresAt: flow.expiresAt } : stateOf(flow, flow.result)\n },\n\n 'auth.oauth.cancel': (p, peer) => {\n const flow = typeof p.flowId === 'string' ? flows.get(p.flowId) : undefined\n if (!flow || flow.peer !== peer)\n return { cancelled: false }\n end(flow, 'The sign-in was cancelled.')\n return { cancelled: true }\n },\n },\n releasePeer(peer) {\n for (const flow of ownFlows(peer))\n end(flow, 'The connection closed.')\n },\n deliverCallback: query => deliverCallback(flows, query, end),\n }\n}\n","/**\n * What the setup wizard reads on the host's machine for a client: what it\n * finds there (`onboarding.detect`: credentials, other agents, local model\n * servers), the providers Connect lists with their custom fields and default\n * model (`onboarding.providers`), a Claude Code setup and its import\n * (`claudeImport.*`; the import copies commands the host will run, so it\n * goes through the install gate, `guardedInstall`) and a skill source's\n * skills (`skills.browse`).\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostSignal } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { RemoteInstallsOptions } from './catalog-install'\nimport type { Handlers } from './types'\nimport { detectAuth } from '../../../chat/auth'\nimport { countClaudeSessionFiles, hasClaudeCodeSetup, importFromClaudeCode, previewClaudeImport } from '../../../chat/claude-import'\nimport { connectorGithubToken, detectOnboardingEnvironment, onboardingProviders } from '../../../chat/host/onboarding/index'\nimport { browseSkillSource } from '../../../skills/browse'\nimport { guardedInstall } from './catalog-install'\nimport { catalogFolder } from './catalogs'\nimport { InvalidParamsError } from './params'\n\ntype OnboardingMethod = 'onboarding.detect' | 'onboarding.providers' | 'claudeImport.detect' | 'claudeImport.preview' | 'claudeImport.run' | 'skills.browse'\n\n/** Longest source spec browsed. */\nconst MAX_SOURCE_LENGTH = 500\n\nexport function createOnboardingHandlers({ host, env, broadcast, installs }: {\n host: Pick<ChatHost, 'resolveFolder' | 'rebuildAllAgents'>\n env: DaemonEnvironment\n broadcast: (signal: HostSignal) => void\n /** A zidane-server's `allowRemoteInstalls` and audit (`./catalog-install`). Absent: the import is refused. */\n installs?: RemoteInstallsOptions\n}): Handlers<OnboardingMethod> {\n const folderOf = (cwd: unknown): string => catalogFolder({ env, host }, cwd)\n /** The providers of `folder`, extension ones included. */\n const registryOf = async (folder: string) => (await env.runtimeConfig(folder)).providers\n const hasSessions = async (): Promise<boolean> => {\n try {\n return (await env.store.list({ limit: 1 })).length > 0\n }\n catch {\n // An unreadable store: the other signals decide.\n return false\n }\n }\n\n return {\n 'onboarding.detect': async (p) => {\n const cwd = folderOf(p.cwd)\n return detectOnboardingEnvironment({\n dataDir: env.userDataDir(),\n registry: await registryOf(cwd),\n state: env.config.stateStore.load(),\n sessions: await hasSessions(),\n // A browser's first visit says nothing about this machine.\n surfaceFirstRun: false,\n cwd,\n })\n },\n 'onboarding.providers': async (p) => {\n const registry = await registryOf(folderOf(p.cwd))\n return onboardingProviders(registry, detectAuth(env.userDataDir(), registry)).map((provider) => {\n const defaultModel = registry[provider.key]?.defaultModel\n return defaultModel ? { ...provider, defaultModel } : provider\n })\n },\n 'claudeImport.detect': (p) => {\n if (!hasClaudeCodeSetup())\n return { available: false, counts: { project: 0, all: 0 } }\n return { available: true, counts: countClaudeSessionFiles({ cwd: folderOf(p.cwd) }) }\n },\n 'claudeImport.preview': p => previewClaudeImport({ cwd: folderOf(p.cwd), prefix: env.config.prefix }),\n 'claudeImport.run': (p, peer) => guardedInstall(installs, peer, 'claudeImport.run', { sessions: p.sessions === true, mcps: p.mcps === true, skills: p.skills === true, commands: p.commands === true }, async () => {\n const commands = p.commands === true\n const summary = await importFromClaudeCode(env.store, {\n cwd: folderOf(p.cwd),\n prefix: env.config.prefix,\n sessions: p.sessions === true,\n mcps: p.mcps === true,\n skills: p.skills === true,\n commands,\n agents: typeof p.agents === 'boolean' ? p.agents : commands,\n allProjects: p.allProjects === true,\n })\n // MCP servers, skills and subagents are read when an agent is built.\n if (summary.mcps || summary.skills || summary.agents)\n void host.rebuildAllAgents({ rediscover: true }).catch(() => undefined)\n if (summary.mcps)\n broadcast({ kind: 'catalog:changed', catalog: 'mcps' })\n if (summary.skills)\n broadcast({ kind: 'catalog:changed', catalog: 'skills' })\n return summary\n }),\n // The GitHub login raises GitHub's limit from 60 to 5,000 calls an hour.\n 'skills.browse': async (p) => {\n if (typeof p.source !== 'string' || p.source.trim() === '' || p.source.length > MAX_SOURCE_LENGTH)\n throw new InvalidParamsError(`source must be a non-empty string of at most ${MAX_SOURCE_LENGTH} characters.`)\n const token = (await connectorGithubToken())?.token\n return browseSkillSource(p.source, token ? { token } : {})\n },\n }\n}\n","/** The main session driving worker sessions. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { Handlers } from './types'\n\ntype OrchestrationMethod\n = | 'orchestration.main' | 'orchestration.createWorker' | 'orchestration.list' | 'orchestration.read'\n | 'orchestration.send' | 'orchestration.steer' | 'orchestration.cancel' | 'orchestration.transcript'\n\nexport function createOrchestrationHandlers({ host }: { host: ChatHost }): Handlers<OrchestrationMethod> {\n return {\n 'orchestration.main': () => host.orchestration.ensureMain(),\n 'orchestration.createWorker': ({ mainId, ...params }) => host.orchestration.createWorker(mainId, params),\n 'orchestration.list': p => host.orchestration.list(p.mainId, p.limit),\n 'orchestration.read': async p =>\n (await host.orchestration.canOrchestrate(p.mainId, p.sessionId)) ? host.orchestration.read(p.sessionId) : null,\n 'orchestration.send': p => host.orchestration.send(p.mainId, p.sessionId, p.prompt, p.wake),\n 'orchestration.steer': p => host.orchestration.steer(p.mainId, p.sessionId, p.message),\n 'orchestration.cancel': p => host.orchestration.cancel(p.mainId, p.sessionId),\n 'orchestration.transcript': p => host.orchestration.transcript(p.mainId, p.sessionId, p.limit),\n }\n}\n","import type { ChatHost } from '../../../chat/host/engine'\n/**\n * Extension side panels and command palette items for a client's app\n * (`panels.*`, `palette.*`): run here (`../../../extensions/panel-host`),\n * answered as data. A panel runs in a read-only scope of its folder's\n * project and the session it shows beside (that session's artifacts, the\n * project's). Live updates go to the connections watching: `panel:changed`,\n * `palette:changed`, one subscription per panel or folder however many\n * watch it; a dropped connection releases its own.\n */\nimport type { PanelHostDeps } from '../../../extensions/panel-host'\nimport type { SessionStore } from '../../../session/index'\nimport type { DaemonEnvironment } from '../environment'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { isPaletteContext } from '../../../chat/palette'\nimport { projectRootOf } from '../../../chat/project-root'\nimport { listExtensionPaletteItems, loadExtensionPanel, panelSummaries, runExtensionPaletteItem, runExtensionPanelAction, subscribeExtensionPalette, subscribeExtensionPanel } from '../../../extensions/panel-host'\nimport { createSharedWatches } from '../../../extensions/shared-watches'\nimport { catalogFolder } from './catalogs'\nimport { InvalidParamsError, requiredString } from './params'\n\ntype PanelMethod\n = | 'panels.list' | 'panels.load' | 'panels.action' | 'panels.watch' | 'panels.unwatch'\n | 'palette.list' | 'palette.run' | 'palette.watch' | 'palette.unwatch'\n\nexport function createPanelHandlers({ host, env, store, onClose }: {\n host: Pick<ChatHost, 'resolveFolder'>\n env: DaemonEnvironment\n store: Pick<SessionStore, 'listArtifacts'>\n onClose: (release: (peer: HostPeer) => void) => void\n}): Handlers<PanelMethod> {\n const folderOf = (cwd: unknown): string => catalogFolder({ env, host }, requiredString(cwd, 'cwd'))\n const registryOf = async (folder: string) => (await env.runtimeConfig(folder)).extensions\n const panelOf = async (folder: string, panelId: unknown) => (await registryOf(folder)).panels.find(p => p.id === panelId)\n const deps: PanelHostDeps = {\n ...(env.hostRuntime ? { hostRuntime: env.hostRuntime } : {}),\n listArtifacts: async query => (await store.listArtifacts?.(query)) ?? [],\n artifactsEnabled: () => env.readSettings().artifacts !== false,\n projectRootOf,\n }\n const paletteContext = (ctx: unknown) => {\n if (!isPaletteContext(ctx))\n throw new InvalidParamsError('ctx must be a palette context.')\n return ctx\n }\n\n // Keyed by the folder as each client names it: the signals carry that name back.\n const panelWatches = createSharedWatches<HostPeer>()\n const paletteWatches = createSharedWatches<HostPeer>()\n onClose((peer) => {\n panelWatches.release(peer)\n paletteWatches.release(peer)\n })\n const panelKey = (cwd: string, panelId: string): string => `${cwd}\\u0000${panelId}`\n\n return {\n 'panels.list': async p => panelSummaries((await registryOf(folderOf(p.cwd))).panels),\n 'panels.load': async (p) => {\n const folder = folderOf(p.cwd)\n return loadExtensionPanel(await panelOf(folder, p.panelId), p.ctx, folder, deps)\n },\n 'panels.action': async (p) => {\n const folder = folderOf(p.cwd)\n return runExtensionPanelAction(await panelOf(folder, p.panelId), requiredString(p.actionId, 'actionId'), p.payload, p.ctx, folder, deps)\n },\n 'panels.watch': (p, peer) => {\n const folder = folderOf(p.cwd)\n const panelId = requiredString(p.panelId, 'panelId')\n const key = panelKey(p.cwd, panelId)\n return panelWatches.watch(key, peer, async () => subscribeExtensionPanel(await panelOf(folder, panelId), () => {\n for (const watcher of panelWatches.owners(key))\n watcher.send({ kind: 'panel:changed', cwd: p.cwd, panelId })\n }))\n },\n 'panels.unwatch': (p, peer) => {\n panelWatches.unwatch(panelKey(requiredString(p.cwd, 'cwd'), requiredString(p.panelId, 'panelId')), peer)\n },\n\n 'palette.list': async (p) => {\n const folder = folderOf(p.cwd)\n return listExtensionPaletteItems((await registryOf(folder)).palette, folder, paletteContext(p.ctx))\n },\n 'palette.run': async (p) => {\n const folder = folderOf(p.cwd)\n return runExtensionPaletteItem((await registryOf(folder)).palette, requiredString(p.source, 'source'), requiredString(p.itemId, 'itemId'), folder, paletteContext(p.ctx))\n },\n 'palette.watch': (p, peer) => {\n const folder = folderOf(p.cwd)\n return paletteWatches.watch(p.cwd, peer, async () => subscribeExtensionPalette((await registryOf(folder)).palette, () => {\n for (const watcher of paletteWatches.owners(p.cwd))\n watcher.send({ kind: 'palette:changed', cwd: p.cwd })\n }))\n },\n 'palette.unwatch': (p, peer) => {\n paletteWatches.unwatch(requiredString(p.cwd, 'cwd'), peer)\n },\n }\n}\n","/**\n * The host's own performance, for a client's Settings › Performance on it:\n * the samples held (`perf.history`), each new one to the connections\n * watching (`perf.watch`, `perf:sample`), and the OS threads of a process\n * it lists (`perf.threads`). The monitor (`src/perf/host.ts`) is made on\n * the first call and samples only while a connection watches; a dropped\n * connection releases its watches, and the host's shutdown stops them all.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostPerf } from '../../../perf/host'\nimport type { SessionStore } from '../../../session'\nimport type { HostKind } from '../../protocol'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { createSharedWatches } from '../../../extensions/shared-watches'\nimport { createHostPerf } from '../../../perf/host'\nimport { InvalidParamsError } from './params'\n\n/** The host process's row in its samples. */\nconst LABEL: Record<HostKind, string> = { 'server': 'Server', 'daemon': 'Daemon', 'in-process': 'Host' }\n\n/**\n * This host's monitor, made on the first call: its process labelled by its\n * kind, its sessions' MCP processes, its sessions' titles from its store.\n *\n * @param host - The host: its kind, engine and store.\n * @param host.kind - What it reports itself as (`ipc.hello`'s `hostKind`).\n * @param host.host - Its engine (the MCP server processes).\n * @param host.store - Its session store (the titles).\n */\nexport function lazyHostPerf({ kind, host, store }: { kind: HostKind, host: Pick<ChatHost, 'mcpServers'>, store: Pick<SessionStore, 'getMeta'> }): () => HostPerf {\n let monitor: HostPerf | null = null\n return () => monitor ??= createHostPerf({\n label: LABEL[kind],\n mcpInstances: () => host.mcpServers.instances(),\n sessionTitle: async (sessionId) => {\n const title = (await store.getMeta?.(sessionId))?.metadata.title\n return typeof title === 'string' && title.trim() ? title : undefined\n },\n })\n}\n\nexport function createPerfHandlers({ perf, onPeerClose, onShutdown }: {\n /** The host's monitor (made once, on first use). */\n perf: () => HostPerf\n /** Registers what to release when a connection drops (its watches). */\n onPeerClose: (release: (peer: HostPeer) => void) => void\n /** Registers what to stop when the host shuts down. */\n onShutdown: (stop: () => void) => void\n}): Handlers<'perf.watch' | 'perf.unwatch' | 'perf.history' | 'perf.threads'> {\n const watchers = createSharedWatches<HostPeer>()\n onPeerClose(peer => watchers.release(peer))\n onShutdown(() => watchers.reset())\n return {\n 'perf.watch': (_p, peer) => watchers.watch('perf', peer, async () => perf().watch((sample) => {\n for (const watcher of watchers.owners('perf'))\n watcher.send({ kind: 'perf:sample', sample })\n })),\n 'perf.unwatch': (_p, peer) => {\n watchers.unwatch('perf', peer)\n },\n 'perf.history': () => ({ samples: perf().history() }),\n 'perf.threads': async (p) => {\n if (!Number.isInteger(p?.pid) || p.pid <= 0)\n throw new InvalidParamsError('perf.threads: \"pid\" must be a process id.')\n return { threads: await perf().threads(p.pid) }\n },\n }\n}\n","/**\n * The integrations the host's clients registered (`integrations.*`): each one\n * belongs to the peer that registered it and goes away when that peer\n * disconnects. State only; the methods and the signal live in\n * `./handlers/integrations`, as presence's do next to `./peers`.\n */\nimport type { IntegrationInfo, IntegrationState } from '../../chat/integrations'\nimport type { HostPeer } from './peers'\n\n/** Integrations one connection may hold at once. */\nexport const MAX_INTEGRATIONS_PER_PEER = 32\n\n/** What a client registers: an {@link IntegrationInfo} without its `since`. */\nexport interface IntegrationEntry {\n name: string\n kind: string\n state: IntegrationState\n detail?: string\n}\n\nexport interface IntegrationRegistry {\n /**\n * Add `peer`'s integration, or replace the one it registered under that name.\n * @returns Whether the list changed.\n * @throws {Error} When another peer registered the name, or `peer` already holds {@link MAX_INTEGRATIONS_PER_PEER} others.\n */\n register: (peer: HostPeer, entry: IntegrationEntry) => boolean\n /**\n * Set the state and detail of `peer`'s integration (an absent detail clears it).\n * @returns Whether the list changed.\n * @throws {Error} When `peer` registered no integration under that name.\n */\n update: (peer: HostPeer, entry: Omit<IntegrationEntry, 'kind'>) => boolean\n /** Every integration, in registration order. */\n list: () => IntegrationInfo[]\n /**\n * Drop every integration `peer` registered.\n * @returns Whether the list changed.\n */\n release: (peer: HostPeer) => boolean\n}\n\n/**\n * @param now - The clock `since` reads (epoch ms).\n */\nexport function createIntegrationRegistry(now: () => number = Date.now): IntegrationRegistry {\n const entries = new Map<string, { owner: HostPeer, info: IntegrationInfo }>()\n\n /** Store `entry` for `owner`; `since` moves only when the state does. */\n function put(owner: HostPeer, entry: IntegrationEntry): boolean {\n const previous = entries.get(entry.name)?.info\n const info: IntegrationInfo = {\n name: entry.name,\n kind: entry.kind,\n state: entry.state,\n ...(entry.detail !== undefined ? { detail: entry.detail } : {}),\n since: previous && previous.state === entry.state ? previous.since : now(),\n }\n entries.set(entry.name, { owner, info })\n return !previous || previous.kind !== info.kind || previous.state !== info.state || previous.detail !== info.detail\n }\n\n return {\n register(peer, entry) {\n const existing = entries.get(entry.name)\n if (existing && existing.owner !== peer)\n throw new Error(`Integration \"${entry.name}\" is registered by another connection.`)\n if (!existing && [...entries.values()].filter(e => e.owner === peer).length >= MAX_INTEGRATIONS_PER_PEER)\n throw new Error(`This connection already registered ${MAX_INTEGRATIONS_PER_PEER} integrations, the most one may.`)\n return put(peer, entry)\n },\n update(peer, entry) {\n const existing = entries.get(entry.name)\n if (!existing || existing.owner !== peer)\n throw new Error(`Integration \"${entry.name}\" is not registered by this connection.`)\n return put(peer, { ...entry, kind: existing.info.kind })\n },\n list: () => [...entries.values()].map(entry => ({ ...entry.info })),\n release(peer) {\n let changed = false\n for (const [name, entry] of entries) {\n if (entry.owner === peer) {\n entries.delete(name)\n changed = true\n }\n }\n return changed\n },\n }\n}\n","/** Integrations the host's clients run (a channel), as they report them, and the signal that follows each change. */\nimport type { IntegrationState } from '../../../chat/integrations'\nimport type { HostSignal } from '../../protocol'\nimport type { IntegrationRegistry } from '../integrations'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { CHANNEL_KIND_PREFIX, hasControlCharacters, INTEGRATION_STATES, isIntegrationState } from '../../../chat/integrations'\nimport { scopeAllows } from '../../scopes'\nimport { createIntegrationRegistry } from '../integrations'\nimport { InvalidParamsError } from './params'\nimport { PolicyScopeError } from './session-policy'\n\n/** Longest `name` and `kind`. */\nconst MAX_NAME_LENGTH = 200\n/** Longest `detail`. */\nconst MAX_DETAIL_LENGTH = 2000\n\nfunction boundedString(value: unknown, name: string, max: number): string {\n if (typeof value !== 'string' || value.length === 0 || value.length > max)\n throw new InvalidParamsError(`${name} must be a non-empty string of at most ${max} characters.`)\n return printable(value, name)\n}\n\n/** `value`, refused when it holds a control character (`channels status` and windows print it). */\nfunction printable(value: string, name: string): string {\n if (hasControlCharacters(value))\n throw new InvalidParamsError(`${name} must not contain control characters.`)\n return value\n}\n\n/** `kind`, refused when it claims to be a channel and the connection's token can't approve (a local connection can). */\nfunction kindFor(peer: HostPeer, kind: string): string {\n if (kind.startsWith(CHANNEL_KIND_PREFIX) && peer.grant && !scopeAllows(peer.grant, 'approve'))\n throw new PolicyScopeError('integrations.register', `with kind \"${CHANNEL_KIND_PREFIX}…\"`, peer.grant)\n return kind\n}\n\nfunction stateOf(value: unknown): IntegrationState {\n if (!isIntegrationState(value))\n throw new InvalidParamsError(`state must be one of ${INTEGRATION_STATES.join(', ')}.`)\n return value\n}\n\nfunction detailOf(value: unknown): { detail?: string } {\n if (value === undefined)\n return {}\n if (typeof value !== 'string' || value.length > MAX_DETAIL_LENGTH)\n throw new InvalidParamsError(`detail must be a string of at most ${MAX_DETAIL_LENGTH} characters.`)\n return { detail: printable(value, 'detail') }\n}\n\nexport function createIntegrationHandlers({ broadcast, onClose, registry = createIntegrationRegistry() }: {\n broadcast: (signal: HostSignal) => void\n /** Registers the peer-close cleanup (`PeerRegistry.onClose`). */\n onClose: (cleanup: (peer: HostPeer) => void) => void\n registry?: IntegrationRegistry\n}): Handlers<'integrations.register' | 'integrations.update' | 'integrations.list'> {\n const changed = (didChange: boolean): void => {\n if (didChange)\n broadcast({ kind: 'integrations:changed', integrations: registry.list() })\n }\n onClose(peer => changed(registry.release(peer)))\n\n return {\n 'integrations.register': (p, peer) => {\n changed(registry.register(peer, {\n name: boundedString(p?.name, 'name', MAX_NAME_LENGTH),\n kind: kindFor(peer, boundedString(p?.kind, 'kind', MAX_NAME_LENGTH)),\n state: stateOf(p?.state),\n ...detailOf(p?.detail),\n }))\n },\n 'integrations.update': (p, peer) => {\n changed(registry.update(peer, {\n name: boundedString(p?.name, 'name', MAX_NAME_LENGTH),\n state: stateOf(p?.state),\n ...detailOf(p?.detail),\n }))\n },\n 'integrations.list': () => registry.list(),\n }\n}\n","/**\n * Who is connected: which sessions have windows attached, which one this\n * window watches, and the integrations (channels and other non-window\n * clients) that registered themselves.\n */\nimport type { DaemonEnvironment } from '../environment'\nimport type { PeerRegistry } from '../peers'\nimport type { Handlers } from './types'\nimport { createIntegrationHandlers } from './integrations'\n\nexport function createPresenceHandlers({ env, peers }: {\n env: DaemonEnvironment\n peers: Pick<PeerRegistry, 'computePresence' | 'broadcastPresence' | 'broadcast' | 'onClose'>\n}): Handlers<'presence.list' | 'presence.watch' | 'integrations.register' | 'integrations.update' | 'integrations.list'> {\n return {\n ...createIntegrationHandlers({ broadcast: peers.broadcast, onClose: peers.onClose }),\n 'presence.list': () => peers.computePresence(),\n 'presence.watch': (p, peer) => {\n peer.watching = p.sessionId\n peers.broadcastPresence()\n // Warm the per-cwd runtime config off the keystroke path: the first\n // suggest.resolve on a cold cwd would otherwise pay full extension\n // discovery inside the typist's wait (the 150ms provider deadline\n // starts only AFTER the registry exists). Fire-and-forget; the\n // 16-entry LRU keeps recently watched cwds hot.\n void env.store.load(p.sessionId).then((data) => {\n if (!data)\n return\n const meta = data.metadata ?? {}\n const cwd = typeof meta.cwd === 'string' ? meta.cwd : (data.projectRoot ?? '')\n return env.runtimeConfig(cwd)\n }).catch(() => undefined)\n },\n }\n}\n","/** The host-owned type-ahead queue every window shares. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostPeer } from '../peers'\nimport type { SendDedup } from '../send-requests'\nimport type { Handlers } from './types'\nimport { deduped } from '../send-requests'\nimport { promptFields } from './chat'\nimport { boundAttachments } from './drafts'\nimport { InvalidParamsError } from './params'\n\nexport function createQueueHandlers({ host, clearDraft, dedup }: {\n host: ChatHost\n clearDraft: (sessionId: string, origin: HostPeer | null) => void\n /** Answers a retried `requestId` with its first outcome (`../send-requests`). Absent: `requestId` is ignored. */\n dedup?: SendDedup\n}): Handlers<'queue.list' | 'queue.add' | 'queue.remove' | 'queue.update' | 'queue.attachments' | 'queue.pushNow'> {\n return {\n 'queue.list': p => host.queueList(p.sessionId),\n 'queue.add': async (p, peer) => {\n // Same cheap shape guards as `drafts.set` — a malformed peer payload\n // must not propagate a non-string into every window's queue box.\n const text = typeof p.text === 'string' ? p.text.slice(0, 64 * 1024) : ''\n const activatedSkills = Array.isArray(p.activatedSkills)\n ? p.activatedSkills.filter((name): name is string => typeof name === 'string')\n : undefined\n const attachments = Array.isArray(p.attachments)\n ? boundAttachments(p.attachments)\n : undefined\n const asCommand = typeof p.asCommand === 'string' ? p.asCommand.slice(0, 128) : undefined\n const fields = promptFields(p)\n const result = await deduped(dedup, 'queue.add', p, () => host.queueAdd(p.sessionId, text, activatedSkills, attachments, asCommand, fields))\n // Queuing/sending consumed the shared draft, same as a direct send\n // (not for a prompt sent from outside the composer).\n if (p.keepDraft !== true)\n clearDraft(p.sessionId, peer)\n return result\n },\n 'queue.remove': p => host.queueRemove(p.sessionId, p.id),\n 'queue.update': p => host.queueUpdate(\n p.sessionId,\n p.id,\n typeof p.text === 'string' ? p.text.slice(0, 64 * 1024) : '',\n updatedAttachments(p.attachments),\n ),\n 'queue.attachments': p => host.queueAttachments(p.sessionId, p.id),\n 'queue.pushNow': p => host.queuePushNow(p.sessionId, p.id),\n }\n}\n\n/**\n * The list `queue.update` stores in place of an entry's attachments. An entry\n * that is malformed or over the budget is refused, not dropped: the list\n * REPLACES what is stored, so a quietly shorter list would delete the rest.\n */\nfunction updatedAttachments(list: unknown): ReturnType<typeof boundAttachments> | undefined {\n if (!Array.isArray(list))\n return undefined\n const bounded = boundAttachments(list)\n if (bounded.length !== list.length)\n throw new InvalidParamsError('attachments: an entry is malformed, or the list is over 24 MiB.')\n return bounded\n}\n","/** Reattach without a reload: replay a session's numbered signals from the host's log (`../signal-log`). */\nimport type { SignalLog } from '../signal-log'\nimport type { Handlers } from './types'\n\nexport function createResumeHandlers({ log }: { log: Pick<SignalLog, 'epoch' | 'replay'> }): Handlers<'sessions.resume'> {\n return {\n 'sessions.resume': (p) => {\n if (p.epoch !== log.epoch)\n return { ok: false, reason: 'epoch' }\n const signals = typeof p.afterSeq === 'number' ? log.replay(p.sessionId, p.afterSeq) : null\n return signals ? { ok: true, signals } : { ok: false, reason: 'gap' }\n },\n }\n}\n","/**\n * A zidane-server's log, for a client's Settings › Logs: the records its\n * bounded buffer holds (`logs.list`) and each new one to the connections\n * following it (`logs.watch`, `logs:record`). Another host has no buffer\n * and refuses both.\n */\nimport type { LogRecord, RingBufferSink } from '../../../logger'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { createSharedWatches } from '../../../extensions/shared-watches'\n\nconst NO_LOGS = 'This host keeps no log for clients (a zidane-server does).'\n\n/** A value as it can cross the wire: an error by its message, anything JSON can't hold by its text. */\nfunction wireValue(value: unknown): unknown {\n if (value instanceof Error)\n return value.message\n try {\n return JSON.parse(JSON.stringify(value) ?? 'null') as unknown\n }\n catch {\n return String(value)\n }\n}\n\n/** A record with its attributes made wire-safe (an extension may log anything). */\nfunction wireRecord(record: LogRecord): LogRecord {\n return { ...record, attrs: Object.fromEntries(Object.entries(record.attrs).map(([key, value]) => [key, wireValue(value)])) }\n}\n\nexport function createLogHandlers({ logs, onClose }: {\n logs?: RingBufferSink\n onClose: (release: (peer: HostPeer) => void) => void\n}): Handlers<'logs.list' | 'logs.watch' | 'logs.unwatch'> {\n const buffer = (): RingBufferSink => {\n if (!logs)\n throw new Error(NO_LOGS)\n return logs\n }\n const followers = createSharedWatches<HostPeer>()\n onClose(peer => followers.release(peer))\n return {\n 'logs.list': () => ({ records: buffer().getRecords().map(wireRecord) }),\n 'logs.watch': (_p, peer) => {\n const sink = buffer()\n return followers.watch('log', peer, async () => sink.subscribe(() => {\n const last = sink.getRecords().at(-1)\n if (!last)\n return\n const record = wireRecord(last)\n for (const follower of followers.owners('log'))\n follower.send({ kind: 'logs:record', record })\n }))\n },\n 'logs.unwatch': (_p, peer) => {\n followers.unwatch('log', peer)\n },\n }\n}\n","/**\n * What only a zidane-server does: manage its tokens (`tokens.*`, and\n * `tokens:changed` to every window after a change), update itself\n * (`server.update.*`) and show its log (`logs.*`, `./logs`). Another host\n * answers them with a refusal.\n */\nimport type { RingBufferSink } from '../../../logger'\nimport type { HostSignal, ServerTokenInfo, ServerTokenScope, ServerUpdateStatus } from '../../protocol'\nimport type { ClientScope } from '../../scopes'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { isValidMachineName } from '../../../chat/machine-protocol'\nimport { isClientScope } from '../../scopes'\nimport { createLogHandlers } from './logs'\nimport { InvalidParamsError } from './params'\n\nexport interface ServerUpdateControl {\n status: () => ServerUpdateStatus\n configure: (enabled: boolean) => ServerUpdateStatus\n check: () => Promise<ServerUpdateStatus>\n installNow: () => Promise<ServerUpdateStatus>\n}\n\n/** A zidane-server's token store, as its clients reach it (`src/server/server.ts` audits each call). */\nexport interface ServerTokensControl {\n createMachineToken: (name: string, by: string | undefined) => { id: string, name: string, token: string }\n list: () => ServerTokenInfo[]\n create: (name: string, scope: ServerTokenScope, by: string | undefined) => ServerTokenInfo & { token: string }\n /** `null`: no live token has that id. */\n revoke: (id: string, by: string | undefined) => ServerTokenInfo[] | null\n /** A one-time pairing code (`src/server/pairing.ts`); throws past the live-code cap. */\n pair: (scope: ClientScope, ttlMs: number | undefined, name: string | undefined, by: string | undefined) => { code: string, expiresAt: number }\n /** A one-time machine join code (`src/ipc/machine/join.ts`); throws past the live-code cap or the server's longest lifetime. */\n machineInvite: (ttlMs: number | undefined, name: string | undefined, by: string | undefined) => { code: string, expiresAt: number }\n /** Calls `listener` after the tokens changed, whoever changed them (a client, a pairing, the CLI). Returns the unsubscribe. */\n onChange: (listener: () => void) => () => void\n}\n\n/** Bounds of `tokens.pair`'s `ttlMs` (`src/server/pairing.ts`). */\nconst PAIR_TTL_MIN_MS = 30_000\nconst PAIR_TTL_MAX_MS = 60 * 60_000\n\nconst NO_UPDATER = 'This host does not update itself (a zidane-server does).'\nconst NO_TOKENS = 'This host has no tokens (only a zidane-server does).'\n\nfunction validName(method: string, name: unknown): string {\n if (typeof name !== 'string' || name.trim() === '')\n throw new InvalidParamsError(`${method}: \"name\" must be a non-empty string.`)\n return name.trim().slice(0, 100)\n}\n\nexport function createServerHandlers({ tokens, update, logs, broadcast, onClose, onPeerClose }: {\n tokens?: ServerTokensControl\n update?: () => ServerUpdateControl | null\n logs?: RingBufferSink\n broadcast: (signal: HostSignal) => void\n /** Registers what to stop when the host shuts down. */\n onClose: (stop: () => void) => void\n /** Registers what to release when a connection drops (its log follow). */\n onPeerClose: (release: (peer: HostPeer) => void) => void\n}): Handlers<'tokens.createMachineToken' | 'tokens.list' | 'tokens.create' | 'tokens.revoke' | 'tokens.revokeSelf' | 'tokens.pair' | 'tokens.machineInvite' | 'server.update.status' | 'server.update.configure' | 'server.update.check' | 'server.update.install' | 'logs.list' | 'logs.watch' | 'logs.unwatch'> {\n const updater = (): ServerUpdateControl => {\n const control = update?.()\n if (!control)\n throw new Error(NO_UPDATER)\n return control\n }\n const store = (): ServerTokensControl => {\n if (!tokens)\n throw new Error(NO_TOKENS)\n return tokens\n }\n // A token created, revoked or paired, here or by the CLI: every window's token list re-reads.\n if (tokens)\n onClose(tokens.onChange(() => broadcast({ kind: 'tokens:changed' })))\n return {\n // Counted against, and audited with, the token that asks.\n 'tokens.createMachineToken': (p, peer) => store().createMachineToken(validName('tokens.createMachineToken', p.name), peer.principal),\n 'tokens.list': () => store().list(),\n 'tokens.create': (p, peer) => {\n const name = validName('tokens.create', p.name)\n if (p.scope !== 'machine' && !isClientScope(p.scope))\n throw new InvalidParamsError('tokens.create: \"scope\" must be \"chat\", \"approve\", \"admin\" or \"machine\".')\n return store().create(name, p.scope, peer.principal)\n },\n 'tokens.revoke': (p, peer) => {\n if (typeof p.id !== 'string' || p.id === '')\n throw new InvalidParamsError('tokens.revoke: \"id\" must be a token id.')\n const revoked = store().revoke(p.id, peer.principal)\n if (!revoked)\n throw new Error(`No live token has the id \"${p.id}\".`)\n return { revoked }\n },\n 'tokens.revokeSelf': (_p, peer) => {\n if (!peer.principal)\n throw new Error('This connection has no token to revoke.')\n const revoked = store().revoke(peer.principal, peer.principal)\n if (!revoked)\n throw new Error('This connection\\'s token is no longer live.')\n return { revoked }\n },\n 'tokens.pair': (p, peer) => {\n if (!isClientScope(p.scope))\n throw new InvalidParamsError('tokens.pair: \"scope\" must be \"chat\", \"approve\" or \"admin\".')\n if (p.ttlMs !== undefined && (!Number.isInteger(p.ttlMs) || p.ttlMs < PAIR_TTL_MIN_MS || p.ttlMs > PAIR_TTL_MAX_MS))\n throw new InvalidParamsError(`tokens.pair: \"ttlMs\" must be an integer from ${PAIR_TTL_MIN_MS} to ${PAIR_TTL_MAX_MS}.`)\n if (p.name !== undefined && typeof p.name !== 'string')\n throw new InvalidParamsError('tokens.pair: \"name\" must be a string.')\n return store().pair(p.scope, p.ttlMs, p.name?.trim() || undefined, peer.principal)\n },\n 'tokens.machineInvite': (p, peer) => {\n if (p.ttlMs !== undefined && (!Number.isInteger(p.ttlMs) || p.ttlMs < PAIR_TTL_MIN_MS || p.ttlMs > PAIR_TTL_MAX_MS))\n throw new InvalidParamsError(`tokens.machineInvite: \"ttlMs\" must be an integer from ${PAIR_TTL_MIN_MS} to ${PAIR_TTL_MAX_MS}.`)\n const name = typeof p.name === 'string' ? p.name.trim() : p.name\n if (name !== undefined && (typeof name !== 'string' || (name !== '' && !isValidMachineName(name))))\n throw new InvalidParamsError('tokens.machineInvite: \"name\" must be a machine name: up to 64 letters, digits, dots, dashes or underscores.')\n return store().machineInvite(p.ttlMs, name || undefined, peer.principal)\n },\n 'server.update.status': () => updater().status(),\n 'server.update.configure': (p) => {\n if (typeof p?.enabled !== 'boolean')\n throw new InvalidParamsError('server.update.configure: \"enabled\" must be true or false.')\n return updater().configure(p.enabled)\n },\n 'server.update.check': () => updater().check(),\n 'server.update.install': () => updater().installNow(),\n ...createLogHandlers({ ...(logs ? { logs } : {}), onClose: onPeerClose }),\n }\n}\n","/**\n * Session data a client reads (and the extension state it writes) instead of\n * its own store: the list rows, one row, the whole document (or it a page of\n * turns at a time), one tool result's text, how its title came about. A window on\n * another machine (zidane-server) has no other way to see the host's\n * sessions.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { Session, SessionData, SessionStore } from '../../../session/index'\nimport type { SessionTurn } from '../../../types'\nimport type { TranscriptReplayCache } from './transcript-cache'\nimport type { Handlers } from './types'\nimport { describeTitleStatus } from '../../../chat/auto-title'\nimport { exportFilename, renderSession } from '../../../chat/session-export'\nimport { getSessionHeader, getSessionMeta, headerFromData, lastContextSizeFromTurns, listSessionMeta, runProgress, sumRunCosts, toolResultText } from '../../../chat/store'\nimport { deleteExtensionSessionState, loadSession, setExtensionSessionState } from '../../../session/index'\nimport { SESSION_TURNS_MAX_PAGE, SESSION_TURNS_PAGE } from '../../protocol'\nimport { InvalidParamsError, nonNegativeInt, sessionIdOf } from './params'\n\ntype SessionReadMethod = 'sessions.listMeta' | 'sessions.getMeta' | 'sessions.get' | 'sessions.getTurns' | 'sessions.getToolResult' | 'sessions.getHeader' | 'sessions.titleStatus' | 'sessions.setExtensionState' | 'sessions.export'\n\nfunction pageBound(value: unknown, name: string, fallback: number, max: number): number {\n return Math.min(nonNegativeInt(value, name) ?? fallback, max)\n}\n\n/**\n * The live session's document without copying it (`toJSON()` deep-clones\n * every turn). Read-only: each transport serializes the reply before the\n * session can change under it.\n */\nfunction liveView(live: Session): SessionData {\n return {\n id: live.id,\n ...(live.agentId !== undefined ? { agentId: live.agentId } : {}),\n ...(live.projectRoot !== undefined ? { projectRoot: live.projectRoot } : {}),\n turns: live.turns,\n runs: live.runs,\n status: live.status,\n metadata: live.metadata,\n createdAt: live.createdAt,\n updatedAt: live.updatedAt,\n }\n}\n\nexport function createSessionReadHandlers({ host, store, snapshots }: { host: ChatHost, store: SessionStore, snapshots: Pick<TranscriptReplayCache, 'document'> }): Handlers<SessionReadMethod> {\n /** The document as the host holds it: the live copy (ahead of the store mid-run, and holding the todos), else the stored one. */\n const documentOf = async (sessionId: string): Promise<SessionData | null> => {\n const live = host.getLiveSession(sessionId)\n if (live)\n return live.toJSON()\n // A reader: a load-time pairing heal stays in memory, the host's own\n // agent persists the document.\n const loaded = await loadSession(store, sessionId, { persistHeal: false })\n return loaded ? loaded.toJSON() : null\n }\n return {\n 'sessions.listMeta': (p) => {\n const projectRoot = p?.projectRoot\n if (projectRoot !== undefined && projectRoot !== null && typeof projectRoot !== 'string')\n throw new InvalidParamsError('projectRoot must be a string or null.')\n return listSessionMeta(store, projectRoot !== undefined ? { projectRoot } : undefined)\n },\n 'sessions.getMeta': p => getSessionMeta(store, sessionIdOf(p)),\n 'sessions.export': async (p) => {\n const sessionId = sessionIdOf(p)\n if (p.format !== 'markdown' && p.format !== 'json')\n throw new InvalidParamsError('format must be \"markdown\" or \"json\".')\n const data = await documentOf(sessionId)\n if (!data)\n throw new Error(`Session \"${sessionId}\" not found.`)\n return { filename: exportFilename(sessionId, p.format), content: renderSession(data, p.format) }\n },\n 'sessions.get': async (p) => {\n const sessionId = sessionIdOf(p)\n if (p.turns !== false)\n return documentOf(sessionId)\n // `turns: false`: the rest of the document, its turns read a page at a time\n // (`sessions.getTurns`), from the same snapshot, named by its version.\n const snapshot = await snapshots.document(store, sessionId, host.getLiveSession(sessionId))\n return snapshot && { ...snapshot.data, turns: [], version: snapshot.version }\n },\n 'sessions.getTurns': async (p) => {\n // One snapshot per content version serves every page (not a load, heal and copy per page).\n const sessionId = sessionIdOf(p)\n const snapshot = await snapshots.document(store, sessionId, host.getLiveSession(sessionId))\n if (!snapshot)\n return null\n const from = pageBound(p.from, 'from', 0, Number.MAX_SAFE_INTEGER)\n const limit = Math.max(1, pageBound(p.limit, 'limit', SESSION_TURNS_PAGE, SESSION_TURNS_MAX_PAGE))\n const { turns } = snapshot.data\n return { turns: turns.slice(from, from + limit), total: turns.length, version: snapshot.version }\n },\n 'sessions.getToolResult': async (p) => {\n const sessionId = sessionIdOf(p)\n if (typeof p.callId !== 'string' || p.callId.length === 0)\n throw new InvalidParamsError('callId must be a non-empty string.')\n // Read in place: the live turns, else the cached snapshot (no load and copy per expand).\n const live = host.getLiveSession(sessionId)\n const turns = live ? live.turns : (await snapshots.document(store, sessionId, null))?.data.turns\n if (!turns)\n return null\n const resultIn = (turn: SessionTurn): string | undefined => {\n for (const block of turn.content) {\n if (block.type === 'tool_result' && block.callId === p.callId)\n return toolResultText(block.output)\n }\n return undefined\n }\n // The named turn first, then the rest (newest first: results sit near their call).\n if (typeof p.turnId === 'string') {\n for (const turn of turns) {\n const text = turn.id === p.turnId ? resultIn(turn) : undefined\n if (text !== undefined)\n return text\n }\n }\n for (let i = turns.length - 1; i >= 0; i--) {\n const text = resultIn(turns[i]!)\n if (text !== undefined)\n return text\n }\n return null\n },\n 'sessions.titleStatus': async (p) => {\n const sessionId = sessionIdOf(p)\n const live = host.getLiveSession(sessionId)\n const header = live ? headerFromData(liveView(live)) : await getSessionHeader(store, sessionId)\n if (!header)\n throw new Error(`Session \"${sessionId}\" not found.`)\n return describeTitleStatus(header.metadata)\n },\n 'sessions.getHeader': async (p) => {\n const sessionId = sessionIdOf(p)\n const live = host.getLiveSession(sessionId)\n if (p.usage !== true)\n return live ? headerFromData(liveView(live)) : getSessionHeader(store, sessionId)\n // The footer's numbers need the turns: read here, only the numbers go out.\n const data = live ? liveView(live) : await store.load(sessionId)\n if (!data)\n return null\n const header = live ? headerFromData(data) : (await getSessionHeader(store, sessionId)) ?? headerFromData({ ...data, id: sessionId })\n // Only a run this host is running: a stored `running` run can be a dead process's.\n const run = live && host.isSessionRunning(sessionId) ? runProgress(data) : undefined\n return {\n ...header,\n contextTokens: lastContextSizeFromTurns(data.turns, data.runs),\n costUsd: sumRunCosts(data.runs),\n ...(run ? { runStartedAt: run.startedAt, runOutputTokens: run.outputTokens } : {}),\n }\n },\n 'sessions.setExtensionState': async (p) => {\n const sessionId = sessionIdOf(p)\n if (typeof p.extension !== 'string' || typeof p.key !== 'string')\n throw new InvalidParamsError('extension and key must be strings.')\n // The live copy when an agent holds the session (its save is\n // header-only, safe mid-run), else the stored one.\n const session = host.getLiveSession(sessionId) ?? await loadSession(store, sessionId, { persistHeal: false })\n if (!session)\n throw new Error(`Session \"${sessionId}\" not found.`)\n // Key checks and size bounds are the shared helpers' own.\n if (p.value === undefined)\n await deleteExtensionSessionState(session, p.extension, p.key)\n else\n await setExtensionSessionState(session, p.extension, p.key, p.value)\n },\n }\n}\n","/** Host settings and the runtime registry: read, write (rebuilding what a change requires), reload, and the setup wizard's write. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostSettings, HostSignal } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { Handlers } from './types'\nimport { settingsToWire } from '../../../chat/host-scoped-settings'\nimport { mergeOnboardingState } from '../../../chat/onboarding/result'\nimport { InvalidParamsError } from './params'\n\nconst isObject = (value: unknown): value is object => typeof value === 'object' && value !== null && !Array.isArray(value)\n\n/**\n * Settings that choose what is discovered on disk (MCP servers, skills,\n * plugins and the configs they come from): a change also re-walks the plugin\n * catalog, so a plugin installed outside the catalog shows up. Which agents\n * rebuild is decided per agent, from what its build read (`applyAgentSettings`).\n */\nconst DISCOVERY_KEYS = ['enabledMcps', 'disabledMcpTools', 'enabledSkills', 'enabledPlugins', 'importForeignConfigs', 'importRulerConfigs'] as const\n\nexport function createSettingsHandlers({ host, env, broadcast, onClose }: {\n host: ChatHost\n env: DaemonEnvironment\n broadcast: (signal: HostSignal) => void\n /** Registers what to stop when the host shuts down: the watch on the settings file. */\n onClose?: (stop: () => void) => void\n}): Handlers<'settings.get' | 'settings.set' | 'runtime.reload' | 'onboarding.complete'> {\n /*\n * The settings this host last acted on. A write through `settings.set` and a\n * change another process made to the file (two daemons, or a daemon and a\n * window in local mode, share `state.json`) are both applied against them,\n * so neither is missed.\n */\n let applied = env.readSettings()\n\n /**\n * Act on a settings change: swap the extension registry when its keys\n * changed, answer the interactions on screen when they switched to skip,\n * rebuild every agent built from a value that changed (at run end when busy,\n * no run aborted), and converge every window's settings UI.\n */\n function apply(next: HostSettings) {\n const before = applied\n applied = next\n const changed = (key: keyof HostSettings): boolean =>\n JSON.stringify(before[key]) !== JSON.stringify(next[key])\n\n /*\n * Extension toggles swap the registry: forget the runtime config first so\n * every rebuild resolves a fresh one, and dispose the old registries only\n * once no agent runs on them (as `runtime.reload`).\n */\n if (changed('enabledExtensions') || changed('loadProjectExtensions')) {\n const disposeOld = env.forgetRuntime()\n void host.rebuildAllAgents({ rediscover: true }).then(disposeOld, disposeOld)\n }\n else if (DISCOVERY_KEYS.some(changed)) {\n // Best-effort, as the extension branch: a failed rebuild must not reject unobserved.\n void host.rebuildAllAgents({ rediscover: true }).catch(() => undefined)\n }\n\n // Flipping to skip answers the modals already on screen — otherwise an\n // interaction raised under `ask` waits forever for an answer the new mode\n // says nobody will give. Resolved host-side so every window converges.\n if (changed('interactionMode') && next.interactionMode === 'skip')\n host.interactions.resolveAutomatically()\n\n // Rebuild what the change makes stale; close terminals turned off.\n host.applyAgentSettings(before, next)\n\n const wire = settingsToWire(next)\n broadcast({ kind: 'settings:changed', settings: wire })\n return wire\n }\n\n // Runs from a file watcher's timer: a throw there would be uncaught and end the host.\n const stopWatching = env.watchSettings?.(() => {\n try {\n const next = env.readSettings()\n if (JSON.stringify(next) !== JSON.stringify(applied))\n apply(next)\n }\n catch (err) {\n console.error('[ipc-daemon] applying a settings change from disk failed:', err)\n }\n })\n if (stopWatching)\n onClose?.(stopWatching)\n\n return {\n 'runtime.reload': () => {\n // Forget first so every rebuild (now for idle sessions, at run end for\n // busy ones) resolves a fresh registry; dispose the old registries only\n // once no agent runs on them. Disposing up front would tear down hooks\n // and HUD writers a busy run is still using.\n const disposeOld = env.forgetRuntime()\n void host.rebuildAllAgents().then(disposeOld, disposeOld)\n },\n\n // Every settings payload carries the legacy `safeMode` for windows older than `approvalMode`.\n 'settings.get': () => settingsToWire(env.readSettings()),\n 'settings.set': (p) => {\n const patch: unknown = p?.patch\n if (typeof patch !== 'object' || patch === null || Array.isArray(patch))\n throw new InvalidParamsError('patch must be an object of settings.')\n return apply(env.writeSettings(p.patch))\n },\n 'onboarding.complete': (p) => {\n const { set, reset } = p?.settings ?? {}\n if (!isObject(set) || !Array.isArray(reset) || reset.some(key => typeof key !== 'string'))\n throw new InvalidParamsError('settings must hold `set` (an object of settings) and `reset` (an array of keys).')\n if (!isObject(p.records))\n throw new InvalidParamsError('records must be an object.')\n const next = apply(env.writeSettings(set, reset))\n const { stateStore } = env.config\n const state = stateStore.load()\n stateStore.save({ ...state, onboarding: mergeOnboardingState(state.onboarding, p.records) })\n return next\n },\n }\n}\n","/** Inline autocomplete, resolved daemon-side and fanned out to every window on the session. */\nimport type { HostSignal } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { createPathAutocompleteProvider, resolveInlineSuggestion } from '../../../chat/inline-autocomplete'\nimport { loadOrThrow } from './session-load'\n\nexport function createSuggestHandlers({ env, broadcastExcept }: {\n env: DaemonEnvironment\n broadcastExcept: (origin: HostPeer | null, signal: HostSignal) => void\n}): {\n methods: Handlers<'suggest.resolve'>\n /** The session was deleted: abort its in-flight compute and forget its sequence. */\n forget: (sessionId: string) => void\n} {\n /**\n * Shared inline-autocomplete state — per-session latest-wins\n * coalescing for `suggest.resolve`. `seq` is the newest sequence seen\n * (stale requests return without computing); `controller` aborts an\n * in-flight compute when a newer request supersedes it (the GUI's\n * controller-map pattern, daemon-side). Entries outlive their compute\n * (the seq high-water mark), so the map is an LRU of 256 sessions:\n * refusing new keys at the cap instead would switch suggestions off for\n * every session past the 256th until the daemon restarts.\n */\n const suggests = new Map<string, { seq: number, controller: AbortController | null }>()\n\n const methods: Handlers<'suggest.resolve'> = {\n 'suggest.resolve': async (p, peer) => {\n const sessionId = String(p.sessionId)\n const seq = typeof p.seq === 'number' ? p.seq : 0\n // Same cheap shape guards + 64 KiB text cap as `drafts.set`.\n const text = typeof p.text === 'string' ? p.text.slice(0, 64 * 1024) : ''\n const caret = typeof p.caret === 'number'\n ? Math.max(0, Math.min(Math.floor(p.caret), text.length))\n : text.length\n\n const prev = suggests.get(sessionId)\n // Latest-wins: a stale seq answers immediately without computing —\n // the requester's own NEWER request (already in flight or about to\n // land) carries the authoritative result.\n if (prev && seq < prev.seq)\n return { suggestion: null, seq }\n // Supersede: abort the in-flight compute for this session, if any.\n prev?.controller?.abort()\n\n const controller = new AbortController()\n const entry = { seq, controller: controller as AbortController | null }\n suggests.delete(sessionId)\n suggests.set(sessionId, entry)\n if (suggests.size > 256) {\n const [oldest, evicted] = suggests.entries().next().value!\n evicted.controller?.abort()\n suggests.delete(oldest)\n }\n\n try {\n // Session cwd from metadata (same derivation as `toRow`) — the\n // per-cwd runtime config is the SAME registry the GUI main uses\n // locally, resolved through the existing daemon environment.\n const data = await loadOrThrow(env.store, sessionId)\n const meta = data.metadata ?? {}\n const cwd = typeof meta.cwd === 'string' ? meta.cwd : (data.projectRoot ?? '')\n const config = await env.runtimeConfig(cwd)\n // Canonical provider assembly (built-in path provider first, then\n // extension providers) and canonical deadlines —\n // `resolveInlineSuggestion` races each provider against its own\n // budget exactly as the GUI main / TUI do.\n const providers = [\n createPathAutocompleteProvider({ cwd: () => cwd }),\n ...config.extensions.inlineAutocompleteProviders,\n ]\n const result = await resolveInlineSuggestion(providers, { text, cursor: caret, cwd, signal: controller.signal })\n // Superseded mid-compute — the newer request owns the fan-out.\n if (controller.signal.aborted || suggests.get(sessionId) !== entry)\n return { suggestion: null, seq }\n // Full ordered candidate list rides along (additive field) so\n // clients keep ↑/↓ rotation; `suggestion` stays candidates[0] for\n // older clients that only read the single field.\n const candidates = result ? [...result.suffixes] : []\n const suggestion = candidates[0] ?? null\n // Fan out to every OTHER window on the session — the requester\n // already has the result from this RPC reply (drafts'\n // broadcastExcept pattern).\n broadcastExcept(peer, { kind: 'suggest:changed', sessionId, seq, basis: text, caret, suggestion, ...(candidates.length > 0 ? { candidates } : {}) })\n return { suggestion, seq, ...(candidates.length > 0 ? { candidates } : {}) }\n }\n finally {\n // Keep the seq high-water mark for stale checks; drop only the\n // controller so a finished compute can't be \"aborted\" later.\n if (suggests.get(sessionId) === entry)\n entry.controller = null\n }\n },\n }\n\n return {\n methods,\n forget: (sessionId) => {\n suggests.get(sessionId)?.controller?.abort()\n suggests.delete(sessionId)\n },\n }\n}\n","import type { EnvironmentRegistry } from '../../chat/environment'\nimport type { EnvironmentSecrets } from '../../chat/environment-settings'\n/**\n * Applying one `sync.push` category on a zidane-server (`./handlers/sync`\n * owns the record, the source check and the audit): each writes through the\n * host's own setters or the user-scope files, skipping overrides (a field\n * whose value here no longer matches what sync wrote becomes one), and\n * reports every field as applied, unchanged or skipped (with why).\n */\nimport type { SyncCategory, SyncFile, SyncPayloads, SyncPushResult } from '../../chat/sync/types'\nimport type { McpServerConfig } from '../../types'\nimport type { DaemonEnvironment } from './environment'\nimport type { ProviderAuth } from './handlers/auth'\nimport type { SyncSetters } from './handlers/sync'\nimport type { HostPeer } from './peers'\nimport type { SyncFieldRecord, SyncRecord } from './sync-store'\nimport { Buffer } from 'node:buffer'\nimport { createHash } from 'node:crypto'\nimport { accessSync, constants, existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from 'node:fs'\nimport { basename, delimiter, dirname, isAbsolute, join, relative, resolve, sep } from 'node:path'\nimport process from 'node:process'\nimport { writeFileAtomic } from '../../atomic-write'\nimport { applyEnvironmentSettingsChange, readEnvironmentSettings } from '../../chat/environment-settings'\nimport { isWindowOnlySetting } from '../../chat/host-scoped-settings'\nimport { parseMcpsFile } from '../../chat/mcps-discovery'\nimport { isMcpServerName, mcpsWritePath } from '../../chat/mcps-write'\nimport { projectUserPaths } from '../../chat/project-user-paths'\nimport { readProjects, safelistProjectKey, writeProjects } from '../../chat/safe-mode'\nimport { DEFAULT_SETTINGS } from '../../chat/settings-defaults'\nimport { hashValue, isRecord } from '../../chat/sync/hash'\nimport { isSyncableSetting, settingsFromWire } from '../../chat/sync/settings-keys'\nimport { settingField, SYNCABLE_ENVIRONMENT_KINDS, SYSTEM_MD_FIELD } from '../../chat/sync/types'\nimport { userSystemMdPath } from '../../chat/system-md'\nimport { InvalidParamsError } from './handlers/params'\n\n/** What applying a push reads and writes through. */\nexport interface SyncApplyContext {\n env: DaemonEnvironment\n setters: SyncSetters\n auth: Pick<ProviderAuth, 'descriptorOf' | 'storedKeys'>\n /** The host's environment kinds and their secret store (`environments`). */\n environments: EnvironmentRegistry\n environmentSecrets: EnvironmentSecrets\n home: () => string\n prefix: () => string\n}\n\nconst MAX_SETTINGS_BYTES = 256 * 1024\n\nconst MAX_SYSTEM_MD_BYTES = 256 * 1024\n\nconst MAX_FILE_BYTES = 1024 * 1024\n\nconst MAX_SKILL_BYTES = 4 * 1024 * 1024\n\nconst MAX_FILES_BYTES = 16 * 1024 * 1024\n\nconst MAX_SKILL_FILES = 200\n\nconst MAX_SKILLS = 500\n\nconst MAX_PATH_DEPTH = 8\n\nconst MAX_SAFELIST_ENTRIES = 1000\n\nconst MAX_ENTRY_LENGTH = 1000\n\nconst NAME_RE = /^\\w[\\w@.-]{0,99}$/\n\nconst SEGMENT_RE = /^[^/\\\\\\0]{1,255}$/\n\n/** A skill file's relative path: plain segments, no `..`, bounded depth. */\nfunction checkRelativePath(path: unknown): string | null {\n if (typeof path !== 'string' || path === '' || isAbsolute(path) || path.includes('\\\\'))\n return null\n const segments = path.split('/')\n if (segments.length > MAX_PATH_DEPTH || segments.some(s => s === '.' || s === '..' || !SEGMENT_RE.test(s)))\n return null\n return segments.join('/')\n}\n\n/** Is `command` runnable here (an absolute path, or found on PATH)? Looks, never runs. */\nfunction commandAvailable(command: string): boolean {\n const executable = (path: string): boolean => {\n try {\n accessSync(path, constants.X_OK)\n return statSync(path).isFile()\n }\n catch {\n return false\n }\n }\n if (command.includes('/'))\n return isAbsolute(command) && executable(command)\n return (process.env.PATH ?? '').split(delimiter).filter(Boolean).some(dir => executable(join(dir, command)))\n}\n\n/** A folder's files, sorted, as one hash (symlinks hashed by target, never followed). Null when absent. */\nfunction hashDir(dir: string): string | null {\n let stat\n try {\n stat = lstatSync(dir)\n }\n catch {\n return null\n }\n if (!stat.isDirectory())\n return `not-a-folder:${stat.mode}`\n const hash = createHash('sha256')\n const walk = (at: string, depth: number): void => {\n if (depth > MAX_PATH_DEPTH + 1)\n return\n for (const name of readdirSync(at).sort()) {\n const path = join(at, name)\n const rel = relative(dir, path).split(sep).join('/')\n const s = lstatSync(path)\n if (s.isDirectory()) {\n walk(path, depth + 1)\n }\n else if (s.isFile()) {\n hash.update(`f:${rel}\\0`)\n hash.update(readFileSync(path))\n hash.update('\\0')\n }\n else {\n hash.update(`o:${rel}:${s.mode}\\0`)\n }\n }\n }\n walk(dir, 0)\n return hash.digest('hex')\n}\n\n/** The hash `hashDir` gives the folder these files make. */\nfunction hashFiles(files: readonly { path: string, bytes: Buffer }[]): string {\n const hash = createHash('sha256')\n // `hashDir` walks in sorted order level by level: replay that order.\n const sorted = [...files].sort((a, b) => compareWalkOrder(a.path, b.path))\n for (const file of sorted) {\n hash.update(`f:${file.path}\\0`)\n hash.update(file.bytes)\n hash.update('\\0')\n }\n return hash.digest('hex')\n}\n\n/** The order a sorted depth-first walk visits two relative paths. */\nfunction compareWalkOrder(a: string, b: string): number {\n const as = a.split('/')\n const bs = b.split('/')\n for (let i = 0; i < Math.min(as.length, bs.length); i++) {\n if (as[i] !== bs[i]) {\n // Same level: readdir order (code units), whether file or folder.\n return as[i]! < bs[i]! ? -1 : 1\n }\n }\n return as.length - bs.length\n}\n\nfunction userSkillsRoot(ctx: SyncApplyContext): string {\n const root = projectUserPaths({ subPath: 'skills', cwd: ctx.home(), home: ctx.home(), prefix: ctx.prefix() })\n .find(p => p.source === 'user' && p.path.includes(`.${ctx.prefix().replace(/^\\./, '')}`))\n return root!.path\n}\nfunction userMcpsPath(ctx: SyncApplyContext): string {\n return mcpsWritePath('user', { home: ctx.home(), cwd: ctx.home(), prefix: ctx.prefix() })\n}\nfunction userExtensionDirs(ctx: SyncApplyContext, name: string): string[] {\n return projectUserPaths({ subPath: 'extensions', cwd: ctx.home(), home: ctx.home(), prefix: ctx.prefix() }).filter(p => p.source === 'user').map(p => join(p.path, name))\n}\n\n/** Is `field` free to write? An override (now or found by a changed value) is not. */\nfunction writable(record: SyncRecord, field: string, currentHash: string | null, result: SyncPushResult): boolean {\n if (record.overrides[field]) {\n result.skipped.push({ field, reason: 'override' })\n return false\n }\n const known = record.fields[field]\n if (known?.hash !== undefined && known.hash !== (currentHash ?? 'absent')) {\n record.overrides[field] = { at: Date.now() }\n result.skipped.push({ field, reason: 'override' })\n return false\n }\n return true\n}\n\nfunction mark(record: SyncRecord, field: string, category: SyncCategory, fields: Omit<SyncFieldRecord, 'category' | 'syncedAt'>): void {\n record.fields[field] = { category, syncedAt: Date.now(), ...fields }\n}\n\n// ---- settings ----------------------------------------------------------\nexport function pushSettings(ctx: SyncApplyContext, record: SyncRecord, payload: SyncPayloads['settings'], result: SyncPushResult): void {\n if (!isRecord(payload?.values))\n throw new InvalidParamsError('settings: payload.values must be an object.')\n if (JSON.stringify(payload.values).length > MAX_SETTINGS_BYTES)\n throw new InvalidParamsError(`settings: larger than ${MAX_SETTINGS_BYTES} bytes.`)\n const settings = ctx.env.readSettings()\n const current = settings as unknown as Record<string, unknown>\n const patch: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(settingsFromWire(payload.values, settings.approvalMode))) {\n const field = settingField(key)\n if (!Object.hasOwn(DEFAULT_SETTINGS, key)) {\n result.skipped.push({ field, reason: 'not a setting' })\n continue\n }\n if (!isSyncableSetting(key)) {\n result.skipped.push({ field, reason: isWindowOnlySetting(key) ? 'window-only setting' : 'not synced' })\n continue\n }\n const currentHash = hashValue(current[key])\n if (!writable(record, field, currentHash, result))\n continue\n if (hashValue(value) === currentHash) {\n mark(record, field, 'settings', { hash: currentHash, sent: currentHash })\n result.unchanged.push(field)\n continue\n }\n patch[key] = value\n }\n if (Object.keys(patch).length === 0)\n return\n const next = ctx.setters.setSettings(patch)\n for (const key of Object.keys(patch)) {\n mark(record, settingField(key), 'settings', { hash: hashValue(next[key]), sent: hashValue(patch[key]) })\n result.applied.push(settingField(key))\n }\n}\n\n// ---- safe-mode allowlists ----------------------------------------------\n/** The project here a client's path names: the same folder inside a workspace root, else one folder of that name in a root. */\nfunction projectHere(ctx: SyncApplyContext, clientPath: string): string | null {\n const roots = (ctx.env.workspaceRoots ?? []).map((root) => {\n try {\n return realpathSync(root)\n }\n catch {\n return null\n }\n }).filter((r): r is string => r !== null)\n const inRoot = (path: string): boolean => roots.some(root => path === root || path.startsWith(root + sep))\n const isDir = (path: string): boolean => statSync(path, { throwIfNoEntry: false })?.isDirectory() === true\n if (isAbsolute(clientPath) && isDir(clientPath)) {\n const real = realpathSync(clientPath)\n if (inRoot(real))\n return safelistProjectKey(real)\n }\n const name = basename(clientPath)\n if (!name || name === '.' || name === '..')\n return null\n const found = [...new Set(roots.map(root => join(root, name)).filter(isDir).map(path => realpathSync(path)))]\n return found.length === 1 ? safelistProjectKey(found[0]!) : null\n}\n\nexport function pushSafelists(ctx: SyncApplyContext, record: SyncRecord, payload: SyncPayloads['safelists'], result: SyncPushResult): void {\n if (!isRecord(payload?.projects))\n throw new InvalidParamsError('safelists: payload.projects must map paths to entries.')\n const dataDir = ctx.env.userDataDir()\n const file = readProjects(dataDir)\n let dirty = false\n for (const [clientPath, entries] of Object.entries(payload.projects)) {\n const field = `safelist:${clientPath}`\n if (!Array.isArray(entries) || entries.length > MAX_SAFELIST_ENTRIES || !entries.every(e => typeof e === 'string' && e.length <= MAX_ENTRY_LENGTH)) {\n result.skipped.push({ field, reason: 'invalid entries' })\n continue\n }\n const target = projectHere(ctx, clientPath)\n if (!target) {\n result.skipped.push({ field, reason: 'no project of that path or name on this server' })\n continue\n }\n // The server's own entries stay; the ones this device put there and dropped since go.\n const previous = record.fields[field]?.target === target ? (record.fields[field]?.entries ?? []) : []\n const current = file[target]?.safelist ?? []\n const next = current.filter(entry => !previous.includes(entry) || entries.includes(entry))\n for (const entry of entries) {\n if (!next.includes(entry))\n next.push(entry)\n }\n mark(record, field, 'safelists', { target, entries: [...entries] })\n if (JSON.stringify(next) === JSON.stringify(current)) {\n result.unchanged.push(field)\n continue\n }\n file[target] = { ...file[target], safelist: next }\n dirty = true\n result.applied.push(field)\n }\n if (dirty)\n writeProjects(dataDir, file)\n}\n\n// ---- SYSTEM.md and skills ----------------------------------------------\n/** A skill as checked bytes, or why it is refused. */\nfunction checkSkill(skill: unknown): { name: string, files: { path: string, bytes: Buffer }[] } | { field: string, reason: string } {\n const name = isRecord(skill) && typeof skill.name === 'string' ? skill.name : ''\n const field = `skill:${name}`\n if (!NAME_RE.test(name))\n return { field, reason: 'not a plain skill name' }\n const files = isRecord(skill) && Array.isArray(skill.files) ? skill.files as SyncFile[] : null\n if (!files || files.length === 0 || files.length > MAX_SKILL_FILES)\n return { field, reason: `needs 1 to ${MAX_SKILL_FILES} files` }\n const out: { path: string, bytes: Buffer }[] = []\n let total = 0\n for (const file of files) {\n const path = checkRelativePath(isRecord(file) ? file.path : undefined)\n if (!path)\n return { field, reason: 'a file path is not a plain relative path' }\n if (typeof file.data !== 'string')\n return { field, reason: `${path}: no data` }\n const bytes = Buffer.from(file.data, 'base64')\n if (bytes.length > MAX_FILE_BYTES)\n return { field, reason: `${path} is larger than ${MAX_FILE_BYTES} bytes` }\n total += bytes.length\n if (out.some(f => f.path === path || f.path.startsWith(`${path}/`) || path.startsWith(`${f.path}/`)))\n return { field, reason: `${path} appears twice` }\n out.push({ path, bytes })\n }\n if (total > MAX_SKILL_BYTES)\n return { field, reason: `larger than ${MAX_SKILL_BYTES} bytes` }\n return { name, files: out }\n}\n\n/** Replace `dir` with exactly these files: staged next to it, then swapped in. */\nfunction writeSkillDir(root: string, name: string, files: readonly { path: string, bytes: Buffer }[]): void {\n mkdirSync(root, { recursive: true })\n const dir = join(root, name)\n const stage = join(root, `.${name}.sync-${process.pid}-${Date.now()}`)\n mkdirSync(stage)\n try {\n for (const file of files) {\n const target = resolve(stage, file.path)\n if (!target.startsWith(stage + sep))\n throw new Error(`${file.path} is outside the skill folder.`)\n mkdirSync(dirname(target), { recursive: true })\n writeFileSync(target, file.bytes)\n }\n const backup = existsSync(dir) ? `${stage}.old` : null\n if (backup)\n renameSync(dir, backup)\n renameSync(stage, dir)\n if (backup)\n rmSync(backup, { recursive: true, force: true })\n }\n finally {\n rmSync(stage, { recursive: true, force: true })\n }\n}\n\nexport function pushFiles(ctx: SyncApplyContext, record: SyncRecord, payload: SyncPayloads['files'], result: SyncPushResult): boolean {\n if (!isRecord(payload) || !Array.isArray(payload.skills) || payload.skills.length > MAX_SKILLS || (payload.systemMd !== null && typeof payload.systemMd !== 'string'))\n throw new InvalidParamsError('files: payload must be { systemMd: string | null, skills: [...] }.')\n let touched = false\n let total = 0\n\n // SYSTEM.md (user scope).\n const mdPath = userSystemMdPath({ home: ctx.home(), prefix: ctx.prefix() })\n const currentMd = existsSync(mdPath) ? readFileSync(mdPath, 'utf8') : null\n const currentMdHash = currentMd === null ? null : hashValue(currentMd)\n if (payload.systemMd !== null && Buffer.byteLength(payload.systemMd) > MAX_SYSTEM_MD_BYTES) {\n result.skipped.push({ field: SYSTEM_MD_FIELD, reason: `larger than ${MAX_SYSTEM_MD_BYTES} bytes` })\n }\n else if (payload.systemMd !== null || record.fields[SYSTEM_MD_FIELD]) {\n if (writable(record, SYSTEM_MD_FIELD, currentMdHash, result)) {\n if (payload.systemMd === null) {\n // This computer has none any more: drop the one sync wrote.\n rmSync(mdPath, { force: true })\n delete record.fields[SYSTEM_MD_FIELD]\n result.applied.push(SYSTEM_MD_FIELD)\n touched = true\n }\n else if (hashValue(payload.systemMd) === currentMdHash) {\n mark(record, SYSTEM_MD_FIELD, 'files', { hash: currentMdHash })\n result.unchanged.push(SYSTEM_MD_FIELD)\n }\n else {\n total += Buffer.byteLength(payload.systemMd)\n writeFileAtomic(mdPath, payload.systemMd, { ensureDir: true })\n mark(record, SYSTEM_MD_FIELD, 'files', { hash: hashValue(payload.systemMd) })\n result.applied.push(SYSTEM_MD_FIELD)\n touched = true\n }\n }\n }\n\n // Skills (user scope, `~/.<prefix>/skills/<name>`).\n const root = userSkillsRoot(ctx)\n const sent = new Set<string>()\n for (const raw of payload.skills) {\n const skill = checkSkill(raw)\n if ('reason' in skill) {\n result.skipped.push(skill)\n continue\n }\n const field = `skill:${skill.name}`\n sent.add(field)\n const bytes = skill.files.reduce((n, f) => n + f.bytes.length, 0)\n if (total + bytes > MAX_FILES_BYTES) {\n result.skipped.push({ field, reason: `over the ${MAX_FILES_BYTES}-byte bound of one push` })\n continue\n }\n const dir = join(root, skill.name)\n if (existsSync(dir) && lstatSync(dir).isSymbolicLink()) {\n result.skipped.push({ field, reason: 'a link on this server, left alone' })\n continue\n }\n const currentHash = hashDir(dir)\n if (!writable(record, field, currentHash, result))\n continue\n const wanted = hashFiles(skill.files)\n if (wanted === currentHash) {\n mark(record, field, 'files', { hash: wanted })\n result.unchanged.push(field)\n continue\n }\n total += bytes\n writeSkillDir(root, skill.name, skill.files)\n mark(record, field, 'files', { hash: hashDir(dir) ?? wanted })\n result.applied.push(field)\n touched = true\n }\n // Skills this device synced and no longer has.\n for (const [field, known] of Object.entries(record.fields)) {\n if (known.category !== 'files' || !field.startsWith('skill:') || sent.has(field))\n continue\n const dir = join(root, field.slice('skill:'.length))\n if (!writable(record, field, hashDir(dir), result))\n continue\n rmSync(dir, { recursive: true, force: true })\n delete record.fields[field]\n result.applied.push(field)\n touched = true\n }\n return touched\n}\n\n// ---- MCP servers ---------------------------------------------------------\nfunction readUserMcps(ctx: SyncApplyContext): McpServerConfig[] {\n const path = userMcpsPath(ctx)\n if (!existsSync(path))\n return []\n try {\n return parseMcpsFile(readFileSync(path, 'utf8'))\n }\n catch {\n return []\n }\n}\n\nexport async function pushMcps(ctx: SyncApplyContext, record: SyncRecord, payload: SyncPayloads['mcps'], peer: HostPeer, result: SyncPushResult): Promise<void> {\n if (!isRecord(payload) || !Array.isArray(payload.servers))\n throw new InvalidParamsError('mcps: payload.servers must be a list.')\n const hashOf = (name: string): string | null => {\n const found = readUserMcps(ctx).find(s => s.name === name)\n return found ? hashValue(found) : null\n }\n const sent = new Set<string>()\n for (const config of payload.servers) {\n const name = isRecord(config) && typeof config.name === 'string' ? config.name : ''\n const field = `mcp:${name}`\n if (!isMcpServerName(name)) {\n result.skipped.push({ field, reason: 'not a plain server name' })\n continue\n }\n sent.add(field)\n const currentHash = hashOf(name)\n if (!writable(record, field, currentHash, result))\n continue\n const wanted = hashValue(config)\n if (record.fields[field]?.sent === wanted && currentHash !== null) {\n result.unchanged.push(field)\n continue\n }\n try {\n await ctx.setters.mcpUpsert({ config: config as unknown as McpServerConfig }, peer)\n }\n catch (err) {\n result.skipped.push({ field, reason: err instanceof Error ? err.message : String(err) })\n continue\n }\n mark(record, field, 'mcps', { hash: hashOf(name) ?? wanted, sent: wanted })\n result.applied.push(field)\n if (typeof config.command === 'string' && config.command.trim() !== '' && !commandAvailable(config.command.trim()))\n result.warnings.push({ field, message: `\"${config.command}\" is not on this server's PATH: the server may not run there.` })\n }\n for (const [field, known] of Object.entries(record.fields)) {\n if (known.category !== 'mcps' || sent.has(field))\n continue\n const name = field.slice('mcp:'.length)\n if (!writable(record, field, hashOf(name), result))\n continue\n try {\n await ctx.setters.mcpRemove({ name }, peer)\n }\n catch (err) {\n result.skipped.push({ field, reason: err instanceof Error ? err.message : String(err) })\n continue\n }\n delete record.fields[field]\n result.applied.push(field)\n }\n}\n\n// ---- extensions ----------------------------------------------------------\nexport async function pushExtensions(ctx: SyncApplyContext, record: SyncRecord, payload: SyncPayloads['extensions'], peer: HostPeer, result: SyncPushResult): Promise<void> {\n if (!isRecord(payload) || !Array.isArray(payload.extensions))\n throw new InvalidParamsError('extensions: payload.extensions must be a list.')\n for (const entry of payload.extensions) {\n const name = isRecord(entry) && typeof entry.name === 'string' ? entry.name : ''\n const field = `extension:${name}`\n if (!NAME_RE.test(name) || typeof entry.spec !== 'string') {\n result.skipped.push({ field, reason: 'needs a plain name and a source spec' })\n continue\n }\n if (record.overrides[field]) {\n result.skipped.push({ field, reason: 'override' })\n continue\n }\n // Installed already (by sync or by hand): left as it is, never updated or removed by sync.\n if (userExtensionDirs(ctx, name).some(dir => existsSync(dir))) {\n if (!record.fields[field])\n mark(record, field, 'extensions', {})\n result.unchanged.push(field)\n continue\n }\n try {\n await ctx.setters.install({ kind: 'extension', spec: entry.spec, scope: 'user', ...(typeof entry.extension === 'string' ? { extension: entry.extension } : {}) }, peer)\n }\n catch (err) {\n result.skipped.push({ field, reason: err instanceof Error ? err.message : String(err) })\n continue\n }\n mark(record, field, 'extensions', {})\n result.applied.push(field)\n }\n}\n\n// ---- provider API keys ---------------------------------------------------\n// ---- environments ------------------------------------------------------\n/**\n * Cloud sandbox kinds (`SYNCABLE_ENVIRONMENT_KINDS`): each as the server's\n * own `environments.update` writes it, so its registry checks every option.\n * A kind the server doesn't have, or the device sent outside the list, is\n * skipped. An edit made on the server since is an override (compared by the\n * hash of its options and on/off state; keys are not read back).\n */\nexport function pushEnvironments(ctx: SyncApplyContext, record: SyncRecord, payload: SyncPayloads['environments'], result: SyncPushResult): void {\n if (!isRecord(payload) || !Array.isArray(payload.kinds))\n throw new InvalidParamsError('environments: payload.kinds must be a list.')\n const currentHash = (kind: string): string => {\n const settings = readEnvironmentSettings(ctx.env.readSettings())\n return hashValue({ config: settings.config[kind] ?? {}, enabled: settings.enabled.includes(kind), disabled: settings.disabled.includes(kind) })\n }\n for (const entry of payload.kinds) {\n const kind = isRecord(entry) && typeof entry.kind === 'string' ? entry.kind : ''\n const field = `environment:${kind}`\n if (!SYNCABLE_ENVIRONMENT_KINDS.includes(kind)) {\n result.skipped.push({ field, reason: 'not a cloud sandbox' })\n continue\n }\n if (!writable(record, field, currentHash(kind), result))\n continue\n const wanted = hashValue(entry)\n if (record.fields[field]?.sent === wanted) {\n result.unchanged.push(field)\n continue\n }\n const values = isRecord(entry.values) ? entry.values : {}\n const secrets = isRecord(entry.secrets) ? entry.secrets : {}\n try {\n const write = applyEnvironmentSettingsChange(ctx.environments, ctx.env.readSettings(), {\n kind,\n ...(typeof entry.enabled === 'boolean' ? { enabled: entry.enabled } : {}),\n values: { ...values, ...secrets } as Record<string, string | number | boolean>,\n })\n for (const secret of write.secrets)\n ctx.environmentSecrets.set(kind, secret.key, secret.value)\n ctx.setters.setSettings(write.settingsPatch)\n }\n catch (err) {\n result.skipped.push({ field, reason: err instanceof Error ? err.message : String(err) })\n continue\n }\n mark(record, field, 'environments', { hash: currentHash(kind), sent: wanted })\n result.applied.push(field)\n }\n}\n\nexport function pushKeys(ctx: SyncApplyContext, record: SyncRecord, payload: SyncPayloads['keys'], result: SyncPushResult): void {\n if (!isRecord(payload) || !Array.isArray(payload.keys))\n throw new InvalidParamsError('keys: payload.keys must be a list.')\n for (const entry of payload.keys) {\n const provider = isRecord(entry) && typeof entry.provider === 'string' ? entry.provider : ''\n const field = `key:${provider}`\n if (!record.keys.includes(provider)) {\n result.skipped.push({ field, reason: 'not opted in for this key' })\n continue\n }\n if (record.overrides[field]) {\n result.skipped.push({ field, reason: 'override' })\n continue\n }\n try {\n if (typeof entry.key !== 'string' || entry.key.trim() === '')\n throw new Error('empty key')\n if (ctx.auth.storedKeys(ctx.auth.descriptorOf(provider)).includes(entry.key.trim())) {\n if (!record.fields[field])\n mark(record, field, 'keys', {})\n result.unchanged.push(field)\n continue\n }\n ctx.setters.setApiKey({ provider, key: entry.key })\n }\n catch (err) {\n result.skipped.push({ field, reason: err instanceof Error ? err.message : String(err) })\n continue\n }\n mark(record, field, 'keys', {})\n result.applied.push(field)\n }\n}\n","/**\n * A zidane-server's settings-sync record (`<dataDir>/sync.json`, 0600,\n * written atomically): the source device, the categories and API keys it\n * opted in, the fields it set (with a hash of what the server held after\n * each write, to tell a server-side edit) and the fields edited here since\n * (overrides). No secret is stored: an API key field has no hash.\n */\nimport type { SyncCategory, SyncSource, SyncStatus } from '../../chat/sync/types'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { OWNER_ONLY, writeJsonFileAtomic } from '../../atomic-write'\nimport { isRecord } from '../../chat/sync/hash'\nimport { settingField, SYNC_CATEGORIES } from '../../chat/sync/types'\n\nexport interface SyncFieldRecord {\n category: SyncCategory\n syncedAt: number\n /** Hash of the server's value right after the last write: anything else there now is an edit made here. */\n hash?: string\n /** Hash of the value the source sent last: the same again is `unchanged`. */\n sent?: string\n /** A safelist: the project key it maps to here, and the entries the source put there. */\n target?: string\n entries?: string[]\n}\n\nexport interface SyncRecord {\n version: 1\n source: SyncSource | null\n categories: SyncCategory[]\n keys: string[]\n fields: Record<string, SyncFieldRecord>\n overrides: Record<string, { at: number }>\n lastPushAt?: number\n}\n\nexport const SYNC_FILE = 'sync.json'\n\nexport function emptySyncRecord(): SyncRecord {\n return { version: 1, source: null, categories: [], keys: [], fields: {}, overrides: {} }\n}\n\nconst SAFE_MODE_FIELD = settingField('safeMode')\nconst APPROVAL_MODE_FIELD = settingField('approvalMode')\n\n/**\n * `approvalMode` replaced the synced `safeMode`. An override of it still\n * guards the server's mode, so it moves over; its field hash (of a boolean)\n * matches no mode, so it goes and the next push syncs the field afresh.\n */\nfunction withoutSafeModeField(record: SyncRecord): SyncRecord {\n const { [SAFE_MODE_FIELD]: override, ...overrides } = record.overrides\n const { [SAFE_MODE_FIELD]: _field, ...fields } = record.fields\n if (override && !overrides[APPROVAL_MODE_FIELD])\n overrides[APPROVAL_MODE_FIELD] = override\n return { ...record, fields, overrides }\n}\n\nexport interface SyncStore {\n file: string\n read: () => SyncRecord\n write: (record: SyncRecord) => void\n}\n\nexport function createSyncStore(dataDir: string): SyncStore {\n const file = join(dataDir, SYNC_FILE)\n return {\n file,\n read: () => {\n if (!existsSync(file))\n return emptySyncRecord()\n try {\n const raw: unknown = JSON.parse(readFileSync(file, 'utf8'))\n if (!isRecord(raw))\n return emptySyncRecord()\n const source = isRecord(raw.source) && typeof raw.source.deviceId === 'string' && typeof raw.source.deviceName === 'string'\n ? raw.source as unknown as SyncSource\n : null\n return withoutSafeModeField({\n version: 1,\n source,\n categories: Array.isArray(raw.categories) ? raw.categories.filter((c): c is SyncCategory => SYNC_CATEGORIES.includes(c as SyncCategory)) : [],\n keys: Array.isArray(raw.keys) ? raw.keys.filter((k): k is string => typeof k === 'string') : [],\n fields: isRecord(raw.fields) ? raw.fields as Record<string, SyncFieldRecord> : {},\n overrides: isRecord(raw.overrides) ? raw.overrides as Record<string, { at: number }> : {},\n ...(typeof raw.lastPushAt === 'number' ? { lastPushAt: raw.lastPushAt } : {}),\n })\n }\n catch {\n // Unreadable: start over (the next write replaces it).\n return emptySyncRecord()\n }\n },\n write: record => writeJsonFileAtomic(file, record, OWNER_ONLY),\n }\n}\n\n/** What `sync.status` says: the record without hashes or safelist entries. */\nexport function syncStatusOf(record: SyncRecord): SyncStatus {\n return {\n source: record.source,\n categories: [...record.categories],\n keys: [...record.keys],\n fields: Object.fromEntries(Object.entries(record.fields).map(([field, f]) => [field, { category: f.category, syncedAt: f.syncedAt }])),\n overrides: { ...record.overrides },\n ...(record.lastPushAt !== undefined ? { lastPushAt: record.lastPushAt } : {}),\n }\n}\n","/**\n * Settings sync from a client's computer (`sync.*`, `docs/SERVER.md`\n * § Settings sync): a zidane-server takes one device's settings, files,\n * MCP servers, extensions and opted-in API keys, through the same setters a\n * window uses (`settings.set`, `mcp.upsert` / `remove`, `catalog.install`,\n * `auth.setApiKey`, the user-scope files), and keeps a record of what came\n * from where (`../sync-store`).\n *\n * - One source per server: `sync.claim` by another device is refused unless\n * it takes over (which drops the previous source's marks, not its values).\n * The source is the device AND the token it claimed with: a device id is a\n * client's word, so the same id from another token is another source\n * (coordination between a user's devices, bound to who authenticated).\n * - A field edited on the server since it was synced (through a window, or\n * on disk: its value no longer matches what sync wrote) is an override:\n * pushes skip it until `sync.reset`.\n * - Window-only settings never apply; skills are written by plain names and\n * relative paths inside the skills folder, size-bounded; extensions and\n * MCP servers go through the install gate (`allowRemoteInstalls`) and its\n * audit; API keys only for providers the source opted in.\n * - Every call is audited with the connection's token; no value is logged.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { SyncCategory, SyncPayloads, SyncPushResult, SyncStatus } from '../../../chat/sync/types'\nimport type { HostSignal, IpcParams } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { HostPeer } from '../peers'\nimport type { SyncApplyContext } from '../sync-apply'\nimport type { SyncRecord } from '../sync-store'\nimport type { ProviderAuth } from './auth'\nimport type { Handlers } from './types'\nimport { homedir } from 'node:os'\nimport { isRecord } from '../../../chat/sync/hash'\nimport { settingField, SYNC_CATEGORIES } from '../../../chat/sync/types'\nimport { pushEnvironments, pushExtensions, pushFiles, pushKeys, pushMcps, pushSafelists, pushSettings } from '../sync-apply'\nimport { createSyncStore, syncStatusOf } from '../sync-store'\nimport { InvalidParamsError } from './params'\n\nexport interface SyncOptions {\n /** One audit line per call (the server adds the connection's token). */\n audit?: (peer: HostPeer, entry: Record<string, unknown>) => void\n}\n\ntype SyncMethod = 'sync.status' | 'sync.claim' | 'sync.push' | 'sync.reset' | 'sync.release'\n\n/** The host's own setters, as a window calls them (installs gated and audited there). */\nexport interface SyncSetters {\n setSettings: (patch: Record<string, unknown>) => Record<string, unknown>\n install: (params: IpcParams<'catalog.install'>, peer: HostPeer) => Promise<unknown> | unknown\n mcpUpsert: (params: IpcParams<'mcp.upsert'>, peer: HostPeer) => Promise<unknown> | unknown\n mcpRemove: (params: IpcParams<'mcp.remove'>, peer: HostPeer) => Promise<unknown> | unknown\n setApiKey: (params: IpcParams<'auth.setApiKey'>) => unknown\n}\n\nconst MAX_DEVICE_FIELD = 200\n\nconst NOT_A_SERVER = 'This host takes no settings sync (a zidane-server does).'\n\nfunction checkDevice(p: { deviceId?: unknown, deviceName?: unknown }, withName: boolean): { deviceId: string, deviceName: string } {\n if (typeof p.deviceId !== 'string' || p.deviceId.trim() === '' || p.deviceId.length > MAX_DEVICE_FIELD)\n throw new InvalidParamsError('deviceId must be a non-empty string.')\n if (withName && (typeof p.deviceName !== 'string' || p.deviceName.trim() === '' || p.deviceName.length > MAX_DEVICE_FIELD))\n throw new InvalidParamsError('deviceName must be a non-empty string.')\n return { deviceId: p.deviceId, deviceName: typeof p.deviceName === 'string' ? p.deviceName.trim() : '' }\n}\n\nfunction checkCategories(value: unknown): SyncCategory[] | undefined {\n if (value === undefined)\n return undefined\n if (!Array.isArray(value) || !value.every(c => SYNC_CATEGORIES.includes(c as SyncCategory)))\n throw new InvalidParamsError(`categories must be some of: ${SYNC_CATEGORIES.join(', ')}.`)\n return SYNC_CATEGORIES.filter(c => value.includes(c))\n}\n\nexport function createSyncHandlers({ host, env, broadcast, setters, auth, options }: {\n host: Pick<ChatHost, 'rebuildAllAgents' | 'environments' | 'environmentSecrets'>\n env: DaemonEnvironment\n broadcast: (signal: HostSignal) => void\n setters: SyncSetters\n auth: Pick<ProviderAuth, 'descriptorOf' | 'storedKeys'>\n options?: SyncOptions\n}): Handlers<SyncMethod> & { markOverrides: (fields: readonly string[]) => Promise<void> } {\n const store = createSyncStore(env.userDataDir())\n const ctx: SyncApplyContext = { env, setters, auth, environments: host.environments, environmentSecrets: host.environmentSecrets, home: () => homedir(), prefix: () => env.config.prefix }\n\n /** Sync calls (and override marks) one at a time: each reads the record, works, writes it. */\n let queue: Promise<unknown> = Promise.resolve()\n const exclusive = <T>(work: () => Promise<T> | T): Promise<T> => {\n const next = queue.then(work, work)\n queue = next.catch(() => undefined)\n return next\n }\n\n const changed = (): void => broadcast({ kind: 'sync:changed' })\n const audit = (peer: HostPeer, entry: Record<string, unknown>): void => options?.audit?.(peer, entry)\n\n function requireOptions(): void {\n if (!options)\n throw new Error(NOT_A_SERVER)\n }\n\n /** Mark fields the source set as edited here; nothing for fields nobody synced. */\n const markOverrides = (fields: readonly string[]): Promise<void> => {\n if (!options || fields.length === 0)\n return Promise.resolve()\n return exclusive(() => {\n const record = store.read()\n const marked = fields.filter(field => record.fields[field] && !record.overrides[field])\n if (marked.length === 0)\n return\n const at = Date.now()\n for (const field of marked)\n record.overrides[field] = { at }\n store.write(record)\n changed()\n })\n }\n\n /** Whether `deviceId` over `peer`'s token is the recorded source. */\n const isSource = (record: SyncRecord, deviceId: string, peer: HostPeer): boolean =>\n record.source !== null && record.source.deviceId === deviceId && record.source.tokenId === peer.principal\n\n /** The source's own call, or a refusal naming the device that syncs. */\n function requireSource(record: SyncRecord, deviceId: string, peer: HostPeer): void {\n if (!record.source)\n throw new Error('No device syncs to this server: claim it first (sync.claim).')\n if (!isSource(record, deviceId, peer))\n throw new Error(`This server is synced from ${record.source.deviceName}${record.source.deviceId === deviceId ? ' with another token' : ''}: take over from that device first.`)\n }\n\n const rebuild = (): void => {\n void host.rebuildAllAgents({ rediscover: true }).catch(() => undefined)\n }\n\n return {\n markOverrides,\n\n 'sync.status': (): SyncStatus => {\n requireOptions()\n return syncStatusOf(store.read())\n },\n\n 'sync.claim': (p, peer) => exclusive(() => {\n requireOptions()\n const { deviceId, deviceName } = checkDevice(p, true)\n const categories = checkCategories(p.categories)\n if (p.keys !== undefined && (!Array.isArray(p.keys) || !p.keys.every(k => typeof k === 'string')))\n throw new InvalidParamsError('keys must be provider names.')\n const takeover = p.takeover === true\n const record = store.read()\n const other = record.source !== null && !isSource(record, deviceId, peer)\n if (other && !takeover) {\n audit(peer, { event: 'sync.claim', deviceId, deviceName, takeover, claimed: false, ok: true })\n return { claimed: false, status: syncStatusOf(record) }\n }\n const next: SyncRecord = other\n ? { version: 1, source: null, categories: [], keys: [], fields: {}, overrides: {} }\n : record\n next.source = {\n deviceId,\n deviceName,\n claimedAt: other || !record.source ? Date.now() : record.source.claimedAt,\n ...(peer.principal ? { tokenId: peer.principal } : {}),\n }\n if (categories)\n next.categories = categories\n if (p.keys !== undefined)\n next.keys = [...new Set(p.keys)]\n store.write(next)\n changed()\n audit(peer, { event: 'sync.claim', deviceId, deviceName, takeover, claimed: true, categories: next.categories, keys: next.keys, ok: true })\n return { claimed: true, status: syncStatusOf(next) }\n }),\n\n 'sync.push': (p, peer) => exclusive(async () => {\n requireOptions()\n const { deviceId } = checkDevice(p, false)\n const category = p.category\n const fields = { event: 'sync.push', category, deviceId }\n try {\n if (!SYNC_CATEGORIES.includes(category))\n throw new InvalidParamsError(`category must be one of: ${SYNC_CATEGORIES.join(', ')}.`)\n const record = store.read()\n requireSource(record, deviceId, peer)\n if (!record.categories.includes(category))\n throw new Error(`\"${category}\" is not synced to this server (claim it with that category).`)\n const result: SyncPushResult = { applied: [], unchanged: [], skipped: [], warnings: [] }\n const payload = p.payload as unknown\n if (category === 'settings') {\n pushSettings(ctx, record, payload as SyncPayloads['settings'], result)\n }\n else if (category === 'safelists') {\n pushSafelists(ctx, record, payload as SyncPayloads['safelists'], result)\n }\n else if (category === 'files') {\n if (pushFiles(ctx, record, payload as SyncPayloads['files'], result)) {\n rebuild()\n broadcast({ kind: 'catalog:changed', catalog: 'skills' })\n }\n }\n else if (category === 'mcps') {\n await pushMcps(ctx, record, payload as SyncPayloads['mcps'], peer, result)\n }\n else if (category === 'extensions') {\n await pushExtensions(ctx, record, payload as SyncPayloads['extensions'], peer, result)\n }\n else if (category === 'environments') {\n pushEnvironments(ctx, record, payload as SyncPayloads['environments'], result)\n }\n else {\n pushKeys(ctx, record, payload as SyncPayloads['keys'], result)\n }\n record.lastPushAt = Date.now()\n store.write(record)\n changed()\n audit(peer, { ...fields, applied: result.applied.length, unchanged: result.unchanged.length, skipped: result.skipped.length, ok: true })\n return result\n }\n catch (err) {\n audit(peer, { ...fields, ok: false, error: err instanceof Error ? err.message : String(err) })\n throw err\n }\n }),\n\n 'sync.reset': (p, peer) => exclusive(() => {\n requireOptions()\n if (typeof p.field !== 'string' || p.field === '')\n throw new InvalidParamsError('field must be a sync field name.')\n const record = store.read()\n const reset = Boolean(record.overrides[p.field])\n if (reset) {\n delete record.overrides[p.field]\n // Forget the server value it was compared against: the next push writes over it.\n const known = record.fields[p.field]\n if (known) {\n delete known.hash\n delete known.sent\n }\n store.write(record)\n changed()\n }\n audit(peer, { event: 'sync.reset', field: p.field, reset, ok: true })\n return { reset }\n }),\n\n 'sync.release': (p, peer) => exclusive(() => {\n requireOptions()\n const { deviceId } = checkDevice(p, false)\n const record = store.read()\n if (!record.source)\n return { released: false }\n requireSource(record, deviceId, peer)\n // What it set stays; the marks go.\n store.write({ version: 1, source: null, categories: [], keys: [], fields: {}, overrides: {} })\n changed()\n audit(peer, { event: 'sync.release', deviceId, ok: true })\n return { released: true }\n }),\n }\n}\n\ntype OverrideWrapped = 'settings.set' | 'mcp.upsert' | 'mcp.remove' | 'catalog.remove' | 'catalog.update' | 'auth.setApiKey' | 'auth.configure' | 'auth.remove' | 'auth.setPreferred'\n\n/**\n * The window-facing setters, marking what they change as an override when\n * the field came from sync (the sync handlers call the unwrapped ones).\n */\nexport function withSyncOverrides(\n handlers: Handlers<OverrideWrapped>,\n { readSettings, markOverrides }: { readSettings: () => object, markOverrides: (fields: readonly string[]) => Promise<void> },\n): Handlers<OverrideWrapped> {\n const after = async <T>(work: () => Promise<T> | T, fields: (result: T) => string[]): Promise<T> => {\n const result = await work()\n await markOverrides(fields(result))\n return result\n }\n return {\n 'settings.set': async (p, peer) => {\n const before = readSettings() as Record<string, unknown>\n return after(() => handlers['settings.set'](p, peer), next => Object.keys(isRecord(p?.patch) ? p.patch : {})\n .filter(key => JSON.stringify(before[key]) !== JSON.stringify((next as unknown as Record<string, unknown>)[key]))\n .map(settingField))\n },\n 'mcp.upsert': (p, peer) => after(() => handlers['mcp.upsert'](p, peer), r => (p.scope === 'project' ? [] : [`mcp:${r.name}`])),\n 'mcp.remove': (p, peer) => after(() => handlers['mcp.remove'](p, peer), r => (r.removed ? [`mcp:${p.name}`] : [])),\n 'catalog.remove': (p, peer) => after(() => handlers['catalog.remove'](p, peer), () => [`${p.kind}:${p.name}`]),\n 'catalog.update': (p, peer) => after(() => handlers['catalog.update'](p, peer), () => [`${p.kind}:${p.name}`]),\n 'auth.setApiKey': (p, peer) => after(() => handlers['auth.setApiKey'](p, peer), () => [`key:${p.provider}`]),\n 'auth.configure': (p, peer) => after(() => handlers['auth.configure'](p, peer), () => [`key:${p.provider}`]),\n 'auth.remove': (p, peer) => after(() => handlers['auth.remove'](p, peer), r => (r.removed ? [`key:${p.provider}`] : [])),\n 'auth.setPreferred': (p, peer) => after(() => handlers['auth.setPreferred'](p, peer), () => [`key:${p.provider}`]),\n }\n}\n","/** Shared terminals: lifecycle, I/O, and the views and viewers each client attaches. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { nonNegativeInt } from './params'\n\ntype TerminalMethod\n = | 'terminal.state' | 'terminal.open' | 'terminal.attach' | 'terminal.detach' | 'terminal.write'\n | 'terminal.resize' | 'terminal.ack' | 'terminal.restart' | 'terminal.close' | 'terminal.setHidden'\n | 'terminal.registerViewer' | 'terminal.unregisterViewer'\n | 'terminal.projectState' | 'terminal.openInProject' | 'terminal.adopt' | 'terminal.releaseDraft'\n\nexport function createTerminalHandlers({ host, isConnected }: {\n host: ChatHost\n isConnected: (peer: HostPeer) => boolean\n}): {\n methods: Handlers<TerminalMethod>\n /** The peer dropped: release its drafts and viewers, then detach its views. */\n releasePeer: (peer: HostPeer) => void\n} {\n return {\n methods: {\n 'terminal.state': p => host.terminals.state(p.sessionId),\n 'terminal.open': p => host.terminals.open(p),\n 'terminal.attach': async (p, peer) => {\n // Optional: older clients omit it, and 0 means no cap.\n const maxLines = nonNegativeInt(p.maxLines, 'maxLines') || undefined\n const result = await host.terminals.attach(p.terminalId, p.clientId, { maxLines })\n // The peer dropped during the attach (a remote reconnect can take seconds):\n // its cleanup already ran, so a client left behind would never ack and stall every view.\n if (!isConnected(peer)) {\n host.terminals.detach(p.terminalId, p.clientId)\n return result\n }\n const views = (peer.terminalViews ??= new Map())\n views.set(p.terminalId, (views.get(p.terminalId) ?? new Set()).add(p.clientId))\n return result\n },\n 'terminal.detach': (p, peer) => {\n const views = peer.terminalViews?.get(p.terminalId)\n views?.delete(p.clientId)\n if (views?.size === 0)\n peer.terminalViews?.delete(p.terminalId)\n host.terminals.detach(p.terminalId, p.clientId)\n },\n 'terminal.write': p => host.terminals.write(p.terminalId, p.data, p.clientId ? { clientId: p.clientId, ...(p.response ? { response: true } : {}) } : undefined),\n 'terminal.resize': p => host.terminals.resize(p.terminalId, p.clientId, p.cols, p.rows, p.claim),\n 'terminal.ack': p => host.terminals.ack(p.terminalId, p.clientId, p.offset),\n 'terminal.restart': p => host.terminals.restart(p.terminalId),\n 'terminal.close': p => host.terminals.close(p.terminalId),\n 'terminal.setHidden': p => host.terminals.setHidden(p.terminalId, p.hidden),\n 'terminal.projectState': p => host.terminals.projectState(p),\n 'terminal.openInProject': async (p, peer) => {\n if (p.draftId)\n (peer.terminalDrafts ??= new Set()).add(p.draftId)\n const result = await host.terminals.openInProject(p)\n // The peer dropped during the open: its cleanup already ran, so nothing would release this draft.\n if (p.draftId && !isConnected(peer))\n host.terminals.releaseDraft(p.draftId)\n return result\n },\n 'terminal.adopt': async (p, peer) => {\n const result = await host.terminals.adopt(p)\n peer.terminalDrafts?.delete(p.draftId)\n return result\n },\n 'terminal.releaseDraft': (p, peer) => {\n peer.terminalDrafts?.delete(p.draftId)\n host.terminals.releaseDraft(p.draftId)\n },\n 'terminal.registerViewer': (p, peer) => {\n ;(peer.terminalViewers ??= new Set()).add(p.viewerId)\n host.terminals.registerViewer(p.viewerId)\n return { ok: true }\n },\n 'terminal.unregisterViewer': (p, peer) => {\n peer.terminalViewers?.delete(p.viewerId)\n host.terminals.unregisterViewer(p.viewerId)\n return { ok: true }\n },\n },\n releasePeer(peer) {\n // A client that crashed or quit never releases its drafts: give their terminals back to the project.\n for (const draftId of peer.terminalDrafts ?? [])\n host.terminals.releaseDraft(draftId)\n for (const viewerId of peer.terminalViewers ?? [])\n host.terminals.unregisterViewer(viewerId)\n for (const [terminalId, clients] of peer.terminalViews ?? []) {\n for (const clientId of clients)\n host.terminals.detach(terminalId, clientId)\n }\n },\n }\n}\n","/** `sessions.generateTitle`: the host titles a session with its own providers and credentials (`ChatHost.generateSessionTitle`). */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostSignal } from '../../protocol'\nimport type { Handlers } from './types'\nimport { optionalString, sessionIdOf } from './params'\n\nexport function createTitleHandlers({ host, broadcast }: {\n host: ChatHost\n broadcast: (signal: HostSignal) => void\n}): Handlers<'sessions.generateTitle'> {\n return {\n 'sessions.generateTitle': async (p) => {\n const sessionId = sessionIdOf(p)\n const providerKey = optionalString(p.providerKey, 'providerKey')\n const model = optionalString(p.model, 'model')\n const title = await host.generateSessionTitle(sessionId, {\n ...(providerKey !== undefined ? { providerKey } : {}),\n ...(model !== undefined ? { model } : {}),\n })\n // As `sessions.setTitle`: every window told.\n broadcast({ kind: 'sessions:changed', op: 'update', sessionId })\n return { title }\n },\n }\n}\n","/** A session's todo list. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { TodoItem } from '../../../chat/todos'\nimport type { SessionStore } from '../../../session/index'\nimport type { TodosSnapshot } from '../../protocol'\nimport type { Handlers } from './types'\nimport { toTodosSnapshot } from '../../../chat/host/signals'\nimport { selectActiveTodos, setTodosForRun } from '../../../chat/todos'\nimport { loadSession } from '../../../session/index'\n\nexport function createTodoHandlers({ host, store }: { host: ChatHost, store: SessionStore }): Handlers<'todos.get' | 'todos.set'> {\n return {\n 'todos.get': (p): TodosSnapshot | null => {\n const state = host.getTodosSnapshot(p.sessionId)\n return state ? toTodosSnapshot(state) : null\n },\n\n /*\n * The host fans the resulting `todos:snapshot` out to every window,\n * including this caller — the returned snapshot is a confirmation, so the\n * sender can tell \"applied\" from \"no live agent\" (null) rather than\n * assuming success. `persistIdle` turns \"no live agent\" into a write to\n * the stored session (nothing else is writing it), for a client that has\n * no store of its own.\n */\n 'todos.set': async (p): Promise<TodosSnapshot | null> => {\n const state = await host.setTodos(p.sessionId, p.items)\n if (state)\n return toTodosSnapshot(state)\n if (p.persistIdle !== true || host.getLiveSession(p.sessionId))\n return null\n return persistIdleTodos(store, p.sessionId, Array.isArray(p.items) ? p.items : [])\n },\n }\n}\n\n/** The idle-session todo edit, as a window applied it to its own copy: the active run's list, archive cleared. */\nasync function persistIdleTodos(store: SessionStore, sessionId: string, items: readonly TodoItem[]): Promise<TodosSnapshot | null> {\n const session = await loadSession(store, sessionId, { persistHeal: false })\n if (!session)\n return null\n // `null` before the first run: the session slot that run will read.\n setTodosForRun(session, selectActiveTodos(session).runId, items, { clearArchive: true })\n await session.save()\n return toTodosSnapshot(selectActiveTodos(session))\n}\n","/** A session's turns: replay, fork, edits, out-of-band appends, and compaction. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { StreamEvent } from '../../../chat/index'\nimport type { SessionStore } from '../../../session/index'\nimport type { HostTranscriptPager } from '../../history/index'\nimport type { HostSignal, LoadEventsPaging } from '../../protocol'\nimport type { Handlers } from './types'\nimport { describeForkFailure } from '../../../chat/session-factory'\nimport { eventsFromTurns } from '../../../chat/store'\nimport { loadOrThrow } from './session-load'\nimport { isPagedLoad } from './transcript-page'\n\ntype TranscriptMethod\n = | 'sessions.loadEvents' | 'sessions.getTurn' | 'sessions.touch' | 'sessions.fork' | 'sessions.deleteTurn'\n | 'sessions.editTurnText' | 'sessions.rewind' | 'sessions.appendTurns' | 'sessions.appendNote' | 'sessions.compact'\n\nexport function createTranscriptHandlers({ host, store, broadcast, pages }: {\n host: ChatHost\n store: SessionStore\n broadcast: (signal: HostSignal) => void\n /** Pages, sliced from the session's whole replay (one replay per scroll-back, not per page), off this thread when it can. */\n pages: Pick<HostTranscriptPager, 'page'>\n}): Handlers<TranscriptMethod> {\n return {\n 'sessions.loadEvents': async (p) => {\n const paging = p as typeof p & LoadEventsPaging\n if (isPagedLoad(paging)) {\n // A slice of the whole replay: pages concatenate to exactly one whole load.\n // The paged shape (`loadEventsPage`); the method is typed by its unpaged call.\n return await pages.page(store, p.sessionId, paging) as unknown as StreamEvent[]\n }\n const data = await loadOrThrow(store, p.sessionId)\n // Pass `runs` so replay reconstructs subagent depth / ancestry /\n // spawn rendering — matching the GUI + TUI local replay paths.\n return eventsFromTurns(data.turns, data.runs)\n },\n 'sessions.getTurn': async (p) => {\n const data = await store.load(p.sessionId)\n return data?.turns.find(t => t.id === p.turnId) ?? null\n },\n // Out-of-band transcript append (local command / bash output) — tell\n // every window to re-converge on the store's canonical replay.\n 'sessions.touch': (p) => {\n broadcast({ kind: 'sessions:changed', op: 'update', sessionId: p.sessionId })\n },\n 'sessions.fork': async (p) => {\n const result = await host.forkSession({\n source: p.sessionId,\n turnId: p.turnId,\n ...(typeof p.title === 'string' && p.title ? { title: p.title.slice(0, 256) } : {}),\n })\n if (!result.ok)\n throw new Error(describeForkFailure(result.reason, p.sessionId, p.turnId))\n broadcast({ kind: 'sessions:changed', op: 'create', sessionId: result.id })\n return { id: result.id }\n },\n 'sessions.deleteTurn': p => host.deleteTurn(p.sessionId, p.turnId),\n // Same 64 KiB text cap as the composer paths.\n 'sessions.editTurnText': p => host.editTurnText(p.sessionId, p.turnId, typeof p.text === 'string' ? p.text.slice(0, 64 * 1024) : ''),\n 'sessions.rewind': p => host.rewindSession(p.sessionId, p.turnId, { inclusive: p.inclusive === true }),\n 'sessions.appendTurns': p => host.appendTurns(p.sessionId, Array.isArray(p.turns) ? p.turns : [], { whenIdle: p.whenIdle === true }),\n 'sessions.appendNote': p => host.appendNote(\n p.sessionId,\n Array.isArray(p.blocks) ? p.blocks.filter(block => typeof block?.text === 'string') : [],\n ),\n 'sessions.compact': p => host.compactSessionNow(p.sessionId),\n }\n}\n","/**\n * `usage.summary`: the welcome screen's usage summary over the host's\n * sessions database, as the desktop app reduces its own\n * (`../../../chat/usage-summary.ts`). The scan reads every turn, so its day\n * buckets are kept a minute and every range is cut from them; concurrent\n * calls share one scan. Days are the host's local days. The greeting's name\n * is left out: the host's user is not the person reading.\n *\n * `usage.providers`: each provider's plan windows, probed with the host's\n * credentials (`../../../chat/provider-usage.ts`, which caches them), and\n * `usage.github`: GitHub's API limits as the host's GitHub client sees them.\n */\nimport type { ProviderDescriptor } from '../../../chat/providers'\nimport type { UsageRange } from '../../../chat/usage-summary'\nimport type { SessionStore } from '../../../session/index'\nimport type { UsageBuckets } from '../../../session/sqlite-usage'\nimport type { Handlers } from './types'\nimport { fetchGithubUsage } from '../../../chat/github-usage'\nimport { fetchAllProviderUsage } from '../../../chat/provider-usage'\nimport { summarizeUsage, USAGE_RANGES } from '../../../chat/usage-summary'\nimport { InvalidParamsError } from './params'\n\n/** How long one scan's buckets serve. */\nconst BUCKETS_TTL_MS = 60_000\n\nexport function createUsageHandlers({ store, scan, dataDir, providers }: {\n store: SessionStore\n /** The store's day buckets (`HostTranscriptPager.usage`); `null`: the store keeps no usage. */\n scan: (store: SessionStore) => Promise<UsageBuckets | null>\n /** Where the credentials are. */\n dataDir: () => string\n /** The host's providers. */\n providers: () => Readonly<Record<string, ProviderDescriptor>>\n}): Handlers<'usage.summary' | 'usage.providers' | 'usage.github'> {\n let cached: { buckets: UsageBuckets, at: number } | null = null\n let pending: Promise<UsageBuckets> | null = null\n const buckets = (now: number): Promise<UsageBuckets> => {\n if (cached && now - cached.at < BUCKETS_TTL_MS)\n return Promise.resolve(cached.buckets)\n pending ??= scan(store).then((scanned) => {\n if (!scanned)\n throw new Error('This host\\'s session store keeps no usage history.')\n cached = { buckets: scanned, at: Date.now() }\n return scanned\n }).finally(() => {\n pending = null\n })\n return pending\n }\n return {\n 'usage.summary': async (p) => {\n if (!USAGE_RANGES.includes(p.range as UsageRange))\n throw new InvalidParamsError(`range must be one of ${USAGE_RANGES.join(', ')}.`)\n const now = new Date()\n return summarizeUsage(await buckets(now.getTime()), p.range, { now })\n },\n 'usage.providers': p => fetchAllProviderUsage(dataDir(), providers(), { refresh: p?.refresh === true }),\n 'usage.github': p => fetchGithubUsage({ probe: p?.probe === true }),\n }\n}\n","/** Commands and file access inside a session's workspace (its execution environment). */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { Handlers } from './types'\nimport { Buffer } from 'node:buffer'\n\ntype WorkspaceMethod\n = | 'sessions.workspaceExec' | 'sessions.workspaceReadFile' | 'sessions.workspaceWriteFile'\n | 'sessions.workspaceListFiles' | 'sessions.workspaceFileSize'\n | 'sessions.workspaceCreate' | 'sessions.workspaceMove' | 'sessions.workspaceCopy' | 'sessions.workspaceRemove'\n | 'sessions.workspaceEmptyDirs'\n\n/** A path param of an entry call: a string, else refused like any invalid name (the rules check the rest). */\nconst pathParam = (value: unknown): string => (typeof value === 'string' ? value : '\\0')\n\nexport function createWorkspaceHandlers({ host }: { host: ChatHost }): Handlers<WorkspaceMethod> {\n return {\n 'sessions.workspaceExec': p => host.workspaceExec(p.sessionId, p.command, {\n ...(p.cwd !== undefined ? { cwd: p.cwd } : {}),\n ...(p.env !== undefined ? { env: p.env } : {}),\n ...(p.timeoutSeconds !== undefined ? { timeoutSeconds: p.timeoutSeconds } : {}),\n }),\n 'sessions.workspaceReadFile': p => host.workspaceReadFile(p.sessionId, p.path),\n 'sessions.workspaceWriteFile': p => host.workspaceWriteFile(p.sessionId, p.path, p.content),\n 'sessions.workspaceListFiles': p => host.workspaceListFiles(p.sessionId, p.path, p.options),\n 'sessions.workspaceFileSize': p => host.workspaceFileSize(p.sessionId, p.path),\n 'sessions.workspaceCreate': (p) => {\n if (p.kind !== 'file' && p.kind !== 'dir')\n throw new Error('kind must be \"file\" or \"dir\".')\n if (p.content !== undefined && typeof p.content !== 'string')\n throw new Error('content must be base64 text.')\n return host.workspaceCreate(p.sessionId, pathParam(p.path), p.kind, {\n ...(p.content !== undefined ? { content: new Uint8Array(Buffer.from(p.content, 'base64')) } : {}),\n ...(p.freeName === true ? { freeName: true } : {}),\n })\n },\n 'sessions.workspaceMove': p => host.workspaceMove(p.sessionId, pathParam(p.from), pathParam(p.to)),\n 'sessions.workspaceCopy': p => host.workspaceCopy(p.sessionId, pathParam(p.from), pathParam(p.toDir)),\n 'sessions.workspaceRemove': p => host.workspaceRemove(p.sessionId, pathParam(p.path)),\n 'sessions.workspaceEmptyDirs': p => host.workspaceEmptyDirs(p.sessionId),\n }\n}\n","import type { ChatHost } from '../../../chat/host/engine'\n/**\n * Streamed workspace commands (`sessions.workspaceExecStream` /\n * `sessions.workspaceExecCancel`): `!` on a remote host, live. The process\n * is the session context's `execStream` (a machine's too); its output goes\n * to the connection that started it only, as `workspace:exec:data` signals,\n * then one `workspace:exec:exit`. Bounded per connection: concurrent\n * commands, chunk size, total output (past it the process group is stopped\n * and the exit says `truncated`). Cancel and a dropped connection kill the\n * process group. A context that can't stream runs the buffered exec and\n * reports it the same way (its cancel stops reporting, not the command).\n */\nimport type { StreamHandle } from '../../../contexts/types'\nimport type { HostSignal } from '../../protocol'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { Buffer } from 'node:buffer'\nimport { randomUUID } from 'node:crypto'\nimport { InvalidParamsError } from './params'\n\nexport const WORKSPACE_EXEC_STREAM_LIMITS = {\n /** Streamed commands one connection may run at once. */\n maxConcurrent: 4,\n /** Largest `chunk` of one data signal, in bytes. */\n chunkBytes: 64 * 1024,\n /** Output past this (stdout + stderr, bytes) stops the process: the same ceiling as a local `!`. */\n maxOutputBytes: 1024 * 1024,\n /** Longest command text. */\n maxCommandLength: 64 * 1024,\n /** The buffered fallback's bound (seconds), as the buffered `!` had. */\n fallbackTimeoutSeconds: 600,\n}\n\ntype ExitSignal = Extract<HostSignal, { kind: 'workspace:exec:exit' }>\n\ninterface RunningExec {\n peer: HostPeer\n /** Ends the process group (the fallback: stops reporting). */\n kill: () => void\n cancelled: boolean\n /** A kill was sent before the process's exit was known: the exit is the kill's. */\n killedLive?: boolean\n}\n\n/** Cut `text` into pieces of at most `max` UTF-8 bytes, never inside a code point. */\nfunction utf8Pieces(text: string, max: number): string[] {\n if (Buffer.byteLength(text) <= max)\n return [text]\n const pieces: string[] = []\n let current = ''\n let bytes = 0\n for (const char of text) {\n const size = Buffer.byteLength(char)\n if (bytes + size > max) {\n pieces.push(current)\n current = ''\n bytes = 0\n }\n current += char\n bytes += size\n }\n if (current)\n pieces.push(current)\n return pieces\n}\n\n/** The longest prefix of `text` within `max` UTF-8 bytes. */\nfunction utf8Prefix(text: string, max: number): string {\n let bytes = 0\n let end = 0\n for (const char of text) {\n const size = Buffer.byteLength(char)\n if (bytes + size > max)\n break\n bytes += size\n end += char.length\n }\n return text.slice(0, end)\n}\n\nexport function createWorkspaceExecStreamHandlers({ host, isConnected, limits = WORKSPACE_EXEC_STREAM_LIMITS }: {\n host: Pick<ChatHost, 'workspaceExecStream' | 'workspaceExec'>\n isConnected: (peer: HostPeer) => boolean\n limits?: typeof WORKSPACE_EXEC_STREAM_LIMITS\n}): {\n methods: Handlers<'sessions.workspaceExecStream' | 'sessions.workspaceExecCancel'>\n /** The peer dropped: kill what it started. */\n releasePeer: (peer: HostPeer) => void\n} {\n const running = new Map<string, RunningExec>()\n const perPeer = new WeakMap<HostPeer, Set<string>>()\n\n const send = (peer: HostPeer, signal: HostSignal): void => {\n if (isConnected(peer))\n peer.send(signal)\n }\n\n /** Output accounting for one exec: emits what fits, reports when the cap is reached. */\n function outputSink(execId: string, peer: HostPeer, onCap: () => void) {\n let total = 0\n let capped = false\n return {\n capped: () => capped,\n emit(stream: 'stdout' | 'stderr', text: string): void {\n if (capped || text === '')\n return\n let piece = text\n if (total + Buffer.byteLength(piece) > limits.maxOutputBytes) {\n piece = utf8Prefix(piece, limits.maxOutputBytes - total)\n capped = true\n }\n total += Buffer.byteLength(piece)\n for (const chunk of piece ? utf8Pieces(piece, limits.chunkBytes) : [])\n send(peer, { kind: 'workspace:exec:data', execId, stream, chunk })\n if (capped)\n onCap()\n },\n }\n }\n\n async function pump(execId: string, peer: HostPeer, stream: StreamHandle, entry: RunningExec): Promise<void> {\n const sink = outputSink(execId, peer, () => entry.kill())\n const drain = async (source: AsyncIterable<Uint8Array> | undefined, name: 'stdout' | 'stderr'): Promise<void> => {\n if (!source)\n return\n const decoder = new TextDecoder()\n try {\n for await (const bytes of source)\n sink.emit(name, decoder.decode(bytes, { stream: true }))\n sink.emit(name, decoder.decode())\n }\n catch {\n // The stream ended badly (a dropped machine link): the exit says how.\n }\n }\n const [code] = await Promise.all([stream.exited, drain(stream.stdout, 'stdout'), drain(stream.stderr, 'stderr')])\n // A cancel or cap that landed after the process exited on its own leaves its real exit.\n const killed = entry.killedLive === true\n const exit: ExitSignal = {\n kind: 'workspace:exec:exit',\n execId,\n code: killed ? null : code,\n signal: killed ? 'SIGTERM' : null,\n ...(sink.capped() ? { truncated: true as const } : {}),\n ...(entry.cancelled && killed ? { cancelled: true as const } : {}),\n }\n send(peer, exit)\n }\n\n /** A context without `execStream`: the buffered exec, reported as one stdout and one stderr chunk. */\n async function buffered(execId: string, peer: HostPeer, entry: RunningExec, run: () => Promise<{ stdout: string, stderr: string, exitCode: number }>): Promise<void> {\n let stopped = false\n entry.kill = () => {\n stopped = true\n }\n const sink = outputSink(execId, peer, () => undefined)\n try {\n const result = await run()\n if (!stopped) {\n sink.emit('stdout', result.stdout)\n sink.emit('stderr', result.stderr)\n }\n send(peer, {\n kind: 'workspace:exec:exit',\n execId,\n code: stopped ? null : result.exitCode,\n signal: stopped ? 'SIGTERM' : null,\n ...(sink.capped() ? { truncated: true as const } : {}),\n ...(entry.cancelled ? { cancelled: true as const } : {}),\n })\n }\n catch (err) {\n sink.emit('stderr', err instanceof Error ? err.message : String(err))\n send(peer, { kind: 'workspace:exec:exit', execId, code: null, signal: null, ...(entry.cancelled ? { cancelled: true as const } : {}) })\n }\n }\n\n return {\n methods: {\n 'sessions.workspaceExecStream': async (p, peer) => {\n if (typeof p.sessionId !== 'string' || p.sessionId === '')\n throw new InvalidParamsError('sessionId must be a non-empty string.')\n if (typeof p.command !== 'string' || p.command.trim() === '')\n throw new InvalidParamsError('command must be a non-empty string.')\n if (p.command.length > limits.maxCommandLength)\n throw new InvalidParamsError(`command is longer than ${limits.maxCommandLength} characters.`)\n if (p.cwd !== undefined && typeof p.cwd !== 'string')\n throw new InvalidParamsError('cwd must be a string.')\n const own = perPeer.get(peer) ?? new Set<string>()\n perPeer.set(peer, own)\n if (own.size >= limits.maxConcurrent)\n throw new Error(`This connection already runs ${own.size} shell commands (at most ${limits.maxConcurrent}): stop one first.`)\n const execId = randomUUID()\n // Reserved before the await: concurrent requests count against the bound too.\n own.add(execId)\n const entry: RunningExec = { peer, kill: () => undefined, cancelled: false }\n running.set(execId, entry)\n const done = (): void => {\n own.delete(execId)\n running.delete(execId)\n }\n const options = p.cwd !== undefined ? { cwd: p.cwd } : {}\n let stream: StreamHandle | null\n try {\n stream = await host.workspaceExecStream(p.sessionId, p.command, options)\n }\n catch (err) {\n done()\n throw err\n }\n if (stream) {\n const live = stream\n let exited = false\n void live.exited.then(() => {\n exited = true\n }, () => {\n exited = true\n })\n entry.kill = () => {\n if (!exited)\n entry.killedLive = true\n void live.kill()\n }\n // Dropped while it started: nobody will read it.\n if (!isConnected(peer))\n entry.kill()\n void pump(execId, peer, live, entry).finally(done)\n }\n else {\n void buffered(execId, peer, entry, () => host.workspaceExec(p.sessionId, p.command, { ...options, timeoutSeconds: limits.fallbackTimeoutSeconds })).finally(done)\n }\n return { execId }\n },\n 'sessions.workspaceExecCancel': (p, peer) => {\n const entry = typeof p.execId === 'string' ? running.get(p.execId) : undefined\n if (!entry || entry.peer !== peer)\n return { cancelled: false }\n entry.cancelled = true\n entry.kill()\n return { cancelled: true }\n },\n },\n releasePeer(peer) {\n for (const execId of perPeer.get(peer) ?? []) {\n const entry = running.get(execId)\n if (entry) {\n entry.cancelled = true\n entry.kill()\n }\n }\n },\n }\n}\n","/**\n * `ipc.hello` verdict: can this client attach to this host process?\n *\n * Pure (no I/O, no state) so every transport applies the same three fences:\n * protocol version, build fingerprint, release. Kept apart from the\n * dispatcher because the rules are subtle and the direction of each fence\n * (only a strictly NEWER client retires the host) matters more than the code.\n *\n * A network server (`hostKind: 'server'`) keeps only the protocol fence: it\n * outlives any one client's upgrade and no client may retire it, so a newer\n * release or build attaches and degrades like an older one does.\n */\nimport type { HelloParams, HostKind } from '../protocol'\nimport { compareVersions } from '../../version'\nimport { IPC_MIN_PROTOCOL_VERSION, IPC_PROTOCOL_VERSION } from '../protocol'\n\nexport type HelloVerdict\n /**\n * `retire`: attach, but the host must exit at its first idle point. `protocolVersion`: what\n * the connection speaks (a server and a client in each other's range speak the lower one).\n */\n = | { accept: true, retire: boolean, protocolVersion: number }\n | { accept: false, message: string }\n\nexport interface HelloContext {\n /** This host's build fingerprint (`IPC_BUILD_ID`; `'unknown'` in compiled binaries). */\n buildId: string\n /** This host's release (`ZIDANE_VERSION`). */\n codeVersion: string\n /** Runs, queues or interactions in flight that a drain would abort. */\n hasActiveWork: boolean\n /** What this host is. Default: a local daemon's fences. */\n hostKind?: HostKind\n}\n\n/**\n * A server accepts a client whose version range overlaps its own\n * ({@link IPC_MIN_PROTOCOL_VERSION}…{@link IPC_PROTOCOL_VERSION}); they speak the lower version.\n */\nfunction evaluateServerHello(params: Partial<HelloParams>): HelloVerdict {\n const client = typeof params.protocolVersion === 'number' ? params.protocolVersion : undefined\n const clientMin = typeof params.minProtocolVersion === 'number' ? Math.min(params.minProtocolVersion, client ?? Infinity) : client\n if (client !== undefined && clientMin !== undefined && clientMin <= IPC_PROTOCOL_VERSION && client >= IPC_MIN_PROTOCOL_VERSION)\n return { accept: true, retire: false, protocolVersion: Math.min(client, IPC_PROTOCOL_VERSION) }\n const upgrade = client !== undefined && client > IPC_PROTOCOL_VERSION ? 'server' : 'client'\n const speaks = IPC_MIN_PROTOCOL_VERSION === IPC_PROTOCOL_VERSION ? `v${IPC_PROTOCOL_VERSION}` : `v${IPC_MIN_PROTOCOL_VERSION} to v${IPC_PROTOCOL_VERSION}`\n return {\n accept: false,\n message: `Protocol version mismatch: the server speaks ${speaks}, the client v${client ?? '?'}. Upgrade the ${upgrade}.`,\n }\n}\n\nexport function evaluateHello(params: Partial<HelloParams>, ctx: HelloContext): HelloVerdict {\n if (ctx.hostKind === 'server')\n return evaluateServerHello(params)\n /*\n * Build-fingerprint drain is DIRECTIONAL: only a strictly NEWER\n * client retires this (older) daemon. An older client accepts a\n * newer daemon — its unknown methods degrade via `optional()`.\n * Without the direction check, two concurrently-running clients\n * from different builds would each reject the other's daemon and\n * drain-respawn in a loop, aborting live runs each cycle.\n */\n const clientBuild = Number(params.buildId)\n const daemonBuild = Number(ctx.buildId)\n const staleBuild\n = params.buildId !== undefined\n && params.buildId !== 'unknown'\n && ctx.buildId !== 'unknown'\n && Number.isFinite(clientBuild)\n && Number.isFinite(daemonBuild)\n && clientBuild > daemonBuild\n /*\n * Release fence: the same protocol version can span several\n * releases, and a daemon outlives the upgrade that replaced its\n * binary — a client running strictly NEWER code must not execute on\n * the old process. Same direction rule as the build fence: only a\n * newer client retires the daemon; older clients attach and degrade.\n */\n const staleRelease\n = typeof params.codeVersion === 'string'\n && compareVersions(params.codeVersion, ctx.codeVersion) > 0\n /*\n * Same protocol, older code, live work: attach instead of asking\n * for a drain that would abort it. The client can speak to this\n * daemon; it only must not stay on it, so the daemon retires at\n * its first idle point and the client's reconnect lands on a\n * fresh one. A protocol mismatch can't attach and stays refused.\n */\n const protocolMatches = params.protocolVersion === IPC_PROTOCOL_VERSION\n if (protocolMatches && (staleBuild || staleRelease) && ctx.hasActiveWork)\n return { accept: true, retire: true, protocolVersion: IPC_PROTOCOL_VERSION }\n if (!protocolMatches || staleBuild || staleRelease) {\n return {\n accept: false,\n message: staleRelease\n ? `Stale daemon: it runs zidane ${ctx.codeVersion} but the client runs ${params.codeVersion}. Draining for respawn.`\n : staleBuild\n ? `Build mismatch: the daemon was started from an older build (daemon ${ctx.buildId}, client ${params.buildId}). Draining for respawn.`\n : `Protocol version mismatch: daemon speaks v${IPC_PROTOCOL_VERSION}, client sent v${params.protocolVersion ?? '?'}.`,\n }\n }\n return { accept: true, retire: false, protocolVersion: IPC_PROTOCOL_VERSION }\n}\n","/**\n * Host identity: which host a client is talking to, stable across restarts.\n *\n * The id is a UUID written once to `<dataDir>/host-id` and read back on every\n * start. The data dir is the host's `userDataDir` (the user's zidane dir), so\n * the local daemon and a window's in-process host share one id: they serve\n * the same store on the same computer. A remote `zidane-server` has its own\n * data dir, hence its own id.\n */\nimport type { HostKind } from '../protocol'\nimport { hostname } from 'node:os'\nimport { join } from 'node:path'\nimport { readOrCreateHostIdFile } from '../../host-id'\n\nexport interface HostIdentityOptions {\n kind: HostKind\n /** Display name. Default: the machine's hostname. */\n name?: string\n}\n\nexport interface HostIdentity {\n /** `undefined` when the data dir can't hold the id: the host still serves, without identity. */\n id: string | undefined\n kind: HostKind\n name: string\n}\n\nconst FILE = 'host-id'\n\nexport function resolveHostIdentity(dataDir: string, options: HostIdentityOptions): HostIdentity {\n return {\n id: readOrCreateHostIdFile(join(dataDir, FILE)),\n kind: options.kind,\n name: options.name ?? hostname(),\n }\n}\n","/**\n * Connected peers: the set, signal fan-out, live presence, and the cleanup a\n * dropped peer triggers. Presence piggybacks on fan-out, so the two live\n * together.\n *\n * Streaming deltas are coalesced here, once per event-loop turn: a run of\n * consecutive deltas with the same owner (`deltaKey`) goes out as one signal\n * with their texts joined, one number, one log entry. Anything else that is\n * fanned out (any other signal, terminal output, an origin-excluded one) and\n * a peer joining or leaving sends the held delta first, and so does\n * {@link PeerRegistry.flush}, which the dispatcher calls around every\n * request, so a reply never overtakes a delta emitted before it.\n */\nimport type { ChatHost } from '../../chat/host/engine'\nimport type { HostSignal, SessionPresence } from '../protocol'\nimport type { ClientScope } from '../scopes'\n\n/**\n * A signal serialized once for every peer of one fan-out. `json` is the\n * signal's JSON, computed on first use (`undefined`: it cannot be encoded,\n * so no peer can receive it). `frame` is where the wire transports memoize\n * the notification text they all send (`../transports/peer-rpc`).\n */\nexport interface EncodedSignal {\n json: () => string | undefined\n frame?: string\n}\n\nexport function encodeSignal(signal: HostSignal): EncodedSignal {\n let json: string | undefined\n let done = false\n return {\n json: () => {\n if (!done) {\n done = true\n try {\n json = JSON.stringify(signal)\n }\n catch {\n json = undefined\n }\n }\n return json\n },\n }\n}\n\n/** One connected client, as the dispatcher sees it. The transport creates it and supplies `send`. */\nexport interface HostPeer {\n /**\n * Delivers one host signal to this client, with its number in its session\n * when it has one (`./signal-log`; the wire carries it as\n * `SIGNAL_SEQ_FIELD`). `encoded` is the same signal already serialized\n * for every peer of the fan-out (absent: serialize it yourself). Must\n * never throw.\n */\n send: (signal: HostSignal, seq?: number, encoded?: EncodedSignal) => void\n /** Set once `ipc.hello` succeeded; only ready peers receive signals. */\n ready: boolean\n /** Session this peer's window is attached to (`presence.watch`). */\n watching: string | null\n /** Browser hosts this peer registered (`browser.registerHost`), released when it drops. */\n browserHosts?: Set<string>\n /** Terminal views attached through this peer: terminal id → client ids. Detached when it drops. */\n terminalViews?: Map<string, Set<string>>\n /** Terminal viewers this peer registered (`terminal.registerViewer`), released when it drops. */\n terminalViewers?: Set<string>\n /** Drafts this peer opened terminals in (`terminal.openInProject`), released to their project when it drops. */\n terminalDrafts?: Set<string>\n /** What authenticated the connection (a zidane-server's token id), for its audit lines. */\n principal?: string\n /**\n * The client scope its token grants (`../scopes`): a call above it is refused. Absent: the\n * connection reaches every method (a local window, the daemon's socket).\n */\n grant?: ClientScope\n /**\n * The protocol version this connection speaks, set by `ipc.hello` (the lower of the client's\n * and the host's, `../daemon/handshake`). A handler that changed shape across versions reads it.\n */\n protocolVersion?: number\n}\n\nexport interface PeerRegistry {\n add: (peer: HostPeer) => void\n /** Whether the peer is still connected (a handler may outlive its peer across an await). */\n has: (peer: HostPeer) => boolean\n /** The peer's connection ended: run every `onClose` cleanup in registration order, then refresh presence. */\n remove: (peer: HostPeer) => void\n /** Release what a peer registered when it drops; runs in registration order. */\n onClose: (cleanup: (peer: HostPeer) => void) => void\n /** Forget every peer WITHOUT per-peer cleanup (the host is shutting down). */\n clear: () => void\n /** Run `stop` once on {@link clear}, when the host shuts down. */\n onClear: (stop: () => void) => void\n size: () => number\n /** Fan a host signal out to every ready peer (terminal output only to its viewers), refreshing presence on the signals that change it. A streaming delta may be held for the rest of this event-loop turn (see the module header). */\n broadcast: (signal: HostSignal) => void\n /** Send the held streaming delta now, if any. */\n flush: () => void\n /**\n * Fan out to every handshaken peer except `origin`. Draft signals use\n * this so a window's own keystrokes never bounce back and fight its\n * cursor — echo-safety by construction, no client-side dedupe.\n */\n broadcastExcept: (origin: HostPeer | null, signal: HostSignal) => void\n computePresence: () => SessionPresence[]\n broadcastPresence: () => void\n /**\n * Late-bound: the broadcast sink exists before the host (the environment\n * the host is built on needs it), and presence reads the host only once a\n * signal arrives.\n */\n bindHost: (host: PresenceSource) => void\n}\n\ntype PresenceSource = Pick<ChatHost, 'approvals' | 'interactions' | 'listLiveSessions'>\n\nexport interface PeerRegistryOptions {\n /** Numbers a signal on its way to every peer (`SignalLog.record`); `json` serializes it (once, shared with the peers). */\n sequence?: (signal: HostSignal, json: () => string | undefined) => number | undefined\n}\n\n/** The fields a delta event may carry and still be coalesced. */\nconst DELTA_FIELDS: ReadonlySet<string> = new Set(['kind', 'text', 'streaming', 'turnId', 'childId', 'depth'])\n\ntype DeltaSignal = Extract<HostSignal, { kind: 'event' }>\n\n/**\n * What a streaming delta coalesces under (session, kind, owner, depth,\n * turn), or `null` when the signal is not a plain delta. Two consecutive\n * deltas with the same key give the client reducers (`appendMarkdownDelta`,\n * `appendThinkingLines` in `src/chat/streaming-pure.ts`) the same rows as\n * one delta with both texts: markdown appends the text, thinking splits it\n * on `\\n` into the owner's last row and new rows after it.\n */\nfunction deltaKey(signal: HostSignal): string | null {\n if (signal.kind !== 'event')\n return null\n const event = signal.event as { kind: string, text?: unknown, streaming?: unknown, turnId?: unknown, childId?: unknown, depth?: unknown }\n if (event.kind === 'markdown' ? event.streaming !== true : event.kind !== 'thinking')\n return null\n if (typeof event.text !== 'string')\n return null\n for (const key in signal) {\n if (key !== 'kind' && key !== 'sessionId' && key !== 'event')\n return null\n }\n for (const key in event) {\n if (!DELTA_FIELDS.has(key))\n return null\n }\n return JSON.stringify([signal.sessionId, event.kind, event.streaming ?? null, event.childId ?? null, event.depth ?? null, event.turnId ?? null])\n}\n\nexport function createPeerRegistry(options: PeerRegistryOptions = {}): PeerRegistry {\n const peers = new Set<HostPeer>()\n let boundHost: PresenceSource | null = null\n const closeCleanups: Array<(peer: HostPeer) => void> = []\n const clearListeners: Array<() => void> = []\n\n /** Sessions with a run in flight, tracked from the run signals themselves. */\n const runningSessions = new Set<string>()\n\n /** The held delta: one slot, so deltas of different owners never change order. */\n let held: { key: string, signal: DeltaSignal, copied: boolean } | null = null\n let flushArmed = false\n\n const flush = (): void => {\n const pending = held\n if (!pending)\n return\n held = null\n emit(pending.signal)\n }\n\n const broadcast = (signal: HostSignal): void => {\n const key = deltaKey(signal)\n if (key !== null && held?.key === key) {\n const delta = signal as DeltaSignal\n if (!held.copied) {\n // The caller's object stays as it was.\n held.signal = { ...held.signal, event: { ...held.signal.event } }\n held.copied = true\n }\n const event = held.signal.event as { text: string }\n event.text += (delta.event as { text: string }).text\n return\n }\n flush()\n if (key === null) {\n emit(signal)\n return\n }\n held = { key, signal: signal as DeltaSignal, copied: false }\n if (!flushArmed) {\n flushArmed = true\n setImmediate(() => {\n flushArmed = false\n flush()\n })\n }\n }\n\n function emit(signal: HostSignal): void {\n // Terminal output only goes where the terminal is shown.\n if (signal.kind === 'terminal:output' || signal.kind === 'terminal:reset') {\n const encoded = encodeSignal(signal)\n for (const peer of peers) {\n if (peer.ready && peer.terminalViews?.has(signal.terminalId))\n peer.send(signal, undefined, encoded)\n }\n return\n }\n // Numbered only here: what every peer gets is what a reattaching one can be replayed.\n fanOut(null, signal, true)\n /*\n * Presence piggybacks on the signals that change it — run state and\n * HITL queues — so the snapshot stays fresh without instrumenting the\n * host. `presence:changed` itself is emitted via `broadcastExcept`\n * directly, so this cannot recurse.\n */\n switch (signal.kind) {\n case 'run:start':\n // Signal-tracked rather than read off `agent.isRunning`: the host\n // broadcasts `run:start` BEFORE invoking `agent.run()`, so the\n // flag lags the signal by a tick.\n runningSessions.add(signal.sessionId)\n broadcastPresence()\n break\n case 'run:end':\n runningSessions.delete(signal.sessionId)\n broadcastPresence()\n break\n case 'approval:request':\n case 'approval:resolved':\n case 'interaction:request':\n case 'interaction:resolved':\n broadcastPresence()\n break\n default:\n break\n }\n }\n\n /** Serialized once here, for the log and every peer. */\n function fanOut(origin: HostPeer | null, signal: HostSignal, numbered: boolean): void {\n const encoded = encodeSignal(signal)\n const seq = numbered ? options.sequence?.(signal, encoded.json) : undefined\n for (const peer of peers) {\n if (!peer.ready || peer === origin)\n continue\n peer.send(signal, seq, encoded)\n }\n }\n\n function broadcastExcept(origin: HostPeer | null, signal: HostSignal): void {\n flush()\n fanOut(origin, signal, false)\n }\n\n /**\n * Live presence: which sessions have attached windows, and their\n * run / awaiting-input state. Union of watched, live-agent, and\n * pending-HITL sessions — small by construction.\n */\n function computePresence(): SessionPresence[] {\n const host = boundHost\n if (!host)\n throw new Error('Presence read before the host was bound.')\n const windowCounts = new Map<string, number>()\n for (const peer of peers) {\n if (peer.ready && peer.watching)\n windowCounts.set(peer.watching, (windowCounts.get(peer.watching) ?? 0) + 1)\n }\n\n const attention = new Set<string>()\n for (const request of host.approvals.listPending())\n attention.add(request.sessionId)\n for (const pending of host.interactions.list())\n attention.add(pending.sessionId)\n\n // Union of signal-tracked runs (fresh) and the agent flag (covers a\n // window attaching to a daemon whose run started before it connected).\n const live = new Map(host.listLiveSessions().map(entry => [entry.sessionId, entry.running]))\n\n const ids = new Set<string>([...windowCounts.keys(), ...attention, ...live.keys(), ...runningSessions])\n return [...ids].map(sessionId => ({\n sessionId,\n windows: windowCounts.get(sessionId) ?? 0,\n running: runningSessions.has(sessionId) || live.get(sessionId) === true,\n attention: attention.has(sessionId),\n }))\n }\n\n function broadcastPresence(): void {\n broadcastExcept(null, { kind: 'presence:changed', sessions: computePresence() })\n }\n\n return {\n add(peer) {\n flush()\n peers.add(peer)\n },\n has: peer => peers.has(peer),\n remove(peer) {\n flush()\n if (!peers.delete(peer))\n return\n for (const cleanup of closeCleanups)\n cleanup(peer)\n // The window detached: its session may have left the \"active\" set.\n if (peer.watching)\n broadcastPresence()\n },\n onClose(cleanup) {\n closeCleanups.push(cleanup)\n },\n clear() {\n flush()\n peers.clear()\n for (const stop of clearListeners.splice(0))\n stop()\n },\n onClear(stop) {\n clearListeners.push(stop)\n },\n size: () => peers.size,\n broadcast,\n flush,\n broadcastExcept,\n computePresence,\n broadcastPresence,\n bindHost(host) {\n boundHost = host\n },\n }\n}\n","/**\n * What each authenticated principal (a zidane-server token id) set going on\n * this host: the sessions it drove (prompts, queued and steered messages,\n * orchestration) and the terminals it opened. Revoking the token stops them\n * (`stop`): a leaked token's agent runs and shells must not outlive its\n * revocation. A process they left running in the background (`nohup`, a\n * daemonized server) is out of reach: only a restart of the host ends it.\n *\n * A driven session is claimed before its method runs (`claim`), so a\n * revocation landing mid-call (a `chat.send` still provisioning) finds it;\n * the rest is recorded after a method succeeded, from its params or result.\n * Work a revoked principal's call left behind once it resolves is stopped\n * there and then. Stopping is per session, not per run: a session another\n * token also drives has its run in flight interrupted and its whole queue\n * dropped, whichever token started that run or queued those messages (the\n * host does not say who started a run, and a leaked token's run must not\n * survive because another device steered it). Peers without a principal (the unix socket, an auth-less\n * loopback server) record nothing. A deleted session's id stays until its\n * token is revoked or the host restarts: nothing runs there, so `stop`\n * passes over it.\n */\nimport type { ChatHost } from '../../chat/host/engine'\nimport type { HostPeer } from './peers'\n\n/** Methods that drive a session's agent: `params.sessionId` names the session. */\nconst DRIVING: ReadonlySet<string> = new Set([\n 'chat.send',\n 'chat.pushQueued',\n 'chat.steer',\n 'chat.followUp',\n 'queue.add',\n 'queue.pushNow',\n 'orchestration.send',\n 'orchestration.steer',\n])\n\n/** What `stop` ended: sessions whose run or background work it stopped, terminals it closed. */\nexport interface StoppedWork {\n runs: number\n terminals: number\n}\n\nexport interface PrincipalWork {\n /** Run `peer`'s call of `method`, noting the session it drives (before the call) or the terminal it opened (after). Returns the call's result. */\n track: (method: string, params: unknown, peer: HostPeer, call: () => unknown) => Promise<unknown>\n /** Drop the queued messages, interrupt the runs, cancel the background work and close the terminals `principal` started, then forget it. */\n stop: (principal: string) => Promise<StoppedWork>\n}\n\ntype WorkHost = Pick<ChatHost, 'isSessionRunning' | 'interrupt' | 'listRunningWork' | 'cancelRunningWork' | 'queueList' | 'queueRemove' | 'terminals'>\n\nexport function createPrincipalWork(host: WorkHost): PrincipalWork {\n const sessions = new Map<string, Set<string>>()\n const terminals = new Map<string, Set<string>>()\n /** Principals already stopped: a call of theirs still in flight is stopped when it resolves. */\n const revoked = new Set<string>()\n\n const add = (map: Map<string, Set<string>>, principal: string, id: string): void => {\n let ids = map.get(principal)\n if (!ids)\n map.set(principal, ids = new Set())\n ids.add(id)\n }\n\n const forgetTerminal = (terminalId: string): void => {\n for (const ids of terminals.values())\n ids.delete(terminalId)\n }\n\n /**\n * Drop the session's queue first: an interrupted run's end drains it, and\n * the next entry would start a fresh run. The whole queue goes, whoever\n * queued each entry: the wire does not say which entries a principal added.\n * Likewise the run in flight is interrupted whoever started it.\n * Returns whether a run, queued messages or background work were stopped.\n */\n const stopSession = async (sessionId: string): Promise<boolean> => {\n const queued = host.queueList(sessionId)\n for (const item of queued)\n host.queueRemove(sessionId, item.id)\n const running = host.isSessionRunning(sessionId)\n const background = host.listRunningWork(sessionId).length > 0\n if (running)\n host.interrupt(sessionId)\n if (background)\n await host.cancelRunningWork(sessionId, 'all', 'The token that started it was revoked.').catch(() => false)\n return running || background || queued.length > 0\n }\n\n const closeTerminal = async (terminalId: string): Promise<boolean> => {\n try {\n await host.terminals.close(terminalId)\n return true\n }\n catch {\n // Already gone, or its shell would not die: the others still close.\n return false\n }\n }\n\n /** Before the call: a revocation landing while it runs (a `chat.send` still provisioning) finds the session. */\n const claim = (method: string, params: unknown, peer: HostPeer): void => {\n const principal = peer.principal\n const sessionId = (params as { sessionId?: unknown } | null)?.sessionId\n if (principal !== undefined && !revoked.has(principal) && DRIVING.has(method) && typeof sessionId === 'string')\n add(sessions, principal, sessionId)\n }\n\n /** After the call succeeded; a principal revoked meanwhile has what it left behind stopped now. */\n const record = (method: string, params: unknown, result: unknown, peer: HostPeer): void => {\n const principal = peer.principal\n if (principal === undefined)\n return\n const p = (params ?? {}) as { sessionId?: unknown, terminalId?: unknown }\n const opened = (result as { id?: unknown } | null)?.id\n const late = revoked.has(principal)\n if (DRIVING.has(method) && typeof p.sessionId === 'string') {\n if (late)\n void stopSession(p.sessionId).catch(() => false)\n else\n add(sessions, principal, p.sessionId)\n }\n else if (method === 'orchestration.createWorker' && typeof result === 'string') {\n if (late)\n void stopSession(result).catch(() => false)\n else\n add(sessions, principal, result)\n }\n else if (method === 'terminal.open' && typeof opened === 'string') {\n if (late)\n void closeTerminal(opened)\n else\n add(terminals, principal, opened)\n }\n else if (method === 'terminal.close' && typeof p.terminalId === 'string') {\n forgetTerminal(p.terminalId)\n }\n }\n\n return {\n async track(method, params, peer, call) {\n claim(method, params, peer)\n const result = await call()\n record(method, params, result, peer)\n return result\n },\n\n async stop(principal) {\n revoked.add(principal)\n const driven = sessions.get(principal) ?? new Set<string>()\n const opened = terminals.get(principal) ?? new Set<string>()\n sessions.delete(principal)\n terminals.delete(principal)\n let runs = 0\n for (const sessionId of driven) {\n if (await stopSession(sessionId))\n runs++\n }\n let closed = 0\n for (const terminalId of opened) {\n if (await closeTerminal(terminalId))\n closed++\n }\n return { runs, terminals: closed }\n },\n }\n}\n","/**\n * Per-session signal numbering and the bounded replay log behind\n * `sessions.resume`.\n *\n * Every session-scoped signal the host fans out to all peers gets the next\n * number of its session (from 1), and the last ones are kept as JSON, so a\n * client that dropped and reattached can be sent exactly what it missed\n * instead of reloading the whole transcript. Signals with no session, and\n * the origin-excluded or viewer-only ones that never go through the full\n * fan-out (drafts, search, suggestions, terminal output), are not numbered.\n *\n * Bounds: per session the last `maxSignals` signals and at most `maxBytes`\n * of them; across sessions `maxTotalBytes`, past which the least recently\n * written session loses its log. Sizes are UTF-8 bytes of the JSON plus\n * {@link ENTRY_OVERHEAD_BYTES} per entry. The bytes are the real bound: a\n * streamed reply is many small signals, and a count bound low enough to bind\n * first would cover less than the time a client needs to notice a dropped\n * connection and come back (`maxSignals` is only a backstop). A\n * position the log no longer covers (or that is not a non-negative integer)\n * is a gap: the client falls back to `sessions.loadEvents`.\n *\n * Numbering survives eviction and `forget`, so a stale position can never\n * pass for a fresh one. A forgotten session keeps only its next number, in\n * a map bounded by `maxForgotten` (least recently forgotten go first); an\n * evicted counter raises a floor every new log starts from, so a number is\n * never given out twice in one epoch, at the cost of new sessions'\n * numbering not starting at 1 once that happened.\n *\n * `epoch` names this log: numbers mean nothing to another host process.\n */\nimport type { HostSignal, SequencedSignal } from '../protocol'\nimport { Buffer } from 'node:buffer'\nimport { randomUUID } from 'node:crypto'\n\n/** What one kept entry costs beyond its JSON (the entry object, its slot), counted against the byte bounds. */\nexport const ENTRY_OVERHEAD_BYTES = 64\n\nexport interface SignalLogOptions {\n /** Default 100 000: past the byte bounds for any realistic signal size. */\n maxSignals?: number\n /** Default 4 MiB. */\n maxBytes?: number\n /** Default 32 MiB. */\n maxTotalBytes?: number\n /** Forgotten sessions whose counters are kept. Default 10 000. */\n maxForgotten?: number\n}\n\nexport interface SignalLog {\n readonly epoch: string\n /**\n * The signal's number in its session, or `undefined` when it is not\n * session-scoped. `serialize` gives its JSON (`undefined`: it cannot be\n * encoded), so a caller that encodes it anyway does it once; default\n * `JSON.stringify`.\n */\n record: (signal: HostSignal, serialize?: () => string | undefined) => number | undefined\n /** Every signal of `sessionId` after `afterSeq`, in order; `null` when the log does not cover them all. */\n replay: (sessionId: string, afterSeq: number) => SequencedSignal[] | null\n /** The session is gone: drop its log (its numbering stays). */\n forget: (sessionId: string) => void\n /** Sessions tracked (live logs and forgotten counters): bounded by `maxForgotten` plus live sessions. */\n sessionCount: () => number\n}\n\ninterface Entry {\n seq: number\n json: string\n bytes: number\n}\n\ninterface SessionLog {\n /** Number the next signal gets. */\n next: number\n entries: Entry[]\n /** Index of the oldest kept entry. */\n head: number\n bytes: number\n}\n\nfunction stringify(signal: HostSignal): string | undefined {\n try {\n return JSON.stringify(signal)\n }\n catch {\n return undefined\n }\n}\n\nfunction sessionOf(signal: HostSignal): string | undefined {\n const id = (signal as { sessionId?: unknown }).sessionId\n return typeof id === 'string' ? id : undefined\n}\n\nexport function createSignalLog(options: SignalLogOptions = {}): SignalLog {\n const maxSignals = options.maxSignals ?? 100_000\n const maxBytes = options.maxBytes ?? 4 * 1024 * 1024\n const maxTotalBytes = options.maxTotalBytes ?? 32 * 1024 * 1024\n const maxForgotten = options.maxForgotten ?? 10_000\n const epoch = randomUUID()\n /** Insertion order = least recently written first. */\n const logs = new Map<string, SessionLog>()\n /** Next number of forgotten sessions; insertion order = least recently forgotten first. */\n const forgotten = new Map<string, number>()\n /** Every number below this may have been given out by a session whose counter is gone. */\n let floor = 1\n let totalBytes = 0\n\n const dropOldest = (log: SessionLog): void => {\n totalBytes -= log.entries[log.head]!.bytes\n log.bytes -= log.entries[log.head]!.bytes\n log.head++\n if (log.head > 1024 && log.head * 2 > log.entries.length) {\n log.entries = log.entries.slice(log.head)\n log.head = 0\n }\n }\n\n const clear = (log: SessionLog): void => {\n totalBytes -= log.bytes\n log.entries = []\n log.head = 0\n log.bytes = 0\n }\n\n return {\n epoch,\n record(signal, serialize = () => stringify(signal)) {\n const sessionId = sessionOf(signal)\n if (sessionId === undefined)\n return undefined\n let log = logs.get(sessionId)\n if (log) {\n logs.delete(sessionId)\n }\n else {\n log = { next: forgotten.get(sessionId) ?? floor, entries: [], head: 0, bytes: 0 }\n forgotten.delete(sessionId)\n }\n logs.set(sessionId, log)\n\n const seq = log.next++\n const json = serialize()\n if (json === undefined) {\n // Not JSON-able, so no peer can receive it either: a hole the log cannot replay.\n clear(log)\n return seq\n }\n const bytes = Buffer.byteLength(json) + ENTRY_OVERHEAD_BYTES\n log.entries.push({ seq, json, bytes })\n log.bytes += bytes\n totalBytes += bytes\n while (log.entries.length - log.head > maxSignals || (log.bytes > maxBytes && log.entries.length - log.head > 0))\n dropOldest(log)\n for (const [id, other] of logs) {\n if (totalBytes <= maxTotalBytes || id === sessionId)\n break\n clear(other)\n }\n return seq\n },\n replay(sessionId, afterSeq) {\n const log = logs.get(sessionId)\n if (!log || !Number.isSafeInteger(afterSeq) || afterSeq < 0)\n return null\n const last = log.next - 1\n if (afterSeq > last || afterSeq < 0)\n return null\n if (afterSeq === last)\n return []\n const first = log.entries[log.head]?.seq\n if (first === undefined || first > afterSeq + 1)\n return null\n const out: SequencedSignal[] = []\n for (let i = log.head; i < log.entries.length; i++) {\n const entry = log.entries[i]!\n if (entry.seq > afterSeq)\n out.push({ seq: entry.seq, signal: JSON.parse(entry.json) as HostSignal })\n }\n return out\n },\n forget(sessionId) {\n const log = logs.get(sessionId)\n if (!log)\n return\n clear(log)\n logs.delete(sessionId)\n forgotten.set(sessionId, log.next)\n while (forgotten.size > maxForgotten) {\n const [oldest, next] = forgotten.entries().next().value!\n forgotten.delete(oldest)\n floor = Math.max(floor, next)\n }\n },\n sessionCount: () => logs.size + forgotten.size,\n }\n}\n","import type { WorkspaceConfinement } from '../../chat/workspace-confinement'\nimport type { FsDirEntry, FsDirListing, FsDirSearch, FsRoots } from '../protocol'\n/**\n * The folders a host lets sessions use, as `fs.*` lists them: the host's own\n * confinement (`ChatHost.workspace`, `src/chat/workspace-confinement.ts`,\n * which the host enforces at its entry points), plus the folder listing,\n * folder creation and folder search, each kept inside the roots. A\n * server is confined to its workspace roots; a local host is not, and its\n * listing root is the user's home, like the window's own folder picker.\n */\nimport { existsSync, mkdirSync, readdirSync, realpathSync, statSync } from 'node:fs'\nimport { readdir } from 'node:fs/promises'\nimport { dirname, join } from 'node:path'\nimport { isInside } from '../../chat/workspace-confinement'\n\n/** Most folders one listing returns. */\nconst MAX_DIR_ENTRIES = 2000\n\n/** How deep a folder search goes below where it starts. */\nexport const SEARCH_MAX_DEPTH = 4\n/** Most folders one search returns. */\nexport const SEARCH_MAX_RESULTS = 200\n/** Most folders one search reads, so a huge tree answers in bounded time. */\nconst SEARCH_MAX_READS = 5000\n/** Folders a search never enters: dependency trees, not projects. */\nconst SEARCH_SKIP = new Set(['node_modules'])\n\n/** A folder name a client may create: one path segment, not hidden, no control characters. */\nfunction checkFolderName(name: string): string {\n const trimmed = name.trim()\n if (!trimmed)\n throw new Error('A folder name is required.')\n if (trimmed.length > 255)\n throw new Error('That folder name is too long.')\n // eslint-disable-next-line no-control-regex -- refusing control characters is the point\n if (/[/\\\\\\u0000-\\u001F]/.test(trimmed))\n throw new Error('A folder name cannot hold \"/\", \"\\\\\" or control characters.')\n if (trimmed.startsWith('.'))\n throw new Error('A folder name cannot start with a dot.')\n return trimmed\n}\n\n/** Exact name first, then a name that starts with the query, then the rest; shallow before deep. */\nfunction searchRank(entry: FsDirEntry, query: string, depth: number): number {\n const name = entry.name.toLowerCase()\n const kind = name === query ? 0 : name.startsWith(query) ? 1 : 2\n return kind * 100 + depth\n}\n\nexport interface WorkspaceRoots {\n describe: () => FsRoots\n /** The real path of `path` when it is a folder inside the roots; throws otherwise. */\n resolveFolder: (path: string) => string\n /** A new session's folder: `cwd` checked when confined, the first root when confined and empty. */\n sessionFolder: (cwd: string) => string\n /** A folder a running session moves to (`setFolder`, launch override): checked when confined; `''` passes. */\n checkFolder: (cwd: string) => string\n list: (path?: string) => FsDirListing\n /** Creates folder `name` in `parent` (inside the roots); throws when it exists or the name is not one plain segment. */\n mkdir: (parent: string, name: string) => FsDirEntry\n /** The folders whose name holds `query`, in `path` (default: every root) and below, within the search bounds. */\n search: (query: string, path?: string) => Promise<FsDirSearch>\n}\n\nexport function createWorkspaceRoots(confinement: WorkspaceConfinement): WorkspaceRoots {\n const { confined, roots, resolveFolder } = confinement\n return {\n describe: () => ({ roots: [...roots], confined }),\n resolveFolder,\n checkFolder: confinement.checkFolder,\n sessionFolder: confinement.sessionFolder,\n list(path) {\n const dir = resolveFolder(path ?? roots[0]!)\n const entries: FsDirEntry[] = []\n let truncated = false\n const names = readdirSync(dir, { withFileTypes: true })\n .filter(e => !e.name.startsWith('.') && (e.isDirectory() || e.isSymbolicLink()))\n .map(e => e.name)\n .sort((a, b) => a.localeCompare(b))\n for (const name of names) {\n let real: string\n try {\n // Canonical, as the confinement's roots are (`../../chat/workspace-confinement`).\n real = realpathSync.native(join(dir, name))\n if (!statSync(real).isDirectory())\n continue\n }\n catch {\n continue\n }\n // A symlink out of the roots is not offered (it would be refused anyway).\n if (!roots.some(root => isInside(root, real)))\n continue\n if (entries.length >= MAX_DIR_ENTRIES) {\n truncated = true\n break\n }\n entries.push({ name, path: real, isGitRepo: existsSync(join(real, '.git')) })\n }\n const atRoot = roots.includes(dir)\n return { roots: [...roots], path: dir, parent: atRoot ? null : dirname(dir), entries, ...(truncated ? { truncated } : {}) }\n },\n mkdir(parent, name) {\n const dir = resolveFolder(parent)\n const folder = checkFolderName(name)\n const target = join(dir, folder)\n try {\n mkdirSync(target)\n }\n catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'EEXIST')\n throw new Error(`${folder} already exists in ${dir}.`)\n throw err\n }\n return { name: folder, path: realpathSync.native(target), isGitRepo: false }\n },\n async search(query, path) {\n const needle = query.trim().toLowerCase()\n if (!needle)\n return { results: [] }\n const starts = path === undefined ? [...roots] : [resolveFolder(path)]\n const found: { entry: FsDirEntry, depth: number }[] = []\n const seen = new Set<string>()\n let reads = 0\n let truncated = false\n // Breadth first: a shallow match is found before the bounds cut a deep one.\n let level = starts.map(dir => ({ dir, depth: 0 }))\n while (level.length > 0) {\n const next: typeof level = []\n for (const { dir, depth } of level) {\n if (reads >= SEARCH_MAX_READS) {\n truncated = true\n break\n }\n reads++\n let dirents\n try {\n dirents = await readdir(dir, { withFileTypes: true })\n }\n catch {\n continue\n }\n // Symlinks are not followed: no loops, no way out of the roots.\n for (const dirent of dirents) {\n if (!dirent.isDirectory() || dirent.name.startsWith('.') || SEARCH_SKIP.has(dirent.name))\n continue\n const child = join(dir, dirent.name)\n if (seen.has(child))\n continue\n seen.add(child)\n if (dirent.name.toLowerCase().includes(needle))\n found.push({ entry: { name: dirent.name, path: child, isGitRepo: existsSync(join(child, '.git')) }, depth })\n if (depth + 1 < SEARCH_MAX_DEPTH)\n next.push({ dir: child, depth: depth + 1 })\n }\n }\n if (reads >= SEARCH_MAX_READS) {\n if (next.length > 0)\n truncated = true\n break\n }\n level = next\n }\n found.sort((a, b) => searchRank(a.entry, needle, a.depth) - searchRank(b.entry, needle, b.depth) || a.entry.path.localeCompare(b.entry.path))\n if (found.length > SEARCH_MAX_RESULTS)\n truncated = true\n const results = found.slice(0, SEARCH_MAX_RESULTS).map(f => f.entry)\n return { results, ...(truncated ? { truncated } : {}) }\n },\n }\n}\n","/**\n * Transport-free JSON-RPC dispatch around a `ChatHost`.\n *\n * Owns everything a host connection needs that is NOT the wire: the typed\n * method table, per-peer state (presence, terminal views, browser hosts,\n * terminal viewers), signal fan-out, the shared draft / search / suggest\n * state, and the `ipc.hello` handshake. A transport (the unix-socket server\n * in `server.ts`, the WebSocket server in `../transports/ws-server.ts`, the\n * in-memory one in `../memory.ts`) only frames messages and hands each\n * connection over as a {@link HostPeer} whose `send` delivers signals.\n *\n * Lifecycle that belongs to the process (draining, retiring once idle) stays\n * with the transport and reaches in through {@link DispatcherLifecycle}.\n *\n * This module is the composition root: peers and fan-out live in\n * `./peers`, each feature's methods (and the per-session or per-peer state\n * only they touch) in `./handlers/<feature>`.\n */\nimport type { ChatHost } from '../../chat/host/engine'\nimport type { RingBufferSink } from '../../logger'\nimport type { HelloParams, HelloResult, HostKind, HostSignal, IpcMethodName } from '../protocol'\nimport type { ClientScope } from '../scopes'\nimport type { DaemonEnvironment } from './environment'\nimport type { RemoteInstallsOptions } from './handlers/catalog-install'\nimport type { MediaTicketRegistry } from './handlers/files'\nimport type { MachineLinksHandlerOptions } from './handlers/machine-links'\nimport type { MachineServeOptions } from './handlers/machine-serve'\nimport type { ServerTokensControl, ServerUpdateControl } from './handlers/server'\nimport type { SyncOptions } from './handlers/sync'\nimport type { MethodTable } from './handlers/types'\nimport type { HostIdentityOptions } from './identity'\nimport type { HostPeer } from './peers'\nimport type { StoppedWork } from './principal-work'\nimport type { SignalLogOptions } from './signal-log'\nimport { dirname } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { AcpErrorCode } from '../../acp/types'\nimport { createChatHost } from '../../chat/host/engine'\nimport { createFileMcpCredentialStore } from '../../chat/mcp-credentials'\nimport { createMcpStatusTracker } from '../../chat/mcp-status'\nimport { SYNC_CATEGORIES } from '../../chat/sync/types'\nimport { ZIDANE_VERSION } from '../../version'\nimport { createHostTranscriptPager } from '../history/index'\nimport { IPC_MIN_PROTOCOL_VERSION, IPC_PROTOCOL_VERSION, IpcErrorCode, MachineErrorCode, PING_METHOD } from '../protocol'\nimport { METHOD_SCOPES, methodScope, scopeAllows } from '../scopes'\nimport { createDaemonEnvironment } from './environment'\nimport { createArtifactHandlers } from './handlers/artifacts'\nimport { createAuthHandlers, createProviderAuth } from './handlers/auth'\nimport { createBrowserHandlers } from './handlers/browser'\nimport { createCatalogInstallHandlers, remoteInstallsAllowed } from './handlers/catalog-install'\nimport { createCatalogHandlers } from './handlers/catalogs'\nimport { createChatHandlers } from './handlers/chat'\nimport { createClientStateHandlers } from './handlers/client-state'\nimport { createContextHandlers } from './handlers/context'\nimport { createDaemonHandlers } from './handlers/daemon'\nimport { createDraftHandlers } from './handlers/drafts'\nimport { createEnvironmentHandlers } from './handlers/environments'\nimport { createExtensionUiHandlers } from './handlers/extension-ui'\nimport { createExtensionHandlers } from './handlers/extensions'\nimport { createFilesHandlers } from './handlers/files'\nimport { createFsHandlers } from './handlers/fs'\nimport { createGitHandlers } from './handlers/git'\nimport { createHistoryHandlers } from './handlers/history'\nimport { createHitlHandlers } from './handlers/hitl'\nimport { createLaunchOverrideHandlers } from './handlers/launch-overrides'\nimport { createMachineLinkHandlers } from './handlers/machine-links'\nimport { createMachineServeHandlers } from './handlers/machine-serve'\nimport { createMachineHandlers } from './handlers/machines'\nimport { createOAuthFlowHandlers } from './handlers/oauth-flows'\nimport { createOnboardingHandlers } from './handlers/onboarding'\nimport { createOrchestrationHandlers } from './handlers/orchestration'\nimport { createPanelHandlers } from './handlers/panels'\nimport { checkParams, InvalidParamsError } from './handlers/params'\nimport { createPerfHandlers, lazyHostPerf } from './handlers/perf'\nimport { createPresenceHandlers } from './handlers/presence'\nimport { createQueueHandlers } from './handlers/queue'\nimport { createResumeHandlers } from './handlers/resume'\nimport { createServerHandlers } from './handlers/server'\nimport { createSessionReadHandlers } from './handlers/session-reads'\nimport { createSessionHandlers } from './handlers/sessions'\nimport { createSettingsHandlers } from './handlers/settings'\nimport { createSuggestHandlers } from './handlers/suggest'\nimport { createSyncHandlers, withSyncOverrides } from './handlers/sync'\nimport { createTerminalHandlers } from './handlers/terminal'\nimport { createTitleHandlers } from './handlers/titles'\nimport { createTodoHandlers } from './handlers/todos'\nimport { createTranscriptHandlers } from './handlers/transcript'\nimport { createUsageHandlers } from './handlers/usage'\nimport { createWorkspaceHandlers } from './handlers/workspace'\nimport { createWorkspaceExecStreamHandlers } from './handlers/workspace-exec-stream'\nimport { evaluateHello } from './handshake'\nimport { resolveHostIdentity } from './identity'\nimport { IPC_BUILD_ID } from './lifecycle'\nimport { createPeerRegistry } from './peers'\nimport { createPrincipalWork } from './principal-work'\nimport { sendDedupFor } from './send-requests'\nimport { createSignalLog } from './signal-log'\nimport { createWorkspaceRoots } from './workspace-roots'\n\n/** Codes a machine error keeps over the wire (`MachineErrorCode`). */\nconst MACHINE_ERROR_CODES: ReadonlySet<number> = new Set(Object.values(MachineErrorCode))\n/** Terminals without a session: only hosts that advertise `HelloResult.projectTerminals` answer them. */\nconst PROJECT_TERMINAL_METHODS: ReadonlySet<string> = new Set(['terminal.projectState', 'terminal.openInProject', 'terminal.adopt', 'terminal.releaseDraft'])\n\nexport type { HostPeer } from './peers'\n\n/** Process lifecycle the transport owns; the dispatcher only asks for it. */\nexport interface DispatcherLifecycle {\n /** `daemon.shutdown`: drain and exit once the reply is out. */\n shutdown: () => void\n /** A newer client found this host mid-work: keep serving, exit at the first idle point. */\n retireWhenIdle: () => void\n isRetiring: () => boolean\n}\n\nexport interface HostDispatcherOptions {\n /**\n * Environment factory: the production daemon uses the disk-backed\n * `createDaemonEnvironment`; tests inject an in-memory one. Receives the\n * broadcast sink wired to peer fan-out.\n */\n createEnvironment?: (broadcast: (signal: HostSignal) => void) => DaemonEnvironment | Promise<DaemonEnvironment>\n appVersion: string\n startedAt: number\n lifecycle: DispatcherLifecycle\n /**\n * What this host reports itself as in `ipc.hello` / `daemon.info`; the id\n * comes from the environment's data dir. Default: a `daemon` named after\n * the machine.\n */\n identity?: HostIdentityOptions\n /** Bounds of the per-session replay log `sessions.resume` reads (`./signal-log`). */\n replay?: SignalLogOptions\n /**\n * Lend this host as a machine to its clients' hosts (`machine.attach`,\n * `docs/MACHINES.md` § Reverse direction). A zidane-server's\n * `allowAsMachine`; absent: refused.\n */\n machineServe?: MachineServeOptions\n /** Its token store, for clients (`tokens.*`): a zidane-server's. Absent: refused. */\n tokens?: ServerTokensControl\n /** The tickets its media are served under (`files.mediaTicket`): a zidane-server's. Absent: refused. */\n media?: MediaTicketRegistry\n /** A zidane-server's self-update (`server.update.*`); read per call, set once it started. */\n update?: () => ServerUpdateControl | null\n /** Pacing of this host's machine links (tests shrink it). */\n machineLinks?: MachineLinksHandlerOptions['pacing']\n /** How long an `auth.oauth.*` sign-in waits for its code. Default 10 minutes. */\n oauthFlowTtlMs?: number\n /** It serves `SERVER_OAUTH_CALLBACK_PATH` (a zidane-server, `deliverOAuthCallback`): a browser client's MCP sign-in may come back there. */\n oauthCallback?: boolean\n /** Its log buffer, for clients (`logs.*`): a zidane-server's. Absent: refused. */\n logs?: RingBufferSink\n /**\n * Installs and removals from clients (`catalog.install` / `remove` /\n * `update`, `mcp.upsert` / `remove`): a zidane-server's `allowRemoteInstalls`\n * and its audit log. Absent: refused.\n */\n remoteInstalls?: RemoteInstallsOptions\n /**\n * Settings sync from a client's computer (`sync.*`): a zidane-server's\n * sync record and audit. Absent: refused.\n */\n sync?: SyncOptions\n /**\n * Workspace writes from clients: cloning (`git.clone`) and creating\n * folders (`fs.mkdir`) in the workspace roots. A zidane-server's\n * `allowClone` and `allowCreateFolders`. Absent: both allowed (the user's\n * own computer).\n */\n workspaceWrites?: WorkspaceWritesOptions\n /**\n * A call refused because the connection's token doesn't reach the method\n * (`../scopes`): a zidane-server writes it to its audit log.\n */\n onForbidden?: (peer: HostPeer, method: string, required: ClientScope) => void\n /**\n * Leave resuming the runs a dead process left to {@link HostDispatcher.resumeAfterRestart}:\n * a host that starts channels calls it once they are connected, so a\n * resumed run's events reach their conversation. Absent: resumed at once.\n */\n deferResume?: boolean\n}\n\n/** Which workspace writes a host takes from its clients, read per call. */\nexport interface WorkspaceWritesOptions {\n /** `git.clone`. */\n clone: () => boolean\n /** `fs.mkdir`. */\n createFolders: () => boolean\n}\n\n/** The workspace writes a host takes, read per call; both allowed without options (the user's own computer). */\nfunction workspaceWritesOf(options: WorkspaceWritesOptions | undefined) {\n const clone = (): boolean => options?.clone() ?? true\n const createFolders = (): boolean => options?.createFolders() ?? true\n return { clone, createFolders, flags: () => ({ clone: clone(), createFolders: createFolders() }) }\n}\n\n/** What the hello says this host offers its clients. */\nfunction hostOffers(options: HostDispatcherOptions, machineServe: boolean, writes: { clone: boolean, createFolders: boolean }): Partial<HelloResult> {\n return {\n ...(machineServe ? { machineServe: true } : {}),\n ...(remoteInstallsAllowed(options.remoteInstalls) ? { remoteInstalls: true } : {}),\n ...writes,\n ...(options.sync ? { sync: true, syncCategories: [...SYNC_CATEGORIES] } : {}),\n }\n}\n\n/** A request's outcome, ready for the transport to frame as a JSON-RPC response. */\nexport type DispatchOutcome\n = | { ok: true, result: unknown }\n | { ok: false, code: number, message: string, data?: unknown }\n\nexport interface HostDispatcher {\n host: ChatHost\n addPeer: (peer: HostPeer) => void\n /** The peer's connection ended: release what it registered and refresh presence. */\n removePeer: (peer: HostPeer) => void\n /** Forget every peer WITHOUT per-peer cleanup, and stop watching the settings file (the host is shutting down). */\n detachAll: () => void\n peerCount: () => number\n handleRequest: (method: string, params: unknown, peer: HostPeer) => Promise<DispatchOutcome>\n /** Resume the runs a dead process left (a host serving every window); see `HostDispatcherOptions.deferResume`. Only the first call does anything. */\n resumeAfterRestart: () => void\n /** Fire-and-forget: no response, errors swallowed, ignored before the handshake. */\n handleNotification: (method: string, params: unknown, peer: HostPeer) => Promise<void>\n /**\n * A principal's credential was revoked (a zidane-server token): interrupt\n * the runs, cancel the background work and close the terminals its peers\n * started (`./principal-work`).\n */\n stopPrincipalWork: (principal: string) => Promise<StoppedWork>\n /** The browser came back to the server's OAuth callback with this query: the MCP server it signs in to, `undefined` when no sign-in waits for it. */\n deliverOAuthCallback: (query: URLSearchParams) => string | undefined\n}\n\n/**\n * The refusal of a call the peer's token doesn't reach (`../scopes`), reported to `onForbidden`;\n * `undefined` when it may call. A peer without a grant (a local window) reaches everything; a\n * method outside the protocol's scope table needs `admin` (never wider than the table says).\n */\nfunction forbiddenCall(method: string, peer: HostPeer, onForbidden: HostDispatcherOptions['onForbidden']): DispatchOutcome | undefined {\n if (!peer.grant)\n return undefined\n const required = methodScope(method) ?? 'admin'\n if (scopeAllows(peer.grant, required))\n return undefined\n onForbidden?.(peer, method, required)\n return {\n ok: false,\n code: IpcErrorCode.Forbidden,\n message: `\"${method}\" needs ${required === 'chat' ? 'a' : 'an'} ${required} token; this connection's token is ${peer.grant}.`,\n data: { required, granted: peer.grant },\n }\n}\n\n/**\n * A connection's terms, set on the peer and reported by `ipc.hello`: the protocol version it\n * speaks, its token's scope (absent for a local window) and the methods this host handles\n * within it.\n */\nfunction connectionTerms(peer: HostPeer, negotiated: number, handled: (method: string) => boolean): Pick<HelloResult, 'minProtocolVersion' | 'negotiatedProtocolVersion' | 'scope' | 'methods'> {\n peer.protocolVersion = negotiated\n const methods = (Object.keys(METHOD_SCOPES) as IpcMethodName[])\n .filter(method => handled(method) && (!peer.grant || scopeAllows(peer.grant, METHOD_SCOPES[method])))\n return { minProtocolVersion: IPC_MIN_PROTOCOL_VERSION, negotiatedProtocolVersion: negotiated, ...(peer.grant ? { scope: peer.grant } : {}), methods }\n}\n\n/** Where this module (and, bundled, its sibling chunks) lives. */\nconst OWN_DIR = dirname(fileURLToPath(import.meta.url))\n\n/**\n * A lazy import of this process's own code failed: the files it was started\n * from were replaced on disk (a rebuild, an upgrade) while it ran.\n */\nexport function isReplacedBuildError(err: unknown): boolean {\n const message = err instanceof Error ? err.message : ''\n const missing = /^Cannot find module '([^']+)'/.exec(message)?.[1]\n // A relative chunk (Bun) or a file next to this one (Node resolves the path); a package an extension lacks is not ours.\n return missing !== undefined && (/^\\.{1,2}\\//.test(missing) || missing.startsWith(`${OWN_DIR}/`))\n}\n\nexport const REPLACED_BUILD_MESSAGE = 'zidane was rebuilt or upgraded while its background service ran. The service restarts once no run is active. To restart it now, quit zidane everywhere and reopen it.'\n\n/** A handler's throw, as the outcome its caller gets. */\nfunction failureOutcome(err: unknown, lifecycle: DispatcherLifecycle): DispatchOutcome {\n // Its own code is gone from disk: say so, and hand over to a fresh process at the first idle point.\n if (isReplacedBuildError(err)) {\n lifecycle.retireWhenIdle()\n return { ok: false, code: IpcErrorCode.HandlerFailed, message: REPLACED_BUILD_MESSAGE }\n }\n if (err instanceof InvalidParamsError)\n return { ok: false, code: AcpErrorCode.InvalidParams, message: err.message }\n // A machine error keeps its code: a client tells \"busy, retry\" from \"refused\" by it.\n const code = (err as { code?: unknown } | null)?.code\n if (typeof code === 'number' && MACHINE_ERROR_CODES.has(code))\n return { ok: false, code, message: (err as Error).message }\n // A handler's own scope refusal (`PolicyScopeError`) answers like the dispatcher's: Forbidden, with what it needs.\n if (code === IpcErrorCode.Forbidden) {\n const data = (err as { data?: unknown }).data\n return { ok: false, code, message: (err as Error).message, ...(data !== undefined ? { data } : {}) }\n }\n return { ok: false, code: IpcErrorCode.HandlerFailed, message: err instanceof Error ? err.message : String(err) }\n}\n\n/**\n * What a previous process left pending: approvals, and (for a host serving\n * every window) every session's durable runs a dead process left. An\n * in-process host resumes those per session, when a window opens it.\n */\nfunction recoverAfterRestart(host: ChatHost, kind: HostKind, deferResume: boolean): () => void {\n host.approvals.rehydrate()\n let resumed = kind === 'in-process'\n const resume = (): void => {\n if (resumed)\n return\n resumed = true\n void host.resumePending().catch(() => undefined)\n }\n if (!deferResume)\n resume()\n return resume\n}\n\nexport async function createHostDispatcher(options: HostDispatcherOptions): Promise<HostDispatcher> {\n const { appVersion, startedAt, lifecycle } = options\n\n const signalLog = createSignalLog(options.replay)\n // Paged transcripts, off this thread when the store is a SQLite file (the worker ends with the host).\n const transcripts = createHostTranscriptPager()\n // Every numbered signal passes here: the ones following a session change drop its cached replay.\n const peers = createPeerRegistry({ sequence: (signal, json) => {\n transcripts.observe(signal)\n return signalLog.record(signal, json)\n } })\n peers.onClear(transcripts.close)\n const { broadcast, broadcastExcept } = peers\n\n const env = await (options.createEnvironment\n ? options.createEnvironment(broadcast)\n : createDaemonEnvironment({ broadcast }))\n const host = createChatHost(env)\n peers.bindHost(host)\n\n const store = env.store\n const identity = resolveHostIdentity(env.userDataDir(), options.identity ?? { kind: 'daemon' })\n const identityFields = { ...(identity.id ? { hostId: identity.id } : {}), hostKind: identity.kind, hostName: identity.name }\n\n // The host's own confinement (it checks it at its entry points); `fs.*` lists with it.\n const workspace = createWorkspaceRoots(host.workspace)\n const drafts = createDraftHandlers({ broadcastExcept })\n const suggest = createSuggestHandlers({ env, broadcastExcept })\n const launchOverrides = createLaunchOverrideHandlers({ host })\n const browser = createBrowserHandlers({ host })\n const terminal = createTerminalHandlers({ host, isConnected: peers.has })\n // Terminals without a session are This computer's (v1): a server answers their methods \"unknown\".\n const projectTerminals = identity.kind !== 'server'\n const execStreams = createWorkspaceExecStreamHandlers({ host, isConnected: peers.has })\n const auth = createProviderAuth({ host, env })\n const mcpStatus = createMcpStatusTracker({ dataDir: () => env.userDataDir(), store: () => env.mcpCredentialStore?.() ?? createFileMcpCredentialStore(env.userDataDir()), onChange: () => broadcast({ kind: 'catalog:changed', catalog: 'mcps' }), onCredentialsChanged: name => host.mcpServers.retire(name) })\n const oauth = createOAuthFlowHandlers({ host, env, auth, mcpStatus, isConnected: peers.has, serverCallback: options.oauthCallback === true, ...(options.oauthFlowTtlMs !== undefined ? { ttlMs: options.oauthFlowTtlMs } : {}) })\n const settings = createSettingsHandlers({ host, env, broadcast, onClose: peers.onClear })\n const installs = createCatalogInstallHandlers({ host, env, broadcast, setSettings: patch => settings['settings.set']({ patch }, null as unknown as HostPeer), ...(options.remoteInstalls ? { options: options.remoteInstalls } : {}) })\n const authHandlers = createAuthHandlers({ auth })\n const sync = createSyncHandlers({\n host,\n env,\n broadcast,\n auth,\n setters: {\n setSettings: patch => settings['settings.set']({ patch }, null as unknown as HostPeer) as unknown as Record<string, unknown>,\n install: (p, peer) => installs['catalog.install'](p, peer),\n mcpUpsert: (p, peer) => installs['mcp.upsert'](p, peer),\n mcpRemove: (p, peer) => installs['mcp.remove'](p, peer),\n setApiKey: p => authHandlers['auth.setApiKey'](p, null as unknown as HostPeer),\n },\n ...(options.sync ? { options: options.sync } : {}),\n })\n const { markOverrides, ...syncMethods } = sync\n const principalWork = createPrincipalWork(host)\n const writes = workspaceWritesOf(options.workspaceWrites)\n const machineServe = createMachineServeHandlers({ host, dataDir: () => env.userDataDir(), hostName: identity.name, settings: () => env.readSettings(), isConnected: peers.has, ...(options.machineServe ? { options: options.machineServe } : {}) })\n\n // Peer-close cleanup, in this order: browser hosts, terminal viewers and views, launch overrides, a lent machine.\n for (const release of [browser.releasePeer, terminal.releasePeer, launchOverrides.releasePeer, machineServe.releasePeer, execStreams.releasePeer, oauth.releasePeer])\n peers.onClose(release)\n\n const forgetSession = (sessionId: string): void => {\n drafts.forget(sessionId)\n launchOverrides.forget(sessionId)\n suggest.forget(sessionId)\n signalLog.forget(sessionId)\n transcripts.forget(sessionId)\n }\n\n /*\n * Exhaustive by `satisfies`: every `IpcMethodName` MUST have a handler\n * (compile error otherwise), each pinned to its `IpcMethods` signature\n * by the slice it comes from (see `./handlers/types`).\n */\n const methods = {\n ...createChatHandlers({ host, clearDraft: drafts.clearDraft, dedup: sendDedupFor(store) }),\n ...createQueueHandlers({ host, clearDraft: drafts.clearDraft, dedup: sendDedupFor(store) }),\n ...drafts.methods,\n ...suggest.methods,\n ...createExtensionHandlers({ env, broadcastExcept }),\n ...launchOverrides.methods,\n ...createSessionHandlers({ host, store, broadcast, forgetSession, hostId: identity.id, workspace }),\n ...createTitleHandlers({ host, broadcast }),\n ...createSessionReadHandlers({ host, store, snapshots: transcripts.replays }),\n ...createTranscriptHandlers({ host, store, broadcast, pages: transcripts }),\n ...createResumeHandlers({ log: signalLog }),\n ...createContextHandlers({ host }),\n ...createEnvironmentHandlers({ host, env, setSettings: settings['settings.set'] }),\n ...createWorkspaceHandlers({ host }),\n ...execStreams.methods,\n ...createGitHandlers({ host, store, workspace, isConnected: peers.has, onClose: peers.onClose, clone: writes.clone }),\n ...createFilesHandlers({ workspace, onClose: peers.onClose, ...(options.media ? { media: options.media } : {}) }),\n ...createFsHandlers({ workspace, environments: () => Promise.resolve(host.listEnvironments('')), createFolders: writes.createFolders, allows: () => ({ remoteInstalls: remoteInstallsAllowed(options.remoteInstalls), asMachine: machineServe.allowed(), sync: Boolean(options.sync), ...writes.flags() }) }),\n ...authHandlers,\n ...oauth.methods,\n ...installs,\n ...createCatalogHandlers({ env, host, mcpStatus }),\n ...createClientStateHandlers({ env }),\n ...createExtensionUiHandlers({ host, env }),\n ...createPanelHandlers({ host, env, store, onClose: peers.onClose }),\n ...createOnboardingHandlers({ host, env, broadcast, ...(options.remoteInstalls ? { installs: options.remoteInstalls } : {}) }),\n ...createArtifactHandlers({ store, broadcast, env, host }),\n ...createUsageHandlers({ store, scan: transcripts.usage, dataDir: () => env.userDataDir(), providers: () => env.config.providers }),\n ...createHistoryHandlers({ host, store }),\n ...createTodoHandlers({ host, store }),\n ...createOrchestrationHandlers({ host }),\n ...createHitlHandlers({ host, store, userDataDir: () => env.userDataDir() }),\n ...browser.methods,\n ...terminal.methods,\n ...settings,\n ...createPresenceHandlers({ env, peers }),\n ...createMachineHandlers({ host, broadcast }),\n ...machineServe.methods,\n ...createMachineLinkHandlers({ host, env, broadcast, hostId: identity.id, server: identity.kind === 'server', appVersion, ...(options.machineLinks ? { pacing: options.machineLinks } : {}) }),\n ...createPerfHandlers({ perf: lazyHostPerf({ kind: identity.kind, host, store }), onPeerClose: peers.onClose, onShutdown: peers.onClear }),\n ...createServerHandlers({ broadcast, onClose: peers.onClear, onPeerClose: peers.onClose, ...(options.logs ? { logs: options.logs } : {}), ...(options.tokens ? { tokens: options.tokens } : {}), ...(options.update ? { update: options.update } : {}) }),\n ...createDaemonHandlers({ host, appVersion, startedAt, lifecycle, identity: identityFields }),\n ...syncMethods,\n // A window's edit of a field the sync source set makes it a server override.\n ...(options.sync\n ? withSyncOverrides({\n 'settings.set': settings['settings.set'],\n 'mcp.upsert': installs['mcp.upsert'],\n 'mcp.remove': installs['mcp.remove'],\n 'catalog.remove': installs['catalog.remove'],\n 'catalog.update': installs['catalog.update'],\n ...authHandlers,\n }, { readSettings: () => env.readSettings(), markOverrides })\n : {}),\n } satisfies MethodTable\n\n /**\n * Widened view for the string-keyed lookup: the table is typed exhaustively\n * above; unknown wire methods fall out here. Own keys only: a wire method\n * named `constructor` / `__proto__` / `toString` is unknown, not a call into\n * `Object.prototype`.\n */\n const handlerFor = (method: string): ((params: unknown, peer: HostPeer) => unknown) | undefined =>\n Object.hasOwn(methods, method) && (projectTerminals || !PROJECT_TERMINAL_METHODS.has(method))\n ? (methods as Partial<Record<string, (params: unknown, peer: HostPeer) => unknown>>)[method]\n : undefined\n\n function hello(params: Partial<HelloParams>, peer: HostPeer): DispatchOutcome {\n const verdict = evaluateHello(params, { buildId: IPC_BUILD_ID, codeVersion: ZIDANE_VERSION, hasActiveWork: host.hasActiveWork(), hostKind: identity.kind })\n if (!verdict.accept) {\n return {\n ok: false,\n code: IpcErrorCode.VersionMismatch,\n message: verdict.message,\n data: { daemon: { protocolVersion: IPC_PROTOCOL_VERSION, appVersion, pid: process.pid, startedAt, buildId: IPC_BUILD_ID, codeVersion: ZIDANE_VERSION, ...identityFields } },\n }\n }\n if (verdict.retire)\n lifecycle.retireWhenIdle()\n peer.ready = true\n const result: HelloResult = {\n protocolVersion: IPC_PROTOCOL_VERSION,\n ...connectionTerms(peer, verdict.protocolVersion, method => handlerFor(method) !== undefined),\n appVersion,\n pid: process.pid,\n startedAt,\n buildId: IPC_BUILD_ID,\n codeVersion: ZIDANE_VERSION,\n ...identityFields,\n signalEpoch: signalLog.epoch,\n ...(lifecycle.isRetiring() ? { retiring: true } : {}),\n ...hostOffers(options, machineServe.allowed(), writes.flags()),\n ...(projectTerminals ? { projectTerminals: true } : {}),\n }\n return { ok: true, result }\n }\n\n async function route(method: string, params: unknown, peer: HostPeer): Promise<DispatchOutcome> {\n // Transport liveness (`../transports/client-core` heartbeat): answered by any host, handshake or not.\n if (method === PING_METHOD)\n return { ok: true, result: {} }\n if (method === 'ipc.hello')\n return hello((params ?? {}) as Partial<HelloParams>, peer)\n\n /*\n * `daemon.shutdown` / `daemon.info` are allowed pre-handshake: a\n * client that just got a VERSION_MISMATCH on `ipc.hello` (so it\n * never became `ready`) still needs to drain this stale daemon\n * before respawning a matching one.\n */\n if (!peer.ready && method !== 'daemon.shutdown' && method !== 'daemon.info')\n return { ok: false, code: IpcErrorCode.NotHandshaken, message: 'Handshake required: send ipc.hello first.' }\n\n const forbidden = forbiddenCall(method, peer, options.onForbidden)\n if (forbidden)\n return forbidden\n\n const handler = handlerFor(method)\n if (!handler && method.startsWith('machine.'))\n return { ok: false, code: MachineErrorCode.MethodNotAllowed, message: `\"${method}\" needs a machine connection (a machine-scoped token); this is a client connection.` }\n if (!handler)\n return { ok: false, code: AcpErrorCode.MethodNotFound, message: `Unknown method \"${method}\".` }\n\n try {\n checkParams(params)\n return { ok: true, result: (await principalWork.track(method, params, peer, () => handler(params, peer))) ?? null }\n }\n catch (err) {\n return failureOutcome(err, lifecycle)\n }\n }\n\n return {\n host,\n addPeer: peers.add,\n removePeer: peers.remove,\n detachAll: peers.clear,\n peerCount: peers.size,\n // What the previous process left (synchronous: nothing above awaited since the host was built).\n resumeAfterRestart: recoverAfterRestart(host, identity.kind, options.deferResume === true),\n\n handleRequest(method, params, peer) {\n // The stream so far goes out first: a handler reads (and a reply follows) every delta emitted before it.\n peers.flush()\n return route(method, params, peer).finally(peers.flush)\n },\n\n /*\n * Notification fast path: fire-and-forget writes with no response\n * bookkeeping. Used for per-keystroke draft sync, where a\n * request/response round-trip per key would be pure overhead.\n * Routed through the SAME handler table as requests; errors are\n * swallowed (there is nowhere to send them) and pre-handshake\n * notifications are ignored.\n */\n async handleNotification(method, params, peer) {\n if (!peer.ready)\n return\n if (forbiddenCall(method, peer, options.onForbidden))\n return\n const handler = handlerFor(method)\n if (!handler)\n return\n try {\n checkParams(params)\n await principalWork.track(method, params, peer, () => handler(params, peer))\n }\n catch {\n // fire-and-forget by contract\n }\n },\n stopPrincipalWork: principalWork.stop,\n deliverOAuthCallback: oauth.deliverCallback,\n }\n}\n","/**\n * Restart the daemon once it is idle after a newer zidane landed on disk.\n *\n * The daemon outlives upgrades: windows restart onto the new build, the\n * daemon keeps running the old one. It watches its own package the same way\n * windows do (`watchInstalledVersion`: the applied marker every install\n * writes, plus a slow poll). Once a newer version is installed it marks\n * itself retiring (`ipc.hello` / `daemon.info` say so) and exits at the\n * first point where it is fully idle: no run, compaction, command or\n * background task, no live terminal, no pending approval or question. Two\n * idle polls in a row, since a queue drain is scheduled just after a\n * dispatch releases and one poll could land in that gap. Windows reconnect\n * on their own and spawn a daemon from the new build.\n *\n * Loop guard: before it exits it records `{ from, to }` in the cache dir. A\n * daemon that starts on `from` again while `to` is still the installed\n * version (the client that respawned it runs an older binary than the one on\n * PATH) does not retire for `to` a second time.\n */\nimport type { CompanionSpec } from '../../chat/auto-update-companion'\nimport type { InstalledVersionState, InstalledVersionWatcher, WatchInstalledVersionOptions } from '../../chat/auto-update-restart'\nimport type { ChatHost } from '../../chat/host/engine'\nimport { mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { watchInstalledVersion } from '../../chat/auto-update-restart'\n\n/** File name of the loop guard inside the cache directory. */\nexport const DAEMON_UPDATE_RESTART_FILE = 'daemon-update-restart.json'\n\n/** The last restart the daemon made for an update. */\nexport interface DaemonUpdateRestartRecord {\n /** Version the daemon ran when it exited. */\n from: string\n /** Installed version it exited for. */\n to: string\n /** ms since epoch. */\n at: number\n}\n\n/** Options for {@link watchDaemonUpdate}. */\nexport interface WatchDaemonUpdateOptions {\n /** The daemon's package, e.g. `{ packageName: 'zidane-tui', binName: 'zidane' }`. */\n spec: CompanionSpec\n /** Version the daemon runs. An empty string turns the watch off. */\n currentVersion: string\n /** Where the applied marker and the loop guard live. */\n cacheDir: string\n /** No runs, compactions, commands, background tasks, live terminals or pending prompts. */\n isIdle: () => boolean\n /** A newer version is installed: the daemon now waits for idle. Called once. */\n onPending?: (version: string) => void\n /** Fully idle with a newer version installed: exit now. Called once. */\n retire: () => void\n /** One diagnostic line per event. */\n log?: (line: string) => void\n /** Idle poll interval. Default 1 s. */\n idlePollMs?: number\n /** Installed-version poll interval, passed to the watcher. Default 5 min. */\n pollMs?: number\n /** Injected for tests. Defaults to {@link watchInstalledVersion}. */\n watch?: (options: WatchInstalledVersionOptions) => InstalledVersionWatcher\n /** Injected for tests. Defaults to `Date.now`. */\n now?: () => number\n}\n\n/** Handle returned by {@link watchDaemonUpdate}. */\nexport interface DaemonUpdateWatch {\n /** The installed version the daemon waits to restart for, or `null`. */\n pending: () => string | null\n /** Stops watching and waiting. */\n close: () => void\n}\n\n/**\n * Nothing a restart would cut short: no run, compaction, command or\n * background task, no live terminal (`hasActiveWork`), and no approval or\n * question waiting for an answer.\n *\n * @param host - The daemon's chat host.\n */\nexport function daemonFullyIdle(host: Pick<ChatHost, 'hasActiveWork' | 'interactions'>): boolean {\n return !host.hasActiveWork() && host.interactions.list().length === 0\n}\n\n/**\n * Reads the loop guard. `null` when there is none or it does not parse.\n *\n * @param cacheDir - Directory that holds the record.\n */\nexport function readDaemonUpdateRestart(cacheDir: string): DaemonUpdateRestartRecord | null {\n try {\n const raw = JSON.parse(readFileSync(join(cacheDir, DAEMON_UPDATE_RESTART_FILE), 'utf8')) as Partial<DaemonUpdateRestartRecord>\n if (typeof raw.from === 'string' && typeof raw.to === 'string' && typeof raw.at === 'number')\n return { from: raw.from, to: raw.to, at: raw.at }\n return null\n }\n catch {\n return null\n }\n}\n\nfunction writeDaemonUpdateRestart(cacheDir: string, record: DaemonUpdateRestartRecord): void {\n try {\n mkdirSync(cacheDir, { recursive: true })\n writeFileSync(join(cacheDir, DAEMON_UPDATE_RESTART_FILE), `${JSON.stringify(record)}\\n`)\n }\n catch {\n // Without the guard a respawn on the old build may retire once more; never worse.\n }\n}\n\n/**\n * Watches for a newer install of the daemon's own package and calls `retire`\n * at the first fully idle point after one lands.\n *\n * @param options - Package, running version, idle probe and callbacks.\n */\nexport function watchDaemonUpdate(options: WatchDaemonUpdateOptions): DaemonUpdateWatch {\n const log = options.log ?? (() => undefined)\n const now = options.now ?? Date.now\n let pending: string | null = null\n let idleTimer: ReturnType<typeof setInterval> | undefined\n let closed = false\n\n const onState = (state: InstalledVersionState): void => {\n if (closed || pending || !state.restartRequired || !state.installed)\n return\n const guard = readDaemonUpdateRestart(options.cacheDir)\n if (guard && guard.from === options.currentVersion && guard.to === state.installed) {\n log(`[ipc-daemon] zidane ${state.installed} is installed, but a restart for it came back on ${options.currentVersion}; staying up`)\n return\n }\n pending = state.installed\n log(`[ipc-daemon] zidane ${pending} is installed; restarting once idle`)\n options.onPending?.(pending)\n let idlePolls = 0\n idleTimer = setInterval(() => {\n if (!options.isIdle()) {\n idlePolls = 0\n return\n }\n idlePolls += 1\n if (idlePolls < 2)\n return\n clearInterval(idleTimer)\n idleTimer = undefined\n writeDaemonUpdateRestart(options.cacheDir, { from: options.currentVersion, to: pending!, at: now() })\n log(`[ipc-daemon] idle; restarting for zidane ${pending}`)\n options.retire()\n }, options.idlePollMs ?? 1000)\n // Never keep the process alive for this.\n if (typeof idleTimer === 'object' && 'unref' in idleTimer)\n idleTimer.unref()\n }\n\n const watcher = (options.watch ?? watchInstalledVersion)({\n spec: options.spec,\n currentVersion: options.currentVersion,\n cacheDir: options.cacheDir,\n ...(options.pollMs !== undefined ? { pollMs: options.pollMs } : {}),\n onChange: onState,\n })\n onState(watcher.current())\n\n return {\n pending: () => pending,\n close: () => {\n closed = true\n clearInterval(idleTimer)\n watcher.close()\n },\n }\n}\n","/**\n * Unix-socket JSON-RPC server around a `ChatHost`.\n *\n * One `net.Server`, one JSON-RPC connection per peer (NDJSON framing: a\n * `net.Socket` is both the Readable and the Writable). The method table,\n * per-peer state, signal fan-out and the `ipc.hello` handshake live in the\n * transport-free dispatcher (`./dispatcher`); this module owns only what is\n * specific to the socket and the process: framing, the socket file and its\n * permissions, idle exit, retiring, and draining. Write backpressure (the\n * slow-consumer bound, the reply size) is shared with the WebSocket server\n * (`../transports/send-budget`).\n *\n * Handshake: a peer's first request MUST be `ipc.hello` carrying its\n * protocol version. Mismatched peers get a structured error (code\n * `IpcErrorCode.VersionMismatch`) and can ask the daemon to drain via `daemon.shutdown`\n * before respawning a fresh one.\n */\nimport type { Server, Socket } from 'node:net'\nimport type { JsonRpcConnection } from '../../acp/json-rpc'\nimport type { ChatHost } from '../../chat/host/engine'\nimport type { HostSignal } from '../protocol'\nimport type { HostDispatcher } from './dispatcher'\nimport type { DaemonEnvironment } from './environment'\nimport type { WatchDaemonUpdateOptions } from './update-retire'\nimport { chmodSync, existsSync, mkdirSync, unlinkSync } from 'node:fs'\nimport { createServer } from 'node:net'\nimport { basename, dirname } from 'node:path'\nimport { createJsonRpcConnection } from '../../acp/json-rpc'\nimport { connectIpcClient } from '../client'\nimport { createPacedWriter } from '../transports/paced-writer'\nimport { createRpcPeer, dispatcherHandlers, PEER_WRITE_HIGH_WATERMARK } from '../transports/peer-rpc'\nimport { createPeerSend } from '../transports/send-budget'\nimport { createHostDispatcher } from './dispatcher'\nimport { legacySocketPath, probeSocket } from './lifecycle'\nimport { daemonFullyIdle, watchDaemonUpdate } from './update-retire'\n\n// Canonical home is the protocol module (clients import the codes without\n// pulling the server's module graph); re-exported here for compatibility.\nexport { IpcErrorCode } from '../protocol'\n\n/** Options for {@link startIpcDaemon}. */\nexport interface IpcDaemonOptions {\n /** Path of the unix socket to listen on. Its directory is created with mode 0700 and the socket gets mode 0600. */\n socketPath: string\n /**\n * Environment factory — the production daemon uses the disk-backed\n * `createDaemonEnvironment`; tests inject an in-memory one. Receives the\n * broadcast sink wired to peer fan-out.\n */\n createEnvironment?: (broadcast: (signal: HostSignal) => void) => DaemonEnvironment | Promise<DaemonEnvironment>\n /**\n * zidane version reported in the handshake.\n * @default 'dev'\n */\n appVersion?: string\n /**\n * Milliseconds the daemon may have zero peers and no running session before\n * it calls `onIdle`. Unset or 0: never. Ignored with a shared `dispatcher`.\n */\n idleShutdownMs?: number\n /** Called when the daemon has had no peers for `idleShutdownMs` and no session is active, or when it retires after a newer client attached mid-work. The CLI exits the process; embedded servers ignore it. */\n onIdle?: () => void\n /** Receives one diagnostic line per event, such as peers connecting. */\n onLog?: (line: string) => void\n /**\n * Serve this already-built host instead of creating one: another front-end\n * (zidane-server's WebSocket) serves it too. Its owner drains it and owns\n * its lifecycle, so `createEnvironment`, `appVersion` and the idle options\n * are ignored, and `close()` only closes this socket's connections.\n */\n dispatcher?: HostDispatcher\n /** See `HostDispatcherOptions.deferResume`: the caller calls `dispatcher.resumeAfterRestart()`. Ignored with a shared `dispatcher`. */\n deferResume?: boolean\n /**\n * A peer with more than this of signals queued for sending (it stopped\n * reading) is dropped; it re-attaches and resumes. Replies are bounded by\n * `maxMessageBytes` instead (`../transports/send-budget`). Default\n * `PEER_WRITE_HIGH_WATERMARK` (8 MiB).\n */\n maxBufferedBytes?: number\n /** A bigger reply goes out as an `IpcErrorCode.ResponseTooLarge` error. Default {@link SOCKET_MAX_REPLY_BYTES}. */\n maxMessageBytes?: number\n /**\n * Watch this package for a newer install and restart (close, then\n * `onIdle`) at the first fully idle point after one lands. Only for a\n * daemon run from an installed build. Ignored with a shared `dispatcher`.\n */\n updateWatch?: Pick<WatchDaemonUpdateOptions, 'spec' | 'currentVersion' | 'cacheDir' | 'pollMs' | 'idlePollMs' | 'watch'>\n}\n\n/**\n * Largest reply on the socket by default. Generous: the peer is this user's\n * own window on this machine, and whole-session reads (`sessions.get`) of a\n * long local session with images must keep fitting. The bound is there so\n * one reply cannot grow the write buffer without limit.\n */\nconst SOCKET_MAX_REPLY_BYTES = 256 * 1024 * 1024\n\n/** A running unix-socket daemon. */\nexport interface IpcDaemon {\n /** Path of the socket it listens on. */\n socketPath: string\n /** The chat host it serves. */\n host: ChatHost\n /** The dispatcher it serves, to connect an in-process client to it (`../memory` `connectInProcess`). */\n dispatcher: HostDispatcher\n /** Number of connected peers. */\n peerCount: () => number\n /** Drains the host, disconnects every peer and removes the socket file. Calling it again returns the same promise. With a shared `dispatcher`, the host is left to its owner. */\n close: () => Promise<void>\n}\n\n/** One open socket connection; `close()` ends them all. */\ninterface SocketConnection {\n socket: Socket\n connection: JsonRpcConnection\n}\n\n/**\n * Starts a unix-socket daemon around a chat host. Each peer must open with `ipc.hello`.\n * A stale socket file left by a dead daemon is replaced. Throws when a live daemon already listens on `socketPath`.\n * @param options - Socket path, environment and lifecycle settings.\n * @returns The running daemon.\n * @example\n * ```ts\n * import { startIpcDaemon } from 'zidane/ipc'\n *\n * const daemon = await startIpcDaemon({\n * socketPath: '/tmp/zidane-demo/daemon/ipc.sock',\n * onLog: line => console.log(line),\n * })\n * console.log(daemon.peerCount())\n * await daemon.close()\n * ```\n */\nexport async function startIpcDaemon(options: IpcDaemonOptions): Promise<IpcDaemon> {\n const { socketPath } = options\n const log = options.onLog ?? (() => undefined)\n const startedAt = Date.now()\n const appVersion = options.appVersion ?? 'dev'\n const maxBuffered = options.maxBufferedBytes ?? PEER_WRITE_HIGH_WATERMARK\n const maxMessage = options.maxMessageBytes ?? SOCKET_MAX_REPLY_BYTES\n\n const connections = new Set<SocketConnection>()\n let idleTimer: ReturnType<typeof setTimeout> | undefined\n // See `retireWhenIdle`.\n let retiring = false\n /** A newer zidane is installed and `./update-retire` waits for full idle; separate so `retireWhenIdle` still arms. */\n let updatePending = false\n let retireTimer: ReturnType<typeof setInterval> | undefined\n\n const shared = options.dispatcher\n const dispatcher = shared ?? await createHostDispatcher({\n ...(options.createEnvironment ? { createEnvironment: options.createEnvironment } : {}),\n appVersion,\n startedAt,\n identity: { kind: 'daemon' },\n ...(options.deferResume ? { deferResume: true } : {}),\n lifecycle: {\n shutdown: () => {\n void close().then(() => options.onIdle?.())\n },\n retireWhenIdle,\n isRetiring: () => retiring || updatePending,\n },\n })\n const host = dispatcher.host\n\n /* ----------------------------------------------------------------------\n * Socket plumbing\n * -------------------------------------------------------------------- */\n\n /*\n * Retire-when-idle: a NEWER client found this daemon mid-work. Draining\n * now would abort every window's runs (a dev edit under `src/ipc` or an\n * upgrade mid-`/review` did exactly that), so keep serving and exit at\n * the first idle point. Two consecutive idle polls: a queue drain is\n * scheduled just after a dispatch releases, and one poll could land in\n * that gap.\n */\n function retireWhenIdle(): void {\n if (retiring)\n return\n retiring = true\n log('[ipc-daemon] a newer client attached mid-work; retiring once idle')\n let idlePolls = 0\n retireTimer = setInterval(() => {\n if (host.hasActiveWork()) {\n idlePolls = 0\n return\n }\n idlePolls += 1\n if (idlePolls < 2)\n return\n clearInterval(retireTimer)\n void close().then(() => options.onIdle?.())\n }, 1000)\n }\n\n // A newer zidane on disk: retire like above, but only once fully idle (`./update-retire`).\n const updates = options.updateWatch && !shared\n ? watchDaemonUpdate({ ...options.updateWatch, isIdle: () => daemonFullyIdle(host), onPending: () => { updatePending = true }, retire: () => void close().then(() => options.onIdle?.()), log })\n : null\n\n function armIdleTimer(): void {\n if (shared || !options.idleShutdownMs || !options.onIdle)\n return\n clearTimeout(idleTimer)\n idleTimer = setTimeout(() => {\n if (dispatcher.peerCount() > 0)\n return // Peers reconnected — the next last-disconnect re-arms.\n /*\n * Never abort a live run just because every window detached — `/exit`\n * is explicitly \"the run keeps going\". Re-arm and check again later.\n */\n if (host.hasActiveWork()) {\n armIdleTimer()\n return\n }\n options.onIdle?.()\n }, options.idleShutdownMs)\n }\n\n function handleConnection(socket: Socket): void {\n // Assigned right below; a signal can only reach this peer after `ipc.hello`, i.e. once it is set.\n let connection: JsonRpcConnection | undefined\n const writer = createPacedWriter(socket)\n const budget = createPeerSend(\n {\n buffered: writer.buffered,\n // NDJSON: `JSON.stringify` escapes newlines, so a message is one line.\n write: (json) => {\n writer.write(`${json}\\n`)\n return true\n },\n },\n {\n maxBuffered,\n maxMessage,\n log,\n label: '[ipc-daemon]',\n stuck: (why) => {\n log(`[ipc-daemon] dropping peer: ${why}`)\n socket.destroy()\n },\n },\n )\n const peer = createRpcPeer({ rpc: () => connection })\n\n const rpc = createJsonRpcConnection({\n input: socket,\n output: socket,\n send: budget.send,\n ...dispatcherHandlers(dispatcher, peer),\n onError: err => log(`[ipc-daemon] peer error: ${err.message}`),\n })\n\n connection = rpc\n const entry: SocketConnection = { socket, connection: rpc }\n connections.add(entry)\n dispatcher.addPeer(peer)\n rpc.start()\n log(`[ipc-daemon] peer connected (${dispatcher.peerCount()} total)`)\n\n const drop = (): void => {\n if (!connections.delete(entry))\n return\n rpc.close()\n dispatcher.removePeer(peer)\n log(`[ipc-daemon] peer disconnected (${dispatcher.peerCount()} left)`)\n if (dispatcher.peerCount() === 0)\n armIdleTimer()\n }\n\n socket.on('close', drop)\n socket.on('error', drop)\n }\n\n /*\n * Stale-socket recovery: a previous daemon that died without cleanup\n * leaves the socket file behind and `listen` would fail EADDRINUSE.\n * Probe before unlinking so a LIVE daemon is never yanked out from\n * under its peers.\n */\n if (existsSync(socketPath)) {\n if (await probeSocket(socketPath))\n throw new Error(`A zidane daemon is already listening on ${socketPath}.`)\n /*\n * Narrow the concurrent-spawn race: another daemon may have bound the\n * socket between the probe above and the unlink below (each probe is a\n * full connect attempt). Re-probe immediately before unlinking and\n * abort startup if something now answers — never yank a live daemon's\n * socket out from under its peers.\n */\n if (await probeSocket(socketPath))\n throw new Error(`A zidane daemon is already listening on ${socketPath}.`)\n unlinkSync(socketPath)\n }\n /*\n * The daemon speaks an unauthenticated RPC surface that can execute tools\n * as the daemon user — restrict access to the owner. The containing dir\n * is created 0700 (belt) and the socket is chmod'd to 0600 right after\n * `listen` (suspenders) so connectability never depends on ambient umask.\n *\n * `mkdirSync`'s mode only applies on CREATION — a pre-existing dir keeps\n * its old mode. When the dir is the DEDICATED daemon dir (the `daemon/`\n * subdir `defaultSocketPath` uses, or one we created fresh for an\n * explicit socket path) chmod it 0700 explicitly. A shared, pre-existing\n * dir (tests pointing the socket at a tmpdir) is left alone — never\n * tighten a directory that also holds unrelated state.\n */\n const socketDir = dirname(socketPath)\n const dedicatedSocketDir = basename(socketDir) === 'daemon' || !existsSync(socketDir)\n mkdirSync(socketDir, { recursive: true, mode: 0o700 })\n if (dedicatedSocketDir) {\n try {\n chmodSync(socketDir, 0o700)\n }\n catch {\n // Best-effort — mirrors the socket chmod below.\n }\n }\n\n const server: Server = createServer(handleConnection)\n await new Promise<void>((resolvePromise, reject) => {\n server.once('error', reject)\n server.listen(socketPath, () => {\n server.off('error', reject)\n resolvePromise()\n })\n })\n try {\n chmodSync(socketPath, 0o600)\n }\n catch {\n // Best-effort on platforms where socket chmod is a no-op (e.g. some\n // network filesystems); the 0700 dir still constrains access.\n }\n log(`[ipc-daemon] listening on ${socketPath}`)\n // We bound the socket, so we own the file — close() unlinks it exactly\n // once. Cleared after the unlink so a file later re-created by a NEW\n // daemon on the same path is never yanked by a stale close.\n let ownsSocketFile = true\n armIdleTimer()\n\n /*\n * Drain any daemon still serving the legacy socket path\n * (`<stateDir>/daemon.sock`). New clients never probe it,\n * so a `--idle-exit 0` service daemon there would run forever alongside\n * this one — two sets of live agents, run guards, and heartbeat writers\n * against the same sessions.db. Fire-and-forget: version mismatch is\n * the EXPECTED case (a legacy daemon speaks an older protocol) and\n * `drainOnMismatch: true` performs the shutdown for us; a same-version\n * survivor (explicit env overrides) gets an explicit daemon.shutdown.\n */\n const legacyPath = shared ? null : legacySocketPath(socketPath)\n if (legacyPath) {\n void (async () => {\n if (!(await probeSocket(legacyPath)))\n return\n log(`[ipc-daemon] draining legacy daemon on ${legacyPath}`)\n try {\n const survivor = await connectIpcClient({ socketPath: legacyPath, appVersion: `${appVersion}/legacy-drain`, drainOnMismatch: true })\n await survivor.request('daemon.shutdown', {}).catch(() => undefined)\n survivor.close()\n }\n catch {\n // IpcVersionMismatchError = drained by the handshake path; anything\n // else (raced exit, wedged socket) is best-effort — leave it.\n }\n })()\n }\n\n async function doClose(): Promise<void> {\n clearTimeout(idleTimer)\n clearInterval(retireTimer)\n updates?.close()\n // A shared host is its owner's to drain and detach (see `dispatcher`).\n if (!shared)\n await host.drain()\n // Stop accepting before closing what is open: a connection landing in\n // between would otherwise keep `server.close` waiting forever.\n const stopped = new Promise<void>((resolvePromise) => {\n server.close(() => resolvePromise())\n })\n for (const { connection, socket } of connections) {\n connection.close()\n socket.destroy()\n }\n connections.clear()\n if (!shared)\n dispatcher.detachAll()\n await stopped\n if (ownsSocketFile) {\n ownsSocketFile = false\n try {\n unlinkSync(socketPath)\n }\n catch {\n // already gone\n }\n }\n }\n\n /*\n * Idempotent close: `daemon.shutdown` runs close() and then onIdle, whose\n * CLI implementation calls daemon.close() again — both callers share one\n * drain instead of double-unlinking the socket. Memoized rather than\n * flag-guarded so the second caller awaits actual completion.\n */\n let closePromise: Promise<void> | null = null\n function close(): Promise<void> {\n closePromise ??= doClose()\n return closePromise\n }\n\n return {\n socketPath,\n host,\n dispatcher,\n peerCount: () => dispatcher.peerCount(),\n close,\n }\n}\n","/**\n * Login-shell PATH for processes not started from a terminal.\n *\n * A Dock/Finder-launched GUI, or a daemon it spawns, inherits launchd's PATH\n * (`/usr/bin:/bin:/usr/sbin:/sbin`), so `node` / `bun` / `yarn` are invisible\n * to agent shell commands. Ask the user's login shell for its PATH and merge\n * it into `process.env.PATH`.\n *\n * Merge, don't replace: a terminal launch may have prepended entries the rc\n * files know nothing about (`nvm use`, direnv, `PATH=... zidane`), and those\n * must survive. Idempotent, so every surface (GUI, daemon) can call it and a\n * daemon spawned by an already-fixed GUI ends up with the same PATH.\n */\nimport { spawnSync } from 'node:child_process'\nimport { userInfo } from 'node:os'\nimport { delimiter } from 'node:path'\nimport process from 'node:process'\nimport { runBounded } from '../../contexts/run-bounded'\n\nconst DELIMITER = '_ZIDANE_SHELL_ENV_'\n\n/** A slow rc file costs startup time; a prompting one must never hang the process. */\nconst DEFAULT_TIMEOUT_MS = 3_000\n\nfunction defaultShell(env: NodeJS.ProcessEnv): string {\n try {\n const { shell } = userInfo()\n if (shell)\n return shell\n }\n catch {}\n return env.SHELL || (process.platform === 'darwin' ? '/bin/zsh' : '/bin/sh')\n}\n\nfunction parsePath(stdout: string): string | undefined {\n const body = stdout.split(DELIMITER)[1]\n if (body === undefined)\n return undefined\n // eslint-disable-next-line no-control-regex\n const clean = body.replace(/\\u001B\\[[0-9;]*[A-Z]/gi, '')\n for (const line of clean.split('\\n')) {\n if (line.startsWith('PATH='))\n return line.slice('PATH='.length) || undefined\n }\n return undefined\n}\n\n/**\n * Options for {@link shellPath} and {@link shellPathAsync}. Without `shell`,\n * the user's shell is tried first, then POSIX fallbacks for non-POSIX defaults\n * (nushell, xonsh) whose `-ilc` differs. An explicit `shell` is tried alone.\n * `timeoutMs` bounds each shell. Default 3000.\n */\nexport interface ShellPathOptions { env?: NodeJS.ProcessEnv, timeoutMs?: number, shell?: string }\n\n// `command env` sidesteps aliases/functions named `env`.\nconst SHELL_ARGS = ['-ilc', `echo -n \"${DELIMITER}\"; command env; echo -n \"${DELIMITER}\"; exit`]\n\nfunction shellCandidates(options: ShellPathOptions): { shells: string[], env: NodeJS.ProcessEnv, timeout: number } {\n const env = options.env ?? process.env\n return {\n shells: options.shell ? [options.shell] : [...new Set([defaultShell(env), '/bin/zsh', '/bin/bash'])],\n timeout: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n env: {\n ...env,\n // Keep oh-my-zsh from blocking on its update prompt / tmux autostart.\n DISABLE_AUTO_UPDATE: 'true',\n ZSH_TMUX_AUTOSTARTED: 'true',\n ZSH_TMUX_AUTOSTART: 'false',\n },\n }\n}\n\n/**\n * Reads the PATH of the user's interactive login shell, blocking until it answers.\n * Tries the user's shell, then `/bin/zsh` and `/bin/bash`. Returns `undefined` on Windows, or when no shell answers in time.\n * @param options - Shell, environment and timeout overrides.\n * @returns The PATH string, or `undefined`.\n */\nexport function shellPath(options: ShellPathOptions = {}): string | undefined {\n if (process.platform === 'win32')\n return undefined\n const { shells, env, timeout } = shellCandidates(options)\n for (const shell of shells) {\n const result = spawnSync(shell, SHELL_ARGS, {\n encoding: 'utf8',\n timeout,\n stdio: ['ignore', 'pipe', 'ignore'],\n env,\n })\n if (result.error || result.status !== 0)\n continue\n const path = parsePath(result.stdout)\n if (path)\n return path\n }\n return undefined\n}\n\n/**\n * {@link shellPath} without blocking the event loop: same shells, args,\n * timeout and parsing, run with {@link runBounded} (a timeout ends the shell's\n * whole tree; under Bun its output survives a shell that exits before Bun\n * watches it). For hosts (the GUI main process) that can start on a cached\n * PATH and refresh in the background.\n * @param options - Shell, environment and timeout overrides.\n * @returns The PATH string, or `undefined`.\n */\nexport async function shellPathAsync(options: ShellPathOptions = {}): Promise<string | undefined> {\n if (process.platform === 'win32')\n return undefined\n const { shells, env, timeout } = shellCandidates(options)\n for (const shell of shells) {\n const run = await runBounded(shell, SHELL_ARGS, { env, timeoutMs: timeout })\n if (run.code !== 0)\n continue\n const path = parsePath(run.stdout)\n if (path)\n return path\n }\n return undefined\n}\n\n/**\n * Entries of `current` the shell doesn't know about (ad-hoc prepends from the\n * launching terminal) stay in front; then the shell's PATH in its own order.\n * From the Dock every launchd entry is already in the shell PATH, so the\n * result is exactly the shell PATH, with the shell's precedence intact.\n * @param current - The PATH of this process.\n * @param shell - The PATH reported by the login shell.\n * @returns The merged PATH string.\n */\nexport function mergePath(current: string | undefined, shell: string | undefined): string {\n const split = (path: string | undefined): string[] => (path ?? '').split(delimiter).filter(Boolean)\n const fromShell = split(shell)\n const known = new Set(fromShell)\n return [...new Set([...split(current).filter(entry => !known.has(entry)), ...fromShell])].join(delimiter)\n}\n\n/** Merge the login shell's PATH into `process.env.PATH`. No-op on Windows or when no shell answers. */\nexport function fixPath(): void {\n const extra = shellPath()\n if (extra)\n process.env.PATH = mergePath(process.env.PATH, extra)\n}\n","/**\n * In-process transport: the host dispatcher in the window's own process, and\n * `IpcClient`s that call it directly instead of over a unix socket.\n *\n * For a window that runs its own host (TUI local mode on the shared engine):\n * the same dispatcher, method table and signal fan-out a daemon serves, with\n * no socket, no spawn and no second process. A caller sees what a socket\n * client would, so the daemon-mode code paths run on it unchanged:\n * - params, results and signals are JSON copies (as on the wire: a top-level\n * `undefined` result arrives as `null`, nested `undefined` fields are\n * dropped, and nothing is shared between the window and the host);\n * - a failed request rejects with `JsonRpcRemoteError` carrying the\n * dispatcher's code; a closed connection rejects with\n * `JsonRpcConnectionClosedError`, in-flight requests included;\n * - responses and signals arrive asynchronously, through one queue in the\n * order the host produced them (a socket reads them in write order);\n * - `close()` detaches quietly; the host shutting down calls `onClose`.\n *\n * `connectInProcess` opens the same client on a dispatcher that already\n * serves other transports (a zidane-server's), optionally held to a client\n * scope like a WebSocket peer with that token.\n *\n * Two socket behaviors are deliberately absent. Request deadlines exist on\n * the socket to recover from a wedged daemon by dropping the connection and\n * reconnecting; in-process there is nothing to reconnect to. And\n * `daemon.shutdown` from a client does not stop the host: its lifetime\n * belongs to the embedding window (`InProcessHost.close()`).\n */\nimport type { ChatHost } from '../chat/host/engine'\nimport type { IpcClient } from './client'\nimport type { HostDispatcher, HostPeer } from './daemon/dispatcher'\nimport type { DaemonEnvironment } from './daemon/environment'\nimport type { HelloResult, HostSignal } from './protocol'\nimport type { ClientScope } from './scopes'\nimport type { SignalListener } from './transports/client-core'\nimport { JsonRpcConnectionClosedError, JsonRpcRemoteError } from '../acp/json-rpc'\nimport { ZIDANE_VERSION } from '../version'\nimport { createHostDispatcher } from './daemon/dispatcher'\nimport { IPC_BUILD_ID } from './daemon/lifecycle'\nimport { IPC_PROTOCOL_VERSION } from './protocol'\n\n/** Options for {@link startInProcessHost}. */\nexport interface InProcessHostOptions {\n /** The host's environment, given the broadcast sink wired to client fan-out. */\n createEnvironment: (broadcast: (signal: HostSignal) => void) => DaemonEnvironment | Promise<DaemonEnvironment>\n /** Reported to clients as the host's `appVersion`. */\n appVersion?: string\n}\n\n/** Options for {@link InProcessHost.connect}. */\nexport interface InProcessClientOptions {\n /** Client version, surfaced in the host's diagnostics. */\n appVersion?: string\n /** Called when the host shuts down under a still-open client. */\n onClose?: () => void\n}\n\n/** Options for {@link connectInProcess}. */\nexport interface InProcessConnectOptions extends InProcessClientOptions {\n /** The client scope the dispatcher holds the client to (`./scopes`). Absent: every method, like a local window. */\n grant?: ClientScope\n}\n\n/** A chat host running in the caller's process, with clients that call it directly. */\nexport interface InProcessHost {\n /** The chat host. */\n host: ChatHost\n /** A new client, already past the `ipc.hello` handshake. */\n connect: (options?: InProcessClientOptions) => Promise<IpcClient>\n /** Number of open clients. */\n peerCount: () => number\n /**\n * Shut the host down: refuse new work, suspend and await every run\n * (`ChatHost.drain`), then close the clients still open (their `onClose`\n * fires). Idempotent.\n */\n close: () => Promise<void>\n}\n\n/** JSON round-trip: what crossing the socket does to a value. */\nfunction wire<T>(value: T): T {\n return value === undefined ? (null as T) : JSON.parse(JSON.stringify(value)) as T\n}\n\n/** One open client, from the host's side. */\ninterface Connection {\n peer: HostPeer\n /** The host is shutting down: reject what is pending, then tell the client. */\n hostClosed: () => void\n}\n\n/**\n * Opens one client on `dispatcher`; `connections` (the in-process host's)\n * tracks it until it closes, so the host can close it when it shuts down.\n */\nasync function openClient(dispatcher: HostDispatcher, options: InProcessConnectOptions, connections?: Set<Connection>): Promise<IpcClient> {\n const listeners = new Set<SignalListener>()\n const pending = new Set<(err: Error) => void>()\n let closed = false\n\n /*\n * Everything bound for the client goes through one FIFO drained in a\n * microtask: signals, and request outcomes once the dispatcher settles\n * them. A signal the host emits after answering a request is therefore\n * delivered after that answer, as a socket would read them.\n */\n const outbox: Array<() => void> = []\n let draining = false\n const deliver = (item: () => void): void => {\n outbox.push(item)\n if (draining)\n return\n draining = true\n queueMicrotask(() => {\n try {\n while (outbox.length > 0) {\n try {\n outbox.shift()!()\n }\n catch {\n // A throwing listener costs that one message, as on the socket\n // (the JSON-RPC reader catches it), never the connection.\n }\n }\n }\n finally {\n draining = false\n }\n })\n }\n\n const peer: HostPeer = {\n ready: false,\n watching: null,\n ...(options.grant ? { grant: options.grant } : {}),\n send(signal, seq, encoded) {\n if (closed)\n return\n const meta = seq === undefined ? undefined : { seq }\n let copy: HostSignal\n try {\n // The fan-out's one serialization, when it has one.\n const json = encoded ? encoded.json() : JSON.stringify(signal)\n if (json === undefined)\n return\n copy = JSON.parse(json) as HostSignal\n }\n catch {\n // Not JSON-able: the socket server drops it the same way, and a\n // bad signal must never break fan-out to the other clients.\n return\n }\n deliver(() => {\n if (closed)\n return\n for (const listener of listeners)\n listener(copy, meta)\n })\n },\n }\n\n const request = (method: string, params: unknown): Promise<unknown> => {\n if (closed)\n return Promise.reject(new JsonRpcConnectionClosedError())\n return new Promise((resolve, reject) => {\n pending.add(reject)\n const settle = (outcome: () => void): void => {\n deliver(() => {\n if (!pending.delete(reject))\n return\n outcome()\n })\n }\n dispatcher.handleRequest(method, params === undefined ? undefined : wire(params), peer).then(\n (result) => {\n settle(() => {\n // The reject is already out of `pending`: a throw here (a result\n // that is not JSON-able) must fail the request, not hang it.\n try {\n if (result.ok)\n resolve(wire(result.result))\n else\n reject(new JsonRpcRemoteError(result.message, result.code, result.data))\n }\n catch (err) {\n reject(err instanceof Error ? err : new Error(String(err)))\n }\n })\n },\n err => settle(() => reject(err)),\n )\n })\n }\n\n /** Stop delivering and fail what is in flight, as a socket closing does. */\n const shut = (): void => {\n closed = true\n listeners.clear()\n outbox.length = 0\n for (const reject of pending)\n reject(new JsonRpcConnectionClosedError())\n pending.clear()\n }\n\n const connection: Connection = {\n peer,\n hostClosed: () => {\n if (closed)\n return\n shut()\n options.onClose?.()\n },\n }\n\n dispatcher.addPeer(peer)\n connections?.add(connection)\n const detach = (): void => {\n if (closed)\n return\n shut()\n connections?.delete(connection)\n dispatcher.removePeer(peer)\n }\n\n let hello: HelloResult\n try {\n hello = await request('ipc.hello', {\n protocolVersion: IPC_PROTOCOL_VERSION,\n appVersion: options.appVersion ?? 'dev',\n pid: process.pid,\n buildId: IPC_BUILD_ID,\n codeVersion: ZIDANE_VERSION,\n }) as HelloResult\n }\n catch (err) {\n detach()\n throw err\n }\n\n return {\n hello,\n request: request as IpcClient['request'],\n notify: (method, params) => {\n if (closed)\n return\n const copy = params === undefined ? undefined : wire(params)\n // Off the caller's stack, as a socket write would be.\n queueMicrotask(() => {\n if (!closed)\n void dispatcher.handleNotification(method, copy, peer)\n })\n },\n onSignal: (listener) => {\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n close: detach,\n }\n}\n\n/**\n * Connects an in-process client to a dispatcher that already runs (a\n * zidane-server's, the daemon's), next to its socket and WebSocket peers.\n * With a `grant`, the dispatcher checks every call against it as it does for\n * a WebSocket peer whose token has that scope (`./scopes`); without one the\n * client reaches every method, like a local window.\n *\n * The dispatcher's owner closes such clients before it stops the host:\n * `onClose` fires only when the in-process host of {@link startInProcessHost}\n * shuts down under one.\n * @param dispatcher - The running dispatcher.\n * @param options - Scope and version.\n * @returns The client, already past the `ipc.hello` handshake.\n */\nexport function connectInProcess(dispatcher: HostDispatcher, options: InProcessConnectOptions = {}): Promise<IpcClient> {\n return openClient(dispatcher, options)\n}\n\n/**\n * Starts a chat host in this process. Clients from `connect` behave like socket clients, without a socket or a second process.\n * @param options - Environment factory and version.\n * @returns The host handle.\n */\nexport async function startInProcessHost(options: InProcessHostOptions): Promise<InProcessHost> {\n const connections = new Set<Connection>()\n let closing: Promise<void> | null = null\n\n const dispatcher = await createHostDispatcher({\n createEnvironment: options.createEnvironment,\n appVersion: options.appVersion ?? 'dev',\n startedAt: Date.now(),\n identity: { kind: 'in-process' },\n lifecycle: {\n // Owned by the embedding window, see the module header.\n shutdown: () => undefined,\n // Clients are this build by construction: never a newer one to retire for.\n retireWhenIdle: () => undefined,\n isRetiring: () => false,\n },\n })\n\n function connect(clientOptions: InProcessClientOptions = {}): Promise<IpcClient> {\n if (closing)\n return Promise.reject(new JsonRpcConnectionClosedError())\n return openClient(dispatcher, clientOptions, connections)\n }\n\n function close(): Promise<void> {\n // Same order as the socket server's shutdown: drain the host, close\n // every connection, then forget the peers without per-peer cleanup.\n closing ??= (async () => {\n await dispatcher.host.drain()\n for (const connection of connections)\n connection.hostClosed()\n connections.clear()\n dispatcher.detachAll()\n })()\n return closing\n }\n\n return {\n host: dispatcher.host,\n connect,\n peerCount: () => dispatcher.peerCount(),\n close,\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"memory-Dj9Eeybi.js","names":["MAX_KEY_LENGTH","DEFAULT_TIMEOUT_MS","NAME_RE","process","isRecord","isRecord","isRecord","process"],"sources":["../src/ipc/transports/paced-writer.ts","../src/ipc/client.ts","../src/ipc/daemon/watch-file.ts","../src/ipc/daemon/environment.ts","../src/ipc/daemon/handlers/machine-links.ts","../src/ipc/daemon/handlers/machines.ts","../src/ipc/transports/peer-rpc.ts","../src/ipc/transports/send-budget.ts","../src/ipc/history/rpc-client.ts","../src/ipc/history/transcript.ts","../src/ipc/daemon/redact.ts","../src/ipc/daemon/catalog-entries.ts","../src/ipc/daemon/handlers/catalogs.ts","../src/ipc/daemon/handlers/artifacts.ts","../src/ipc/daemon/handlers/auth.ts","../src/ipc/daemon/handlers/browser.ts","../src/ipc/daemon/handlers/catalog-install.ts","../src/text-origin.ts","../src/ipc/daemon/send-requests.ts","../src/ipc/daemon/handlers/chat.ts","../src/ipc/daemon/handlers/client-state.ts","../src/ipc/daemon/handlers/context.ts","../src/ipc/daemon/handlers/daemon.ts","../src/ipc/daemon/handlers/drafts.ts","../src/ipc/daemon/handlers/environments.ts","../src/ipc/daemon/handlers/extension-ui.ts","../src/ipc/daemon/handlers/extensions.ts","../src/ipc/daemon/handlers/files.ts","../src/ipc/daemon/handlers/fs.ts","../src/ipc/daemon/handlers/session-policy.ts","../src/ipc/daemon/handlers/sessions.ts","../src/ipc/daemon/handlers/git.ts","../src/ipc/daemon/handlers/history.ts","../src/ipc/daemon/handlers/hitl.ts","../src/ipc/daemon/handlers/launch-overrides.ts","../src/ipc/daemon/handlers/machine-serve.ts","../src/ipc/daemon/handlers/oauth-flows.ts","../src/ipc/daemon/handlers/onboarding.ts","../src/ipc/daemon/handlers/orchestration.ts","../src/ipc/daemon/handlers/panels.ts","../src/ipc/daemon/handlers/perf.ts","../src/ipc/daemon/integrations.ts","../src/ipc/daemon/handlers/integrations.ts","../src/ipc/daemon/handlers/presence.ts","../src/ipc/daemon/handlers/queue.ts","../src/ipc/daemon/handlers/resume.ts","../src/ipc/daemon/handlers/logs.ts","../src/ipc/daemon/handlers/server.ts","../src/ipc/daemon/handlers/session-reads.ts","../src/ipc/daemon/handlers/settings.ts","../src/ipc/daemon/handlers/suggest.ts","../src/ipc/daemon/sync-apply.ts","../src/ipc/daemon/sync-store.ts","../src/ipc/daemon/handlers/sync.ts","../src/ipc/daemon/handlers/terminal.ts","../src/ipc/daemon/handlers/titles.ts","../src/ipc/daemon/handlers/todos.ts","../src/ipc/daemon/handlers/transcript.ts","../src/ipc/daemon/handlers/usage.ts","../src/ipc/daemon/handlers/workspace.ts","../src/ipc/daemon/handlers/workspace-exec-stream.ts","../src/ipc/daemon/handshake.ts","../src/ipc/daemon/identity.ts","../src/ipc/daemon/peers.ts","../src/ipc/daemon/principal-work.ts","../src/ipc/daemon/signal-log.ts","../src/ipc/daemon/workspace-roots.ts","../src/ipc/daemon/dispatcher.ts","../src/ipc/daemon/update-retire.ts","../src/ipc/daemon/server.ts","../src/ipc/daemon/shell-path.ts","../src/ipc/memory.ts"],"sourcesContent":["/**\n * Writes to a socket with backpressure: slices go out while the socket takes\n * them (`write` returns true), the rest waits for `drain`. Messages keep\n * their order, and `buffered` counts what is queued here plus what the\n * socket still holds, so a send budget measuring it sees the whole backlog.\n *\n * Handing a socket one large buffer at once is what this avoids: Bun's\n * `node:net` re-copies the unsent remainder after each partial write, so a\n * 100 MB reply took ~12 s to cross a unix socket, against ~70 ms when paced\n * (Node is fast either way).\n *\n * Small messages written in one go (a fan-out, a reply behind its signals)\n * are joined and handed over as one buffer, from a microtask (so before any\n * I/O), as soon as the socket asks for more, or once they add up to a slice:\n * one encode and one socket write instead of one per message. A large message is not joined: it goes\n * out in slices, after what was written before it.\n */\nimport type { Writable } from 'node:stream'\nimport { Buffer } from 'node:buffer'\n\n/** Largest slice handed to the socket at once. */\nconst SLICE_BYTES = 64 * 1024\n\nexport interface PacedWriter {\n write: (text: string) => void\n /** Bytes not yet handed to the OS: queued here, plus the socket's own buffer. */\n buffered: () => number\n}\n\nexport function createPacedWriter(stream: Writable): PacedWriter {\n const queue: Buffer[] = []\n let queuedBytes = 0\n let waiting = false\n /** Small messages not yet encoded, joined on their way into `queue`. */\n let pending: string[] = []\n let pendingBytes = 0\n let armed = false\n\n const takePending = (): void => {\n if (pending.length === 0)\n return\n const bytes = Buffer.from(pending.length === 1 ? pending[0]! : pending.join(''))\n pending = []\n pendingBytes = 0\n queue.push(bytes)\n queuedBytes += bytes.length\n }\n\n const pump = (): void => {\n waiting = false\n takePending()\n while (queue.length > 0) {\n if (stream.destroyed || stream.writableEnded) {\n queue.length = 0\n queuedBytes = 0\n return\n }\n const head = queue[0]!\n const slice = head.length > SLICE_BYTES ? head.subarray(0, SLICE_BYTES) : head\n if (slice === head)\n queue.shift()\n else\n queue[0] = head.subarray(SLICE_BYTES)\n queuedBytes -= slice.length\n if (!stream.write(slice)) {\n waiting = true\n stream.once('drain', pump)\n return\n }\n }\n }\n\n return {\n write(text) {\n if (text.length >= SLICE_BYTES) {\n takePending()\n const bytes = Buffer.from(text)\n queue.push(bytes)\n queuedBytes += bytes.length\n if (!waiting)\n pump()\n return\n }\n pending.push(text)\n pendingBytes += Buffer.byteLength(text)\n // While the socket is full, `drain` takes them.\n if (waiting)\n return\n if (pendingBytes >= SLICE_BYTES) {\n pump()\n return\n }\n if (armed)\n return\n armed = true\n queueMicrotask(() => {\n armed = false\n if (!waiting)\n pump()\n })\n },\n buffered: () => pendingBytes + queuedBytes + stream.writableLength,\n }\n}\n","/**\n * Typed daemon client — the only thing a zidane window (TUI, attach CLI,\n * GUI main process) needs to talk to a shared chat host.\n *\n * `request` is checked against the `IpcMethods` contract, `onSignal`\n * delivers every `HostSignal` fan-out, and `connectIpcClient` handles the\n * handshake including the protocol-version dance: a mismatched daemon is\n * asked to drain (`daemon.shutdown`) so the caller can respawn a fresh one.\n * The transport-independent half (handshake, deadlines, signals) is shared\n * with the WebSocket client in `./transports/client-core`.\n */\nimport type { Socket } from 'node:net'\nimport type { EnsureDaemonOptions } from './daemon/lifecycle'\nimport type { IpcClient } from './transports/client-core'\nimport { connect } from 'node:net'\nimport { createJsonRpcConnection, errorResponse } from '../acp/json-rpc'\nimport { METHOD_NOT_FOUND } from '../chat/hosts/connection'\nimport { ensureDaemonRunning, probeSocket } from './daemon/lifecycle'\nimport { createSignalListeners, IpcVersionMismatchError, openIpcClient } from './transports/client-core'\nimport { createPacedWriter } from './transports/paced-writer'\n\nexport { type IpcClient, IpcVersionMismatchError } from './transports/client-core'\n\n/** Options for {@link connectIpcClient}. */\nexport interface IpcClientOptions {\n /** Path of the daemon's unix socket. */\n socketPath: string\n /** Client zidane version, surfaced in daemon diagnostics. */\n appVersion?: string\n /** Called when the daemon connection drops (socket close/error). */\n onClose?: () => void\n /**\n * On a version/build mismatch, ask the stale daemon to drain before\n * throwing (default). PASSIVE clients (the presence watcher) must set\n * this false: they retry on a timer, and an old-build window left open\n * across a protocol bump would otherwise drain the NEW daemon in a\n * loop, aborting every other window's runs.\n */\n drainOnMismatch?: boolean\n}\n\n/**\n * Connects to a daemon over its unix socket and completes the `ipc.hello` handshake.\n * On a protocol, build or code version mismatch it throws {@link IpcVersionMismatchError}. Unless `drainOnMismatch` is `false`, it first asks the stale daemon to drain. Rejects when nothing listens on the socket.\n * @param options - Socket path and client settings.\n * @returns A typed client. Requests are checked against {@link IpcMethods}.\n * @example\n * ```ts\n * import { connectIpcClient, defaultSocketPath } from 'zidane/ipc'\n *\n * const client = await connectIpcClient({ socketPath: defaultSocketPath() })\n * const sessions = await client.request('sessions.list', {})\n * const stop = client.onSignal(signal => console.log(signal.kind))\n * console.log(sessions.length)\n * stop()\n * client.close()\n * ```\n */\nexport async function connectIpcClient(options: IpcClientOptions): Promise<IpcClient> {\n const socket: Socket = await new Promise((resolvePromise, reject) => {\n const s = connect(options.socketPath)\n s.once('connect', () => {\n s.off('error', reject)\n resolvePromise(s)\n })\n s.once('error', reject)\n })\n\n const signals = createSignalListeners()\n let closed = false\n\n // A large request (turns with images) goes out paced, as the daemon's replies do.\n const writer = createPacedWriter(socket)\n const connection = createJsonRpcConnection({\n input: socket,\n output: socket,\n send: json => writer.write(`${json}\\n`),\n // The daemon never sends requests to clients — only notifications.\n onRequest: message => errorResponse(message.id, METHOD_NOT_FOUND, 'Clients do not accept requests.'),\n onNotification: signals.onNotification,\n })\n connection.start()\n\n const close = (): void => {\n if (closed)\n return\n closed = true\n connection.close()\n socket.destroy()\n }\n\n socket.on('close', () => {\n if (closed)\n return\n closed = true\n connection.close()\n options.onClose?.()\n })\n socket.on('error', () => {\n // 'close' follows; swallow so an unhandled 'error' doesn't crash us.\n })\n\n const passive = options.drainOnMismatch === false\n return openIpcClient(\n // `abort` destroys the socket (not `close()`), so its 'close' handler fires `onClose`.\n { rpc: connection, close, abort: () => socket.destroy(), where: options.socketPath },\n signals.listeners,\n {\n ...(options.appVersion ? { appVersion: options.appVersion } : {}),\n drain: passive ? 'stale-only' : 'always',\n buildFence: !passive,\n },\n )\n}\n\n/**\n * One-call convenience for windows: make sure a daemon is up (spawning if\n * needed), connect, and — when the running daemon speaks an older protocol\n * — drain it and spawn a fresh one before retrying once.\n * @param options - Client options without `socketPath`, plus the daemon spawn options.\n * @returns A connected client.\n */\nexport async function connectOrSpawnDaemon(\n options: Omit<IpcClientOptions, 'socketPath'> & EnsureDaemonOptions = {},\n): Promise<IpcClient> {\n const socketPath = await ensureDaemonRunning(options)\n try {\n return await connectIpcClient({ ...options, socketPath })\n }\n catch (err) {\n if (!(err instanceof IpcVersionMismatchError))\n throw err\n /*\n * The stale daemon was told to drain by `connectIpcClient`, but\n * `daemon.shutdown` replies BEFORE the socket actually closes (the\n * drain runs on `setImmediate`). Poll until the socket stops\n * accepting connections (bounded) before respawning, so\n * `ensureDaemonRunning` doesn't re-probe the still-listening stale\n * daemon and hit a second mismatch.\n */\n const drainDeadline = Date.now() + 2000\n while (await probeSocket(socketPath)) {\n if (Date.now() > drainDeadline)\n break\n await new Promise(r => setTimeout(r, 100))\n }\n const retryPath = await ensureDaemonRunning(options)\n return connectIpcClient({ ...options, socketPath: retryPath })\n }\n}\n","/**\n * Notice when another process rewrites a file (the settings in `state.json`):\n * a watch on the file, followed to each new file a writer swaps in (writers\n * replace it atomically), plus a slow poll for file systems that send no\n * events. Both compare its modification time and size, so a burst of events\n * from one write calls back once.\n */\n\nimport { statSync, watch } from 'node:fs'\n\n/** Coalesces the events one write produces. */\nconst DEBOUNCE_MS = 100\n/** The fallback poll, when file events are missed. */\nconst POLL_MS = 2_000\n\nfunction stampOf(file: string): string {\n try {\n const stats = statSync(file)\n return `${stats.mtimeMs}:${stats.size}`\n }\n catch {\n return 'missing'\n }\n}\n\n/**\n * Call `onChange` after `file` changes. Returns the function that stops watching.\n *\n * @param file - The file to watch.\n * @param onChange - Called once per change, after its events settle.\n * @param options - Options.\n * @param options.pollMs - The fallback poll interval. Default 2 s.\n * @param options.watch - The file watch: `node:fs`'s by default; tests pass their own.\n */\nexport function watchFileChanges(file: string, onChange: () => void, options: { pollMs?: number, watch?: typeof watch } = {}): () => void {\n let stamp = stampOf(file)\n let pending: ReturnType<typeof setTimeout> | undefined\n let watcher: ReturnType<typeof watch> | undefined\n let stopped = false\n\n const check = (): void => {\n pending = undefined\n const now = stampOf(file)\n if (now === stamp)\n return\n stamp = now\n onChange()\n }\n // One check after a burst of events settles.\n const onEvent = (): void => {\n clearTimeout(pending)\n pending = setTimeout(check, DEBOUNCE_MS)\n pending.unref?.()\n }\n const arm = (): void => {\n watcher?.close()\n watcher = undefined\n if (stopped)\n return\n try {\n watcher = (options.watch ?? watch)(file, (event) => {\n onEvent()\n // The file was replaced: the watch still follows the old one.\n if (event === 'rename')\n arm()\n })\n watcher.on('error', () => undefined)\n watcher.unref()\n }\n catch {\n // No file yet: the poll watches it once it exists.\n }\n }\n\n arm()\n // Leaves a burst to its debounced check.\n const poll = setInterval(() => {\n if (watcher === undefined)\n arm()\n if (pending === undefined)\n check()\n }, options.pollMs ?? POLL_MS)\n poll.unref?.()\n return () => {\n stopped = true\n clearTimeout(pending)\n clearInterval(poll)\n watcher?.close()\n watcher = undefined\n }\n}\n","import type { ChatHostEnvironment, PendingApprovalsStore } from '../../chat/host/environment'\n/**\n * Disk-backed `ChatHostEnvironment` for the zidane daemon.\n *\n * Mirrors the TUI's storage layout so the daemon is a drop-in peer of the\n * terminal process: sessions in `sessions.db` (canonical sqlite store),\n * settings in `state.json`'s `settings` slot, credentials/safelist under the\n * shared user dir, extensions discovered per-cwd with the same allowlist +\n * trust contract every other surface uses.\n */\nimport type { ResolvedConfig } from '../../chat/index'\nimport type { ExtensionBus, ExtensionHostRuntimeBridge } from '../../extensions/index'\nimport type { LogSink } from '../../logger'\nimport type { SessionStore } from '../../session/index'\nimport type { HostSettings, HostSignal, HudState, WireApprovalRequest } from '../protocol'\nimport { existsSync, readFileSync, unlinkSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport { OWNER_ONLY, writeJsonFileAtomic } from '../../atomic-write'\nimport { resolveConfig } from '../../chat/config'\nimport { applyApiKeyEnv, credentialsPath } from '../../chat/credentials'\nimport { createExtensionMcpHost } from '../../chat/extension-mcp-host'\nimport { createMemoryApprovalsStore } from '../../chat/host/approvals'\nimport { createFileMcpCredentialStore } from '../../chat/mcp-credentials'\nimport { BUILTIN_PROVIDERS } from '../../chat/providers'\nimport { enforceSettingsInvariants, SETTINGS_TOGGLES } from '../../chat/settings-catalog'\nimport { DEFAULT_SETTINGS, settingsFromStored, sparseSettingsUpdate } from '../../chat/settings-defaults'\nimport { createExtensionBus, createExtensionHostRuntimeBridge, createExtensionHud, discoverAndBuildExtensionRegistry } from '../../extensions/index'\nimport { consoleSink, createLogger, fanoutSink } from '../../logger'\nimport { watchFileChanges } from './watch-file'\n\n/** The host environment of a daemon or an embedded host: a {@link ChatHostEnvironment} backed by disk, with settings writes and runtime-config control. */\nexport interface DaemonEnvironment extends ChatHostEnvironment {\n /** Merges a patch into the stored settings, drops the `reset` keys it doesn't set, and returns the settings in effect afterwards. */\n writeSettings: (patch: Partial<HostSettings>, reset?: readonly (keyof HostSettings)[]) => HostSettings\n /** The extensions' HUD now, as `hud:state` pushes it (`hud.get`). Absent: an environment without a HUD of its own. */\n hudState?: () => HudState\n /** Drop the per-cwd runtime-config memo (settings changed) and dispose the registries it held. */\n invalidateRuntime: () => void\n /**\n * Drop the memo WITHOUT disposing: the next `runtimeConfig` builds fresh\n * registries while agents still running on the old ones keep working.\n * Returns the disposer for what was dropped; call it once no agent\n * holds those registries (`runtime.reload` after every session rebuilt).\n */\n forgetRuntime: () => () => void\n /** Base config resolved at daemon boot (paths, store, state). */\n config: ResolvedConfig\n /** The config `runtimeConfig(cwd)` already built or is building, without building one. Absent: never known. */\n peekRuntimeConfig?: (cwd: string) => Promise<ResolvedConfig> | undefined\n /**\n * Calls `onChange` after the settings file changes, whoever wrote it (another\n * daemon or window on the same `state.json`). Returns the function that stops\n * watching. Absent when the settings live in no file.\n */\n watchSettings?: (onChange: () => void) => () => void\n /**\n * Shared extension bus for daemon-side registries (`ctx.bus`). The\n * server delivers validated `extension.emit` notifications into it;\n * daemon-side emits leave through its `onEmit` → `broadcast`. Optional:\n * test environments without extensions omit it.\n */\n extensionBus?: ExtensionBus\n}\n\n/**\n * File-backed pending-approvals persistence (`pending-approvals.json` next\n * to `state.json`). Small, rewritten atomically enough for its purpose —\n * the queue holds at most a handful of rows.\n * @param path - Path of the JSON file. A missing or unreadable file reads as empty.\n * @returns A store that persists approvals to that file.\n */\nexport function createFileApprovalsStore(path: string): PendingApprovalsStore {\n function read(): WireApprovalRequest[] {\n if (!existsSync(path))\n return []\n try {\n const parsed = JSON.parse(readFileSync(path, 'utf8'))\n return Array.isArray(parsed) ? (parsed as WireApprovalRequest[]) : []\n }\n catch {\n return []\n }\n }\n\n function write(rows: WireApprovalRequest[]): void {\n if (rows.length === 0) {\n try {\n unlinkSync(path)\n }\n catch {\n // absent already — fine\n }\n return\n }\n // Atomic: this file exists to survive a crash — a torn write would\n // corrupt the very queue we're persisting to recover. Owner-only: rows\n // carry tool inputs (commands, file contents).\n writeJsonFileAtomic(path, rows, OWNER_ONLY)\n }\n\n return {\n insert(request) {\n const rows = read().filter(r => r.id !== request.id)\n rows.push(request)\n write(rows)\n },\n delete(id) {\n write(read().filter(r => r.id !== id))\n },\n clear() {\n write([])\n },\n list() {\n return read()\n },\n }\n}\n\n/** Options for {@link createHostEnvironment}. */\nexport interface HostEnvironmentOptions {\n /** Sink that fans a signal out to every connected client. */\n broadcast: (signal: HostSignal) => void\n /** Turns on verbose stream logging to the host console. */\n debugStream?: boolean\n /** Also receives its extensions' setup and runtime log records (stderr gets the warnings either way). */\n logSink?: LogSink\n /** Daemon only: base cwd for its own boot-time config resolution. Default: `process.cwd()`. */\n cwd?: string\n /**\n * Share the embedding window's setup instead of resolving the daemon's\n * own: a host in the window's process. Absent: the daemon (own config,\n * per-cwd extension discovery, multi-process).\n */\n shared?: SharedHostSetup\n}\n\n/** What a host in the window's own process takes from the window. */\nexport interface SharedHostSetup {\n /**\n * The window's boot config (paths, store, state file): one store and one\n * writer to `state.json` in the process.\n */\n config: ResolvedConfig\n /**\n * The window's per-cwd session config. Discovering extensions here instead\n * would run every extension's `setup` a second time in the same process.\n * `invalidate` / `forget` back `DaemonEnvironment.invalidateRuntime` /\n * `forgetRuntime` (settings changes, `runtime.reload`).\n */\n runtimeConfig: {\n resolve: (cwd: string) => Promise<ResolvedConfig>\n invalidate?: () => void\n forget?: () => () => void\n }\n /** Host-runtime bridge the window's registries were built with (`ChatHostEnvironment.hostRuntime`). */\n hostRuntime?: ExtensionHostRuntimeBridge\n /** The window's extension bus, so `extension.emit` from other clients reaches its extensions. */\n extensionBus?: ExtensionBus\n /** Whether another process also drives these sessions. Default `false` (single writer). */\n multiProcess?: boolean\n /** The window's instrumentation for every agent the host builds (`ChatHostEnvironment.instrumentAgent`). */\n instrumentAgent?: ChatHostEnvironment['instrumentAgent']\n /** Whether the window can show terminals (`ChatHostEnvironment.terminals`). */\n terminals?: boolean\n}\n\n/**\n * The daemon's environment: its own config, per-cwd extension discovery, multi-process.\n * @param options - Broadcast sink and boot settings. `shared` is not accepted.\n * @returns The environment.\n */\nexport function createDaemonEnvironment(options: Omit<HostEnvironmentOptions, 'shared'>): Promise<DaemonEnvironment> {\n return createHostEnvironment(options)\n}\n\n/**\n * Disk-backed host environment: the daemon's, or (with `shared`) a host\n * sharing the window's process and setup.\n * @param options - Broadcast sink, boot settings and the optional shared window setup.\n * @returns The environment.\n */\nexport async function createHostEnvironment(options: HostEnvironmentOptions): Promise<DaemonEnvironment> {\n const { shared } = options\n const config = shared?.config ?? await resolveOwnConfig(options.cwd)\n const store: SessionStore = config.store\n\n /*\n * Project-DB mode resolves storage to a PER-REPO `.zidane/sessions.db`\n * from the boot cwd. A single daemon serving windows opened in different\n * projects would then read/write every session against ONE project's DB.\n * The daemon is a single-store process, so warn loudly rather than\n * silently mixing projects; a project-scoped daemon (own socket) is the\n * supported way to use project-DB mode with the daemon.\n */\n if (!shared && config.paths.projectDir) {\n process.stderr.write(\n `[zidane-daemon] warning: project-DB mode is on, so this daemon uses ${config.paths.db}. `\n + `Windows opened in other projects will share this project's sessions. `\n + `Run a per-project daemon (ZIDANE_DAEMON_SOCKET) to isolate them.\\n`,\n )\n }\n\n /*\n * `config.initialSettings` is `resolveConfig`'s migrated snapshot of the\n * on-disk settings (it went through `settingsFromStored`, which maps the\n * legacy keys). Layering it under the live raw read means a user with\n * legacy-shaped settings gets the SAME effective settings in the daemon\n * as in the TUI, while mid-session writes (live `stateStore`) still win.\n * The live read goes through the same defaults migration, so a value\n * frozen at an old default by an older full-object writer doesn't override it.\n */\n const readSettings = (): HostSettings => ({\n ...DEFAULT_SETTINGS,\n ...config.initialSettings,\n ...settingsFromStored(config.stateStore.load().settings ?? {}),\n })\n\n /**\n * Fields the invariant forced (only ever `false`), so the stored file records\n * them too — otherwise a later read of `state.settings` would resurrect the\n * value the invariant just rejected. A field already `false` before the\n * invariant ran is left out: writing it would freeze a default on disk.\n */\n const pickInvariantFields = (unenforced: HostSettings, merged: HostSettings, patch: Partial<HostSettings>): Partial<HostSettings> => {\n const out: Partial<HostSettings> = {}\n for (const row of SETTINGS_TOGGLES) {\n if (row.requires && merged[row.key] === false && unenforced[row.key] !== false && patch[row.key] !== false)\n out[row.key] = false\n }\n return out\n }\n\n const writeSettings = (patch: Partial<HostSettings>, reset: readonly (keyof HostSettings)[] = []): HostSettings => {\n /*\n * Read-modify-write of the whole `state.json`, synchronous, through the\n * state store. A host in the window's process shares the window's store\n * (`config`), so the two writers interleave whole writes and each keeps\n * the other's fields. Across processes (the daemon and a local-mode\n * window on the same file) nothing locks; in daemon mode the window\n * leaves settings to the daemon and persists only its window-local\n * keys (`WINDOW_LOCAL_SETTINGS`: `useDaemon`, `remoteHosts`).\n */\n const state = config.stateStore.load()\n // Same invariants every writer applies (`orchestration` needs `useDaemon`,\n // …) — enforced on the MERGED view, since a patch can flip a requirement\n // off while the dependent stays true in the stored fields.\n const written = sparseSettingsUpdate(state.settings, patch, reset)\n const unenforced: HostSettings = { ...DEFAULT_SETTINGS, ...config.initialSettings, ...settingsFromStored(written) }\n const merged = enforceSettingsInvariants(unenforced)\n const next = sparseSettingsUpdate(written, pickInvariantFields(unenforced, merged, patch)) as Partial<HostSettings>\n config.stateStore.save({ ...state, settings: next })\n return merged\n }\n\n const userDataDir = (): string => config.paths.userDir\n\n const applyAuthEnv = (): void => {\n const dir = userDataDir()\n process.env.ZIDANE_CREDENTIALS_PATH = credentialsPath(dir)\n // The window's own registry when sharing its config (custom providers);\n // the daemon uses the built-ins.\n applyApiKeyEnv(dir, shared ? config.providers : BUILTIN_PROVIDERS)\n }\n\n /*\n * Daemon-side extension HUD: extension hooks run HERE in daemon mode, so\n * their `ctx.tui` writes need a live bus (headless hosts otherwise no-op\n * them). Every change is forwarded to the windows as `hud:state` /\n * `hud:notify` signals; the TUI overlays them under its local HUD.\n */\n const hud = createExtensionHud()\n const hudState = (): HudState => {\n const state = hud.getState()\n return {\n statuses: Object.fromEntries(\n Object.entries(state.statuses).map(([name, s]) => [name, { text: s.text, loader: s.loader }]),\n ),\n banners: Object.fromEntries(\n Object.entries(state.banners).map(([name, lines]) => [name, [...lines]]),\n ),\n sessions: Object.fromEntries(\n Object.entries(state.sessions).map(([id, byExtension]) => [\n id,\n Object.fromEntries(Object.entries(byExtension).map(([name, s]) => [name, { text: s.text, loader: s.loader }])),\n ]),\n ),\n badges: Object.fromEntries(Object.entries(state.badges).map(([id, list]) => [id, [...list]])),\n }\n }\n hud.subscribe(() => options.broadcast({ kind: 'hud:state', ...hudState() }))\n hud.onNotify((n) => {\n options.broadcast({ kind: 'hud:notify', extension: n.extension, text: n.text, tone: n.tone })\n })\n\n const base = {\n // The daemon serves explicitly-invoked clients (`zidane attach`)\n // even when `useDaemon` is off: a multi-writer surface by\n // construction, so the run guard + heartbeat are not setting-gated.\n // A shared host is single-writer unless told otherwise.\n multiProcess: shared ? shared.multiProcess === true : true,\n hudState,\n broadcast: (signal: HostSignal) => {\n // A deleted session's extension statuses and composer badges go with it.\n if (signal.kind === 'sessions:changed' && signal.op === 'delete')\n hud.clearSession(signal.sessionId)\n options.broadcast(signal)\n },\n store,\n readSettings,\n writeSettings,\n ...(config.stateStore.path ? { watchSettings: (onChange: () => void) => watchFileChanges(config.stateStore.path!, onChange) } : {}),\n userDataDir,\n stateDir: () => config.paths.stateDir,\n /*\n * The host's own log (a shared MCP server's output no session owns): the\n * daemon's stderr, its log file, plus the log sink. A host in the window's\n * process writes only to the sink: stderr there is the window's terminal.\n */\n ...(shared\n ? (options.logSink ? { logger: createLogger(options.logSink) } : {})\n : { logger: createLogger(options.logSink ? fanoutSink([options.logSink, consoleSink()]) : consoleSink()) }),\n applyAuthEnv,\n mcpCredentialStore: () => createFileMcpCredentialStore(userDataDir()),\n /*\n * The daemon persists parked approvals so a restart can re-offer them. A\n * host in the window's process dies with its runs, so it keeps them in\n * memory: the file is the daemon's (same state dir), not its to load or\n * clear.\n */\n approvalsPersistence: shared\n ? createMemoryApprovalsStore()\n : createFileApprovalsStore(join(dirname(config.paths.state), 'pending-approvals.json')),\n ...(options.debugStream !== undefined ? { debugStream: options.debugStream } : {}),\n config,\n }\n\n // The window's per-cwd config: no discovery, HUD or bus of our own;\n // the window's registries own those.\n if (shared) {\n const { resolve, invalidate, forget } = shared.runtimeConfig\n return {\n ...base,\n // Session artifacts where the window's local agent kept them.\n cacheDir: () => config.paths.cacheDir,\n runtimeConfig: resolve,\n ...(shared.hostRuntime ? { hostRuntime: shared.hostRuntime } : {}),\n ...(shared.extensionBus ? { extensionBus: shared.extensionBus } : {}),\n ...(shared.instrumentAgent ? { instrumentAgent: shared.instrumentAgent } : {}),\n ...(shared.terminals !== undefined ? { terminals: shared.terminals } : {}),\n invalidateRuntime: () => invalidate?.(),\n // Same contract as the daemon's: drop now, dispose when the returned\n // disposer runs (once no agent holds the old registries).\n forgetRuntime: () => forget?.() ?? (() => undefined),\n }\n }\n\n /*\n * Per-(cwd + allowlist + trust) runtime-config memo — same invalidation\n * axes the GUI's extension registry cache uses. Dropped wholesale on\n * settings writes that touch extension keys (see the server's\n * `settings.set` handler calling `invalidate`).\n */\n /*\n * Daemon-side extension bus: one bus shared by every per-cwd registry\n * (channels are private per extension id, so sharing is safe — and it\n * lets the server deliver a validated `extension.emit` no matter which\n * cwd's registry claimed the id). Emits from daemon-side extensions\n * already delivered loopback inside the bus; the hook fans the envelope\n * out to every window as `extension:signal`.\n */\n const extensionBus = createExtensionBus()\n extensionBus.onEmit((envelope) => {\n options.broadcast({ kind: 'extension:signal', ...envelope })\n })\n\n /*\n * LRU-bounded: a service-style daemon (`--idle-exit 0`) serving many\n * project folders would otherwise accumulate a full ResolvedConfig +\n * extension registry per (cwd × allowlist) key forever. Map iteration\n * order is insertion order; a cache hit re-inserts to mark recency.\n */\n const RUNTIME_CACHE_MAX = 16\n const runtimeCache = new Map<string, Promise<ResolvedConfig>>()\n\n // One bridge for every registry this daemon builds; the engine scopes the\n // invoking session onto it per command (see `ChatHostEnvironment.hostRuntime`).\n const hostRuntime = createExtensionHostRuntimeBridge()\n\n // `ctx.mcp` (`'mcp:call'` permission): one connection pool for every per-cwd registry.\n const mcpHost = createExtensionMcpHost({\n prefix: config.prefix,\n readSettings,\n credentialStore: () => createFileMcpCredentialStore(userDataDir()),\n })\n\n /**\n * Best-effort release of an evicted entry's extension registry\n * (teardown hooks, HUD writers — `registry.dispose()` is idempotent).\n * Fire-and-forget: eviction must never block or throw on a broken\n * extension teardown, and a rejected resolve has nothing to release.\n */\n const disposeRuntime = (promise: Promise<ResolvedConfig>): void => {\n void promise\n .then(config => config.extensions.dispose())\n .catch(() => undefined)\n }\n\n const runtimeKey = (cwd: string, settings: HostSettings): string => [\n cwd,\n JSON.stringify(settings.enabledExtensions ?? null),\n String(settings.loadProjectExtensions === true),\n ].join('\\u0000')\n\n const runtimeConfig = (cwd: string): Promise<ResolvedConfig> => {\n const settings = readSettings()\n const key = runtimeKey(cwd, settings)\n\n const existing = runtimeCache.get(key)\n if (existing) {\n // Refresh recency.\n runtimeCache.delete(key)\n runtimeCache.set(key, existing)\n return existing\n }\n\n const promise = (async () => {\n const extensionRegistry = await discoverAndBuildExtensionRegistry({\n cwd,\n hud,\n bus: extensionBus,\n hostRuntime,\n mcp: mcpHost,\n prefix: config.prefix,\n ...(settings.enabledExtensions !== undefined ? { enabledAllowlist: [...settings.enabledExtensions] } : {}),\n trustProjectExtensions: settings.loadProjectExtensions === true,\n readSettings,\n ...(options.logSink ? { sink: fanoutSink([options.logSink, consoleSink({ minLevel: 'warn' })]) } : {}),\n })\n return resolveConfig({\n cwd,\n extensionRegistry,\n store: () => store,\n })\n })()\n\n runtimeCache.set(key, promise)\n while (runtimeCache.size > RUNTIME_CACHE_MAX) {\n const oldest = runtimeCache.keys().next().value\n if (oldest === undefined)\n break\n const evicted = runtimeCache.get(oldest)\n runtimeCache.delete(oldest)\n if (evicted)\n disposeRuntime(evicted)\n }\n promise.catch(() => {\n if (runtimeCache.get(key) === promise)\n runtimeCache.delete(key)\n })\n return promise\n }\n\n return {\n ...base,\n runtimeConfig,\n peekRuntimeConfig: cwd => runtimeCache.get(runtimeKey(cwd, readSettings())),\n hostRuntime,\n invalidateRuntime: () => {\n for (const entry of runtimeCache.values())\n disposeRuntime(entry)\n runtimeCache.clear()\n },\n forgetRuntime: () => {\n const dropped = [...runtimeCache.values()]\n runtimeCache.clear()\n return () => {\n for (const entry of dropped)\n disposeRuntime(entry)\n }\n },\n extensionBus,\n }\n}\n\n/** The daemon's own boot config: paths + store + state, from `cwd`. */\nasync function resolveOwnConfig(cwd: string | undefined): Promise<ResolvedConfig> {\n /*\n * `bun:sqlite` is loaded LAZILY so `zidane/ipc` stays importable under\n * plain Node (the Electron GUI main process imports this barrel for\n * `createChatHost`; the sqlite chunk must never be evaluated there).\n * Same invariant the tsdown config maintains for `zidane/session/sqlite`.\n */\n const { createTuiStore } = await import('../../session/sqlite')\n /*\n * Session-facing runtime config is re-resolved per cwd (project\n * extensions differ per folder); this one only carries paths, store, state.\n */\n return resolveConfig({\n ...(cwd !== undefined ? { cwd } : {}),\n store: resolved => createTuiStore(resolved.db),\n })\n}\n","/**\n * A local host's machine links for its clients (`machines.share.*`,\n * `machines.useServer`, `machines.links.status`; `docs/MACHINES.md` § Client\n * UI). Opt-in down to the module graph: the controller (`../../machine/links`,\n * which dials servers) is imported only while remote hosts are on, so with\n * the setting off nothing is loaded, no token read, nothing dialed. Turning\n * remote hosts off stops every link (the wanted links stay saved).\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { MachineLinksStatus } from '../../../chat/machine-protocol'\nimport type { MachineLinks } from '../../machine/links'\nimport type { HostSignal } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { Handlers } from './types'\nimport { existsSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { remoteHostsGate } from '../../../chat/feature-gate'\nimport { InvalidParamsError } from './params'\n\nconst GATE_POLL_MS = 2000\nconst EMPTY: MachineLinksStatus = { shares: [], uses: [] }\n\n/** Options for {@link createMachineLinkHandlers}: the host, settings access and the signal sink. */\nexport interface MachineLinksHandlerOptions {\n /** The chat host whose machine registry the links feed. */\n host: ChatHost\n /** Environment accessors for reading settings and locating the user data directory. */\n env: Pick<DaemonEnvironment, 'readSettings' | 'userDataDir'>\n /** Sink that fans a signal out to every connected client. */\n broadcast: (signal: HostSignal) => void\n /** Id of this host, when it has one. */\n hostId: string | undefined\n /** A zidane-server: it has no links (a server is shared from, never shares from here); every method is refused. */\n server?: boolean\n /** zidane version reported when dialing a server. */\n appVersion: string\n /** Connection pacing for the links (tests shrink it). */\n pacing?: { minDelayMs?: number, maxDelayMs?: number, heartbeatMs?: number, pollMs?: number }\n}\n\ntype Methods = 'machines.share.start' | 'machines.share.stop' | 'machines.useServer' | 'machines.links.status'\n\n/** A server's: no links, nothing loaded or resumed. */\nfunction serverLinkHandlers(): Handlers<Methods> {\n const refuse = (): never => {\n throw new Error('A zidane-server has no machine links: share a computer with it from that computer (zidane machine share, or its Hosts page).')\n }\n return { 'machines.share.start': refuse, 'machines.share.stop': refuse, 'machines.useServer': refuse, 'machines.links.status': refuse }\n}\n\n/**\n * Builds the `machines.share.*`, `machines.useServer` and `machines.links.status` handlers.\n * The links load lazily and only while remote hosts are enabled. On a zidane-server every method throws. Turning remote hosts off stops every link.\n * @param options - Host, environment, broadcast sink and pacing.\n * @returns The four method handlers.\n */\nexport function createMachineLinkHandlers(options: MachineLinksHandlerOptions): Handlers<Methods> {\n if (options.server)\n return serverLinkHandlers()\n const { host, env, broadcast } = options\n let links: Promise<MachineLinks> | undefined\n let gateTimer: ReturnType<typeof setInterval> | undefined\n\n const gateOn = (): boolean => remoteHostsGate.isEnabled(env.readSettings())\n\n const stop = (): void => {\n const current = links\n links = undefined\n clearInterval(gateTimer)\n gateTimer = undefined\n void current?.then(l => l.close()).catch(() => undefined)\n broadcast({ kind: 'machine:links', links: EMPTY })\n }\n\n const load = (): Promise<MachineLinks> => {\n links ??= import('../../machine/links').then(({ startMachineLinks }) => startMachineLinks({\n dataDir: env.userDataDir(),\n machines: host.machines,\n hostId: options.hostId,\n appVersion: options.appVersion,\n settings: () => env.readSettings(),\n onChange: status => broadcast({ kind: 'machine:links', links: status }),\n ...options.pacing,\n }))\n // Remote hosts turned off (here or in another window): every link stops.\n gateTimer ??= setInterval(() => {\n if (!gateOn())\n stop()\n }, options.pacing?.pollMs ?? GATE_POLL_MS)\n gateTimer.unref?.()\n return links\n }\n\n const required = (): Promise<MachineLinks> => {\n if (!gateOn())\n throw new Error(`Remote hosts are off${remoteHostsGate.isKilled() ? ` (${remoteHostsGate.killSwitchEnv}=1)` : ''}: machines are part of them.`)\n return load()\n }\n\n const str = (value: unknown, name: string): string => {\n if (typeof value !== 'string' || value === '')\n throw new InvalidParamsError(`\"${name}\" must be a non-empty string.`)\n return value\n }\n\n // Links saved by an earlier run resume with the host, only while remote hosts are on.\n if (gateOn() && existsSync(join(env.userDataDir(), 'machine-links.json')))\n void load().catch(() => undefined)\n host.machines.onClose(() => {\n const current = links\n links = undefined\n clearInterval(gateTimer)\n void current?.then(l => l.close()).catch(() => undefined)\n })\n\n return {\n 'machines.share.start': async (p) => {\n if (!Array.isArray(p.roots))\n throw new InvalidParamsError('\"roots\" must be a list of folders.')\n // A confined host lends only its own workspace (local hosts are not confined).\n if (host.workspace.confined) {\n for (const root of p.roots)\n host.workspace.resolveFolder(String(root))\n }\n return (await required()).startShare({ hostId: str(p.hostId, 'hostId'), name: str(p.name, 'name'), roots: p.roots, ...(typeof p.token === 'string' ? { token: p.token } : {}) })\n },\n 'machines.share.stop': async p => (await required()).stopShare(str(p.hostId, 'hostId')),\n 'machines.useServer': async (p) => {\n if (typeof p.enabled !== 'boolean')\n throw new InvalidParamsError('\"enabled\" must be a boolean.')\n return (await required()).setUse(str(p.hostId, 'hostId'), p.enabled)\n },\n 'machines.links.status': async () => (gateOn() ? (await load()).status() : EMPTY),\n }\n}\n","/** Machines this host knows, for clients (`docs/MACHINES.md`): list them, forget one, browse one's folders. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostSignal } from '../../protocol'\nimport type { Handlers } from './types'\nimport { posix } from 'node:path'\nimport { insideDeclaredRoots } from '../../../chat/host/machines'\nimport { InvalidParamsError } from './params'\n\n/** Folders listed per call at most. */\nconst MAX_DIRS = 2000\n\n/**\n * Builds the `machines.list`, `machines.forget` and `machines.listDirs` handlers.\n * `machines.forget` broadcasts a `machine:status` signal with the machine offline when it removed one. `machines.listDirs` is confined to the machine's declared roots and throws for a path outside them.\n * @param options - The chat host and the signal broadcast sink.\n * @returns The three method handlers.\n */\nexport function createMachineHandlers({ host, broadcast }: { host: ChatHost, broadcast: (signal: HostSignal) => void }): Handlers<'machines.list' | 'machines.forget' | 'machines.listDirs'> {\n return {\n 'machines.list': () => host.machines.list(),\n 'machines.forget': (p) => {\n if (typeof p.machineId !== 'string')\n throw new InvalidParamsError('machines.forget: \"machineId\" must be a string.')\n const machine = host.machines.get(p.machineId)\n const forgotten = host.machines.forget(p.machineId)\n if (forgotten && machine)\n broadcast({ kind: 'machine:status', machineId: machine.id, name: machine.name, status: 'offline' })\n return { forgotten }\n },\n 'machines.listDirs': async (p) => {\n if (typeof p.machineId !== 'string')\n throw new InvalidParamsError('machines.listDirs: \"machineId\" must be a string.')\n const machine = host.machines.get(p.machineId)\n const link = host.machines.link(p.machineId)\n if (!machine || !link)\n throw new Error(`Unknown machine \"${p.machineId}\".`)\n const roots = machine.roots.map(root => root.path)\n // No path: the first root.\n const asked = p.path === undefined || p.path === '' ? roots[0]! : p.path\n if (typeof asked !== 'string' || !insideDeclaredRoots(machine.roots, asked))\n throw new Error(`${String(asked)} is outside ${machine.name}'s roots.`)\n const path = posix.normalize(asked)\n const root = roots.find(r => insideDeclaredRoots([{ path: r }], path))!\n // The machine confines the listing again on its filesystem (real paths); never waits for an offline one.\n const { entries } = await link.call('fs.list', { handle: { id: 'host-list-dirs', cwd: root }, path }, { wait: false })\n const dirs = entries\n .map(entry => (typeof entry === 'string' ? entry : entry.path))\n .filter(name => name.endsWith('/'))\n .map(name => posix.join(path, name.slice(0, -1)))\n .sort()\n .slice(0, MAX_DIRS)\n return { path, dirs, roots }\n },\n }\n}\n","/**\n * The host side of one JSON-RPC connection, for every wire transport (the\n * unix socket in `../daemon/server.ts`, the WebSocket in `./ws-server.ts`):\n * a dispatcher {@link HostPeer} whose signals go out as `ipc.signal`\n * notifications, and the request / notification handlers that hand incoming\n * messages to the dispatcher. Framing and the write-backpressure bound\n * (`./send-budget`) stay with the transport.\n *\n * A signal is serialized once per fan-out, not once per peer: the first peer\n * builds the notification text from the signal's JSON and every other peer\n * of the fan-out sends the same string ({@link signalFrame}).\n */\nimport type { JsonRpcConnectionOptions } from '../../acp/json-rpc'\nimport type { AcpPeer, JsonRpcMessage, JsonRpcRequest, JsonRpcResponse } from '../../acp/types'\nimport type { HostDispatcher, HostPeer } from '../daemon/dispatcher'\nimport type { HostSignal } from '../protocol'\nimport { errorResponse, successResponse } from '../../acp/json-rpc'\nimport { SIGNAL_SEQ_FIELD } from '../protocol'\n\n/**\n * Per-peer write backpressure bound. A wedged peer (e.g. a SIGSTOP'd\n * terminal) stops reading, so fan-out writes pile up in the transport's\n * send buffer without bound and can OOM the host. A peer buffering more\n * than this is dropped: the protocol supports re-attach + backfill, so\n * killing a wedged peer is safe and self-healing.\n */\nexport const PEER_WRITE_HIGH_WATERMARK = 8 * 1024 * 1024\n\nexport interface RpcPeerOptions {\n /** The connection's JSON-RPC side; signals are dropped until it exists. */\n rpc: () => (Pick<AcpPeer, 'sendNotification'> & { sendSerialized?: (json: string, message: JsonRpcMessage) => void }) | undefined\n}\n\n/** What the send budget sees of a pre-serialized signal: a notification, never a reply. */\nconst SIGNAL_MESSAGE: JsonRpcMessage = { jsonrpc: '2.0', method: 'ipc.signal' }\n\n/**\n * The `ipc.signal` notification text for a signal whose JSON is `json`,\n * byte for byte what serializing `{ jsonrpc, method, params: { ...signal,\n * [SIGNAL_SEQ_FIELD]: seq } }` gives; `undefined` when splicing could not\n * promise that (an empty or non-object JSON, a signal that has the field).\n */\nexport function signalFrame(signal: HostSignal, json: string, seq: number | undefined): string | undefined {\n if (seq === undefined)\n return `{\"jsonrpc\":\"2.0\",\"method\":\"ipc.signal\",\"params\":${json}}`\n if (json.length <= 2 || json[0] !== '{' || !json.endsWith('}') || Object.hasOwn(signal, SIGNAL_SEQ_FIELD))\n return undefined\n return `{\"jsonrpc\":\"2.0\",\"method\":\"ipc.signal\",\"params\":${json.slice(0, -1)},\"${SIGNAL_SEQ_FIELD}\":${seq}}}`\n}\n\nexport function createRpcPeer(options: RpcPeerOptions): HostPeer {\n return {\n ready: false,\n watching: null,\n send(signal, seq, encoded) {\n try {\n const rpc = options.rpc()\n if (!rpc)\n return\n if (encoded && rpc.sendSerialized) {\n const json = encoded.json()\n if (json === undefined)\n return // Not JSON-able: no peer can receive it.\n encoded.frame ??= signalFrame(signal, json, seq)\n if (encoded.frame !== undefined) {\n rpc.sendSerialized(encoded.frame, SIGNAL_MESSAGE)\n return\n }\n }\n rpc.sendNotification('ipc.signal', seq === undefined ? signal : { ...signal, [SIGNAL_SEQ_FIELD]: seq })\n }\n catch {\n // A dying connection (or a signal JSON can't encode) must never take the host down with it.\n }\n },\n }\n}\n\n/** The JSON-RPC handlers that route one peer's requests and notifications to the dispatcher. */\nexport function dispatcherHandlers(dispatcher: HostDispatcher, peer: HostPeer): Pick<JsonRpcConnectionOptions, 'onRequest' | 'onNotification'> {\n return {\n onRequest: async (message: JsonRpcRequest): Promise<JsonRpcResponse> => {\n const outcome = await dispatcher.handleRequest(message.method, message.params, peer)\n return outcome.ok\n ? successResponse(message.id, outcome.result)\n : errorResponse(message.id, outcome.code, outcome.message, outcome.data)\n },\n onNotification: message => dispatcher.handleNotification(message.method, message.params, peer),\n }\n}\n","/**\n * One connection's outgoing budget, for every wire transport (the unix\n * socket in `../daemon/server.ts`, the WebSocket in `./ws-server.ts`).\n *\n * The slow-consumer bound is about pushed signals piling up for a peer that\n * stopped reading, not about one big reply it asked for: reply bytes still\n * queued are set aside (`replyReserve`) when the backlog is measured. The\n * buffer drains in order, so the reserve can only shrink to what is still\n * buffered; a peer that never reads keeps it whole and is dropped once the\n * signals behind it pass the bound. A reply itself is bounded by the message\n * size (over it, an `IpcErrorCode.ResponseTooLarge` error goes instead and\n * the connection stays), and the whole buffer by a hard cap for memory.\n *\n * The reserve is an approximation: it assumes the buffer drains oldest\n * first and only clamps it to what is still buffered, so after a partial\n * drain it may still count reply bytes that already left, and the signals\n * backlog reads low by at most that much. The memory bound, precisely: a\n * reply leaves the whole buffer at most `H = maxBuffered + 2 × maxMessage`\n * (checked after its write), and every signal re-clamps the reserve to what\n * is buffered, so the reserve never exceeds what the buffer held at the\n * first signal after the last reply (at most `H` plus that signal). A\n * signal leaves the measured backlog at most `maxBuffered`, so between\n * sends a peer holds at most `maxBuffered + H = 2 × maxBuffered + 2 ×\n * maxMessage` bytes (plus one signal). The write that crosses a bound is\n * the last: the peer is marked stuck and nothing more goes out. That is the\n * only backlog check: the buffer grows through `send`, so a backlog\n * over the bound is always seen by the write that made it.\n */\nimport type { JsonRpcMessage } from '../../acp/types'\nimport { Buffer } from 'node:buffer'\nimport { errorResponse } from '../../acp/json-rpc'\nimport { IpcErrorCode } from '../protocol'\n\n/** What the budget writes to: the transport's buffer and its framing. */\nexport interface SendTarget {\n /** Bytes written but not yet handed to the OS. */\n buffered: () => number\n /** Write one serialized message (the target frames it); `false`: the transport dropped it. */\n write: (json: string) => boolean\n}\n\nexport interface SendLimits {\n /** Signals backlog past which the peer is stuck (replies set aside). */\n maxBuffered: number\n /** Largest reply; a bigger one is answered with `ResponseTooLarge`. */\n maxMessage: number\n /** The peer cannot keep up: tear it down (called once). */\n stuck: (why: string) => void\n log: (line: string) => void\n /** Log prefix, e.g. `[ipc-ws]`. */\n label: string\n}\n\nexport interface PeerSend {\n /** Bytes buffered that are not reply bytes: what the slow-consumer bound measures. */\n backlog: () => number\n /** Send one message (the JSON-RPC endpoint's `send`): replies and the rest apart. */\n send: (json: string, message: JsonRpcMessage) => void\n /** Give up on the peer (once): {@link SendLimits.stuck} runs and nothing more goes out. */\n markStuck: (why: string) => void\n}\n\nfunction isReply(message: JsonRpcMessage): boolean {\n return 'id' in message && message.id !== undefined && message.id !== null && ('result' in message || 'error' in message)\n}\n\nexport function createPeerSend(target: SendTarget, limits: SendLimits): PeerSend {\n const { maxBuffered, maxMessage, log, label } = limits\n let replyReserve = 0\n let stuck = false\n const markStuck = (why: string): void => {\n if (stuck)\n return\n stuck = true\n limits.stuck(why)\n }\n const backlog = (): number => {\n const buffered = target.buffered()\n replyReserve = Math.min(replyReserve, buffered)\n return buffered - replyReserve\n }\n const send = (json: string, message: JsonRpcMessage): void => {\n if (stuck)\n return\n if (!isReply(message)) {\n if (!target.write(json) || backlog() > maxBuffered)\n markStuck(`more than ${maxBuffered} bytes of signals unsent`)\n return\n }\n let text = json\n let bytes = Buffer.byteLength(text)\n if (bytes > maxMessage) {\n const id = (message as { id: string | number }).id\n log(`${label} reply to ${String(id)} is ${bytes} bytes (> ${maxMessage}): answering with an error instead`)\n text = JSON.stringify(errorResponse(id, IpcErrorCode.ResponseTooLarge, `The reply is over ${maxMessage} bytes: ask for less (a transcript: a smaller page).`, { bytes, maxBytes: maxMessage }))\n bytes = Buffer.byteLength(text)\n }\n if (!target.write(text)) {\n markStuck('reply dropped by the transport')\n return\n }\n replyReserve += bytes\n if (target.buffered() > maxBuffered + 2 * maxMessage)\n markStuck(`more than ${maxBuffered + 2 * maxMessage} bytes unsent`)\n }\n return { backlog, send, markStuck }\n}\n","/**\n * The calling side of a worker RPC: request ids, a pending map, a timeout\n * per request, and crash recovery. A worker that crashes rejects what is\n * pending and is spawned again on the next use, after a backoff that doubles\n * up to a cap. A worker that cannot start (the factory throws, or it dies\n * before it said ready) or that crashes `maxCrashes` times in a row puts the\n * client in degraded mode: every request then rejects at once with a\n * {@link WorkerUnavailableError}, the caller's signal to do the work on its\n * own thread.\n *\n * Runtime-neutral: the factory returns a Bun / Web `Worker` or a Node\n * `worker_threads.Worker` ({@link WorkerLike}). The worker side is\n * `serveWorkerRpc` (`./rpc-serve.ts`); the wire is {@link WorkerCall} out,\n * {@link WorkerMessage} back.\n */\n\n/** A worker from either runtime: Bun / Web `Worker` (`addEventListener`) or Node `worker_threads.Worker` (`on`). */\nexport interface WorkerLike {\n /** Sends a {@link WorkerCall} to the worker. */\n postMessage: (message: unknown) => void\n /** Ends the worker. */\n terminate: () => unknown\n /** Lets the worker keep the process alive (while a reply is due). */\n ref?: () => void\n /** Stops the worker from keeping the process alive. */\n unref?: () => void\n /** Node's events: `message`, `error`, `exit`. */\n on?: (event: string, listener: (value: unknown) => void) => unknown\n /** Bun / Web events: `message`, `error`, `close`. */\n addEventListener?: (type: string, listener: (event: unknown) => void) => void\n}\n\n/** What the client posts: `init` once per spawn, then requests (`id` absent: a notification, no reply). */\nexport type WorkerCall = { init: unknown } | { id?: number, request: unknown }\n\n/** What the worker posts back. */\nexport type WorkerMessage\n = | { ready: true }\n | { fatal: string }\n | { id: number, ok: true, result: unknown }\n | { id: number, ok: false, error: { name: string, message: string } }\n\n/** No worker served the request: do the work on this thread. `degraded`: none will until the client is recreated. */\nexport class WorkerUnavailableError extends Error {\n /**\n * @param message - Why no worker served.\n * @param degraded - No worker will serve until the client is recreated.\n */\n constructor(message: string, readonly degraded: boolean) {\n super(message)\n this.name = 'WorkerUnavailableError'\n }\n}\n\n/** The worker's handler threw: `remoteName` and `message` are the thrown error's. */\nexport class WorkerRequestError extends Error {\n /**\n * @param remoteName - The thrown error's `name`.\n * @param message - The thrown error's `message`.\n */\n constructor(readonly remoteName: string, message: string) {\n super(message)\n this.name = 'WorkerRequestError'\n }\n}\n\n/** How {@link createWorkerRpcClient} spawns and supervises its worker. */\nexport interface WorkerRpcClientOptions {\n /** Spawns the worker. A throw puts the client in degraded mode. */\n create: () => WorkerLike\n /** Posted to every worker this client spawns, before any request (`serveWorkerRpc`'s `init`). */\n init?: unknown\n /** A request unanswered this long rejects, and the worker counts as crashed. Default 30 s. */\n timeoutMs?: number\n /** Crashes in a row before degraded mode. Default 3. */\n maxCrashes?: number\n /** Wait before spawning again after a crash: `base` doubled per crash in a row, at most `max`. Default 250 ms / 10 s. */\n backoffMs?: { base: number, max: number }\n /** What the worker is called in the errors it causes (`<name> unavailable: …`). Default `worker`. */\n name?: string\n /** Called once, with the reason, when the client goes degraded: from then on the caller does the work on its own thread. */\n onDegraded?: (reason: string) => void\n}\n\n/** The calling side of a worker RPC, from {@link createWorkerRpcClient}. */\nexport interface WorkerRpcClient<Req, Res> {\n /** Spawns the worker when none runs. Rejects {@link WorkerUnavailableError} when no worker can serve, {@link WorkerRequestError} when the handler threw. */\n request: (request: Req, options?: { timeoutMs?: number }) => Promise<Res>\n /** Fire-and-forget, only to a running worker (none: nothing to tell). */\n notify: (request: Req) => void\n /** True once no worker will serve (it could not start, or crashed `maxCrashes` times in a row). */\n isDegraded: () => boolean\n /** Terminates the worker and rejects what is pending; later requests reject. Idempotent. */\n close: () => void\n}\n\ninterface Pending {\n resolve: (value: unknown) => void\n reject: (error: Error) => void\n timer: ReturnType<typeof setTimeout>\n}\n\n/** Subscribes to a worker's messages, errors and exit, whichever event API it has. */\nfunction listen(worker: WorkerLike, on: { message: (data: unknown) => void, failed: (reason: string) => void }): void {\n if (typeof worker.on === 'function') {\n worker.on('message', data => on.message(data))\n worker.on('error', err => on.failed(err instanceof Error ? err.message : String(err)))\n worker.on('exit', code => on.failed(`exited with code ${String(code)}`))\n return\n }\n worker.addEventListener?.('message', event => on.message((event as MessageEvent).data))\n worker.addEventListener?.('error', event => on.failed((event as ErrorEvent).message || 'worker error'))\n // Bun's `close`: the worker exited.\n worker.addEventListener?.('close', event => on.failed(`exited with code ${(event as { code?: number }).code ?? '?'}`))\n}\n\n/**\n * A worker RPC client. The worker spawns on the first request.\n * @param options - How to spawn the worker, its `init`, the timeout and the crash policy.\n */\nexport function createWorkerRpcClient<Req, Res>(options: WorkerRpcClientOptions): WorkerRpcClient<Req, Res> {\n const timeoutMs = options.timeoutMs ?? 30_000\n const maxCrashes = options.maxCrashes ?? 3\n const backoff = options.backoffMs ?? { base: 250, max: 10_000 }\n const name = options.name ?? 'worker'\n const pending = new Map<number, Pending>()\n let nextId = 1\n let worker: WorkerLike | null = null\n let ready = false\n let crashes = 0\n let retryAt = 0\n let degraded: string | null = null\n let closed = false\n\n function degrade(reason: string): string {\n degraded = reason\n options.onDegraded?.(reason)\n return reason\n }\n\n function settleAll(reason: string): void {\n const error = new WorkerUnavailableError(reason, degraded !== null || closed)\n for (const [id, entry] of pending) {\n clearTimeout(entry.timer)\n pending.delete(id)\n entry.reject(error)\n }\n }\n\n /** The current worker is gone: a spawn failure degrades, a crash backs off. */\n function fail(failed: WorkerLike, reason: string): void {\n if (failed !== worker)\n return\n const wasReady = ready\n worker = null\n ready = false\n try {\n void failed.terminate()\n }\n catch {\n // Already gone.\n }\n crashes++\n if (!wasReady || crashes >= maxCrashes)\n degrade(`${name} unavailable: ${wasReady ? `${crashes} crashes in a row` : 'it did not start'} (${reason})`)\n retryAt = Date.now() + Math.min(backoff.base * 2 ** (crashes - 1), backoff.max)\n settleAll(degraded ?? `worker crashed: ${reason}`)\n }\n\n function onMessage(from: WorkerLike, data: unknown): void {\n if (from !== worker || typeof data !== 'object' || data === null)\n return\n const message = data as WorkerMessage\n if ('ready' in message) {\n ready = true\n return\n }\n if ('fatal' in message) {\n ready = false\n fail(from, message.fatal)\n return\n }\n const entry = pending.get(message.id)\n if (!entry)\n return\n pending.delete(message.id)\n clearTimeout(entry.timer)\n crashes = 0\n if (pending.size === 0)\n from.unref?.()\n if (message.ok)\n entry.resolve(message.result)\n else\n entry.reject(new WorkerRequestError(message.error.name, message.error.message))\n }\n\n function ensureWorker(): WorkerLike {\n if (closed)\n throw new WorkerUnavailableError('worker client closed', true)\n if (degraded !== null)\n throw new WorkerUnavailableError(degraded, true)\n if (worker)\n return worker\n if (Date.now() < retryAt)\n throw new WorkerUnavailableError('worker restarting after a crash', false)\n let spawned: WorkerLike\n try {\n spawned = options.create()\n }\n catch (err) {\n throw new WorkerUnavailableError(degrade(`${name} unavailable: ${err instanceof Error ? err.message : String(err)}`), true)\n }\n worker = spawned\n listen(spawned, { message: data => onMessage(spawned, data), failed: reason => fail(spawned, reason) })\n // Idle, it must not keep the process alive; `request` refs it while a reply is due.\n spawned.unref?.()\n spawned.postMessage({ init: options.init } satisfies WorkerCall)\n return spawned\n }\n\n return {\n request(request, requestOptions = {}) {\n return new Promise<Res>((resolve, reject) => {\n let target: WorkerLike\n try {\n target = ensureWorker()\n }\n catch (err) {\n reject(err instanceof Error ? err : new Error(String(err)))\n return\n }\n const id = nextId++\n const wait = requestOptions.timeoutMs ?? timeoutMs\n const timer = setTimeout(fail, wait, target, `no reply in ${wait} ms`)\n pending.set(id, { resolve: resolve as (value: unknown) => void, reject, timer })\n target.ref?.()\n try {\n target.postMessage({ id, request } satisfies WorkerCall)\n }\n catch (err) {\n // Not cloneable: this request only, the worker is fine.\n pending.delete(id)\n clearTimeout(timer)\n if (pending.size === 0)\n target.unref?.()\n reject(new WorkerUnavailableError(`could not post the request: ${err instanceof Error ? err.message : String(err)}`, false))\n }\n })\n },\n notify(request) {\n try {\n worker?.postMessage({ request } satisfies WorkerCall)\n }\n catch {\n // A worker going away takes its state with it.\n }\n },\n isDegraded: () => degraded !== null,\n close() {\n if (closed)\n return\n closed = true\n const current = worker\n worker = null\n settleAll('worker client closed')\n try {\n void current?.terminate()\n }\n catch {\n // Already gone.\n }\n },\n }\n}\n","/**\n * `sessions.loadEvents` pages served off the host's thread. A whole-session\n * replay (load every turn, replay them all) takes tens to hundreds of\n * milliseconds on a long session; on the host's event loop that stalls the\n * TUI in local mode, and every session's streaming on a daemon or a\n * zidane-server. The history worker (`./worker.ts`) runs the same replay\n * cache against its own read-only connection to the sessions database, so\n * pages are identical to the in-thread ones (same versioning by `getMeta`,\n * same bounds); only the thread differs.\n *\n * The pager falls back to the in-thread cache whenever the worker cannot\n * serve: a store that is not a SQLite file, `ZIDANE_NO_HISTORY_WORKER=1`,\n * a worker that cannot start or keeps crashing (degraded), or one request it\n * lost (a crash, a timeout).\n *\n * The worker also scans the usage summary's day buckets (`usage.summary`),\n * a read of every turn; without it, the scan runs here on a read-only\n * connection of its own.\n */\nimport type { SessionStore } from '../../session/index'\nimport type { SqliteStoreFile } from '../../session/sqlite-store'\nimport type { UsageBuckets } from '../../session/sqlite-usage'\nimport type { TranscriptReplayCache } from '../daemon/handlers/transcript-cache'\nimport type { HostSignal, LoadEventsPaging, SessionEventsPage } from '../protocol'\nimport type { WorkerLike, WorkerRpcClientOptions } from './rpc-client'\nimport { sqliteStoreFile } from '../../session/sqlite-store'\nimport { runUsageAggregates } from '../../session/sqlite-usage'\nimport { InvalidParamsError } from '../daemon/handlers/params'\nimport { changedSessionOf, createTranscriptReplayCache } from '../daemon/handlers/transcript-cache'\nimport { openReadonlySqlite } from './readonly-db'\nimport { createWorkerRpcClient, WorkerRequestError, WorkerUnavailableError } from './rpc-client'\n\n/** Kill switch: `1` pages on the host's thread, with no worker. */\nexport const HISTORY_WORKER_KILL_SWITCH = 'ZIDANE_NO_HISTORY_WORKER'\n\n/** What `./worker.ts` takes as `init`. */\nexport interface HistoryWorkerInit {\n /** The sessions database, opened read-only by the worker. */\n dbPath: string\n}\n\n/** The history worker's requests. */\nexport type HistoryWorkerRequest\n = | { op: 'page', sessionId: string, paging: LoadEventsPaging }\n | { op: 'drop', sessionId: string }\n | { op: 'usage' }\n\n/**\n * The history worker's module: the sibling source file in development, the\n * sibling `history-worker.js` entry in the published dist, and the entry\n * embedded under the binary's root in a compiled executable\n * (`scripts/build-executables.ts`, `scripts/build-server.ts`).\n */\nexport function historyWorkerUrl(): URL {\n if (typeof Bun !== 'undefined' && (Bun as unknown as { isStandaloneExecutable?: boolean }).isStandaloneExecutable)\n return new URL('./src/ipc/history/worker.ts', import.meta.url)\n return new URL(import.meta.url.endsWith('.ts') ? './worker.ts' : './history-worker.js', import.meta.url)\n}\n\n/** A Bun / Web `Worker` on the history worker module. */\nfunction spawnHistoryWorker(): WorkerLike {\n return new Worker(historyWorkerUrl().href, { type: 'module' })\n}\n\n/** A client of the history worker, from {@link createTranscriptHistoryWorker}. */\nexport interface TranscriptHistoryWorker {\n /**\n * One `sessions.loadEvents` page, from the worker. Rejects\n * {@link WorkerUnavailableError} when the worker could not serve it (page\n * in-thread then), {@link InvalidParamsError} for bad paging, and the\n * worker's error otherwise (an unknown session).\n */\n page: (sessionId: string, paging: LoadEventsPaging) => Promise<SessionEventsPage>\n /** The session changed or went away: the worker forgets its replay. */\n drop: (sessionId: string) => void\n /** The usage summary's day buckets (`runUsageAggregates`). Rejects {@link WorkerUnavailableError} when the worker could not serve them. */\n usage: () => Promise<UsageBuckets>\n /** True once the worker will not serve again (it could not start, or keeps crashing). */\n isDegraded: () => boolean\n /** Terminates the worker; later pages reject {@link WorkerUnavailableError}. */\n close: () => void\n}\n\n/**\n * A client of the history worker over `dbPath`. The worker spawns on the\n * first page.\n * @param options - The database, and (tests, a Node host) how to spawn the worker.\n */\nexport function createTranscriptHistoryWorker(options: {\n dbPath: string\n /** Default: a Bun / Web `Worker` on {@link historyWorkerUrl}. */\n create?: () => WorkerLike\n} & Pick<WorkerRpcClientOptions, 'timeoutMs' | 'maxCrashes' | 'backoffMs' | 'onDegraded'>): TranscriptHistoryWorker {\n const { dbPath, create = spawnHistoryWorker, ...rest } = options\n const client = createWorkerRpcClient<HistoryWorkerRequest, unknown>({ name: 'history worker', create, init: { dbPath } satisfies HistoryWorkerInit, ...rest })\n return {\n async page(sessionId, paging) {\n try {\n return await client.request({ op: 'page', sessionId, paging }) as SessionEventsPage\n }\n catch (err) {\n if (err instanceof WorkerRequestError)\n throw err.remoteName === 'InvalidParamsError' ? new InvalidParamsError(err.message) : new Error(err.message)\n throw err\n }\n },\n drop: sessionId => client.notify({ op: 'drop', sessionId }),\n usage: async () => await client.request({ op: 'usage' }) as UsageBuckets,\n isDegraded: client.isDegraded,\n close: client.close,\n }\n}\n\n/** Where a host's paged `sessions.loadEvents` are served: the history worker when it can, else the in-thread cache. */\nexport interface HostTranscriptPager {\n /** The in-thread cache: the fallback pages, and the host's other whole-session reads (`document`). */\n replays: TranscriptReplayCache\n /** One page of a session of `store` (the worker serves it when `store` is a SQLite file). */\n page: (store: SessionStore, sessionId: string, paging: LoadEventsPaging) => Promise<SessionEventsPage>\n /** A host signal: one that follows a change to a session drops its replay, here and in the worker. */\n observe: (signal: HostSignal) => void\n /** The session is gone: forget it here and in the worker. */\n forget: (sessionId: string) => void\n /** The usage summary's day buckets of `store`; `null` for a store that is not a SQLite file (it keeps no usage to scan). */\n usage: (store: SessionStore) => Promise<UsageBuckets | null>\n /** Terminates the worker (the host is shutting down); later pages are served in-thread. */\n close: () => void\n}\n\nconst debugFallback: (error: unknown) => void = process.env.ZIDANE_DEBUG\n ? error => console.error('[zidane/ipc] the history worker could not serve; the host thread does:', error)\n : () => {}\n\n/**\n * A host's pager. The worker is used only for a store that is a SQLite file\n * (`sqliteStoreFile`), with the kill switch off; it spawns lazily, on the\n * first page, for the first such file (one host, one store).\n * @param options - Options.\n * @param options.replays - The in-thread cache; default a new one.\n * @param options.worker - Makes the worker client (tests); default {@link createTranscriptHistoryWorker}.\n */\nexport function createHostTranscriptPager(options: {\n replays?: TranscriptReplayCache\n worker?: (dbPath: string) => TranscriptHistoryWorker\n} = {}): HostTranscriptPager {\n const replays = options.replays ?? createTranscriptReplayCache()\n const makeWorker = options.worker ?? (dbPath => createTranscriptHistoryWorker({ dbPath }))\n let worker: { client: TranscriptHistoryWorker, path: string } | null = null\n let closed = false\n\n const usable = (store: SessionStore): { client: TranscriptHistoryWorker, file: SqliteStoreFile } | null => {\n const file = sqliteStoreFile(store)\n if (closed || !file || process.env[HISTORY_WORKER_KILL_SWITCH] === '1')\n return null\n worker ??= { client: makeWorker(file.path), path: file.path }\n return worker.path === file.path && !worker.client.isDegraded() ? { client: worker.client, file } : null\n }\n const drop = (sessionId: string): void => worker?.client.drop(sessionId)\n\n return {\n replays,\n async page(store, sessionId, paging) {\n const target = usable(store)\n if (target) {\n // The worker reads on its own connection: let this one's queued writes land first, as an in-thread read would wait for them.\n await target.file.settled()\n try {\n return await target.client.page(sessionId, paging)\n }\n catch (err) {\n if (!(err instanceof WorkerUnavailableError))\n throw err\n debugFallback(err)\n }\n }\n return replays.page(store, sessionId, paging)\n },\n observe(signal) {\n replays.observe(signal)\n const sessionId = changedSessionOf(signal)\n if (sessionId !== undefined)\n drop(sessionId)\n },\n forget(sessionId) {\n replays.forget(sessionId)\n drop(sessionId)\n },\n async usage(store) {\n const file = sqliteStoreFile(store)\n if (!file)\n return null\n await file.settled()\n const target = usable(store)\n if (target) {\n try {\n return await target.client.usage()\n }\n catch (err) {\n if (!(err instanceof WorkerUnavailableError))\n throw err\n debugFallback(err)\n }\n }\n const db = await openReadonlySqlite(file.path)\n try {\n return runUsageAggregates(db)\n }\n finally {\n db.close()\n }\n },\n close() {\n closed = true\n worker?.client.close()\n worker = null\n },\n }\n}\n","/**\n * Secret redaction for what a host shows about its MCP servers\n * (`catalog.mcps`): command-line arguments and URLs, which config files\n * routinely fill with tokens. Over-redacting an ordinary argument is a\n * cosmetic loss; under-redacting leaks a credential to every client, so the\n * rules lean wide, but stay off file paths, package names and plain words.\n *\n * - URLs (`scheme://…`, as an argument or inside one): userinfo, query values,\n * fragment values, and secret-looking path segments.\n * - Values of secret-looking flags (`--token x`, `--api-key=x`), of header\n * flags (`-H \"Name: value\"`, `--header=Name: value`), of secret-looking\n * headers anywhere (`Authorization: Bearer …`), and of secret-looking\n * `KEY=VALUE` pairs (`-e GITHUB_TOKEN=…`, `env API_KEY=…`, `--pass x`).\n * - JSON arguments (`--config '{\"apiKey\":\"…\"}'`): the value of every\n * secret-named key at any depth; the other strings as values.\n * - Connection strings and form bodies (`Server=x;Password=…`,\n * `a=1&token=…`): each secret-named pair's value.\n * - Known token shapes anywhere in an argument (`sk-…`, `ghp_…`, `xoxb-…`,\n * `AKIA…`, `glpat-…`, `zds_…`), and whole high-entropy arguments.\n *\n * What counts as secret-looking is shared (`src/chat/secret-shapes`): the\n * remote host URL check refuses the same shapes in a URL's path.\n */\nimport { isSecretName, isSecretPathSegment, KNOWN_TOKEN, looksLikeSecret } from '../../chat/secret-shapes'\nimport { REDACTED } from '../protocol'\n\nconst HEADER_FLAGS = new Set(['-H', '--header', '--headers'])\nconst URL_SHAPED = /^[a-z][a-z0-9+.-]*:\\/\\//i\nconst HEADER = /^([\\w-]+):(\\s*)\\S.*$/s\nconst KEY_VALUE = /^([A-Z_][\\w.-]*)=(.*)$/is\n/** `k=v` pairs joined by `;` or `&` (a connection string, a form body): `Server=x;Password=y`, `a=1&token=x`. */\nconst DELIMITED_PAIRS = /^[a-z_][\\w .-]*=[^;&]*(?:[;&][a-z_][\\w .-]*=[^;&]*)+[;&]?$/i\n/** A JSON object or array argument (`--config '{\"apiKey\":\"…\"}'`). */\nconst JSON_SHAPED = /^\\s*[{[][\\s\\S]*[}\\]]\\s*$/\n\nconst scrubKnownTokens = (value: string): string => value.replace(KNOWN_TOKEN, REDACTED)\n\nfunction redactPairs(text: string): string {\n return text.split('&').map((pair) => {\n const eq = pair.indexOf('=')\n return eq < 0 ? pair : `${pair.slice(0, eq)}=${REDACTED}`\n }).join('&')\n}\n\n/**\n * `https://user:pw@host/p/<key>/sse?k=v#t=x` → `https://<redacted>@host/p/<redacted>/sse?k=<redacted>#t=<redacted>`;\n * an unparsable URL is redacted whole.\n */\nexport function redactUrl(raw: string): string {\n let url: URL\n try {\n url = new URL(raw)\n }\n catch {\n return REDACTED\n }\n const credentials = url.username !== '' || url.password !== '' ? `${REDACTED}@` : ''\n const path = url.pathname.split('/').map(segment => isSecretPathSegment(segment) ? REDACTED : segment).join('/')\n const keys = [...url.searchParams.keys()]\n const query = keys.length > 0 ? `?${keys.map(key => `${encodeURIComponent(key)}=${REDACTED}`).join('&')}` : ''\n const fragment = url.hash.slice(1)\n const hash = fragment === '' ? '' : fragment.includes('=') ? `#${redactPairs(fragment)}` : looksLikeSecret(fragment) ? `#${REDACTED}` : `#${fragment}`\n const authority = url.host !== '' || raw.includes('//') ? `//${credentials}${url.host}` : ''\n return scrubKnownTokens(`${url.protocol}${authority}${path}${query}${hash}`)\n}\n\nfunction redactHeader(value: string): string {\n const match = HEADER.exec(value)\n return match ? `${match[1]}:${match[2]}${REDACTED}` : REDACTED\n}\n\n/** One value standing on its own (a positional argument, or what follows `--flag=`). */\nfunction redactValue(value: string): string {\n if (URL_SHAPED.test(value))\n return redactUrl(value)\n const header = HEADER.exec(value)\n if (header && isSecretName(header[1]!))\n return redactHeader(value)\n const json = JSON_SHAPED.test(value) ? redactJson(value) : null\n if (json !== null)\n return json\n if (DELIMITED_PAIRS.test(value))\n return redactDelimitedPairs(value)\n const pair = KEY_VALUE.exec(value)\n if (pair)\n return `${pair[1]}=${isSecretName(pair[1]!) ? REDACTED : redactValue(pair[2]!)}`\n if (looksLikeSecret(value))\n return REDACTED\n return scrubKnownTokens(value)\n}\n\n/** `Server=x;Password=y` → `Server=x;Password=<redacted>`: each secret-named pair's value, the others' as values. */\nfunction redactDelimitedPairs(value: string): string {\n return value.split(/([;&])/).map((part) => {\n const eq = part.indexOf('=')\n if (eq < 0)\n return part\n const name = part.slice(0, eq)\n return `${name}=${isSecretName(name.trim()) ? REDACTED : redactValue(part.slice(eq + 1))}`\n }).join('')\n}\n\n/** A JSON argument with every secret-named key's value redacted (any depth), the other strings as values; `null` when not JSON. */\nfunction redactJson(value: string): string | null {\n let parsed: unknown\n try {\n parsed = JSON.parse(value)\n }\n catch {\n return null\n }\n if (parsed === null || typeof parsed !== 'object')\n return null\n const walk = (node: unknown): unknown => {\n if (typeof node === 'string')\n return redactValue(node)\n if (Array.isArray(node))\n return node.map(walk)\n if (node !== null && typeof node === 'object')\n return Object.fromEntries(Object.entries(node).map(([key, child]) => [key, isSecretName(key) ? REDACTED : walk(child)]))\n return node\n }\n return JSON.stringify(walk(parsed))\n}\n\n/** An MCP server's arguments with every secret-looking value replaced by {@link REDACTED}. */\nexport function redactArgs(args: readonly string[]): string[] {\n const out: string[] = []\n for (let i = 0; i < args.length; i++) {\n const arg = args[i]!\n if (!arg.startsWith('-')) {\n out.push(redactValue(arg))\n continue\n }\n const eq = arg.indexOf('=')\n const flag = eq > 0 ? arg.slice(0, eq) : arg\n if (eq > 0) {\n const value = arg.slice(eq + 1)\n out.push(`${flag}=${HEADER_FLAGS.has(flag) ? redactHeader(value) : isSecretName(flag) ? REDACTED : redactValue(value)}`)\n continue\n }\n out.push(scrubKnownTokens(arg))\n const next = args[i + 1]\n if (next === undefined || next.startsWith('-'))\n continue\n if (HEADER_FLAGS.has(flag)) {\n out.push(redactHeader(next))\n i++\n }\n else if (isSecretName(flag)) {\n out.push(REDACTED)\n i++\n }\n }\n return out\n}\n","/**\n * What a host discovered, as the settings tabs list it (`catalog.*`): the\n * same scans and gates the host's agents use (`composeSessionSkills`,\n * `discoverSessionMcpServers`, the plugin gates), each entry with whether\n * the host's settings enable it. Wire-safe and secret-free: an MCP server's\n * `env` / `headers` values never leave the host, and its URL and arguments\n * go through `./redact` (credentials, query / fragment values, header and\n * secret-flag values, secret `KEY=VALUE` pairs, token-shaped values).\n */\nimport type { McpServerStatus } from '../../chat/mcp-status'\nimport type { DiscoveredMcp, DiscoveryError } from '../../chat/mcps-discovery'\nimport type { DiscoveredPlugin } from '../../chat/plugins-discovery'\nimport type { LoadedExtension, LoadedPluginRecord } from '../../extensions/index'\nimport type { SkillConfig } from '../../skills/index'\nimport type { HostCatalogError, HostCatalogExtension, HostCatalogMcp, HostCatalogPlugin, HostCatalogSkill, HostSettings } from '../protocol'\nimport { REDACTED } from '../protocol'\nimport { redactArgs, redactUrl } from './redact'\n\nconst allows = (list: readonly string[] | undefined, name: string): boolean => list === undefined || list.includes(name)\n\n/**\n * Disk skills (gated by `enabledSkills`), then plugin and extension skills\n * (gated by their plugin / extension, so always on here), later ones winning\n * a name like the agent's own merge (`mergeSkillCatalog`).\n */\nexport function skillEntries(input: { disk: readonly SkillConfig[], plugin: readonly SkillConfig[], extension: readonly SkillConfig[], settings: HostSettings }): HostCatalogSkill[] {\n const byName = new Map<string, HostCatalogSkill>()\n const add = (skill: SkillConfig, origin: HostCatalogSkill['origin']): void => {\n const contributedBy = origin === 'plugin' ? skill.metadata?.['zidane.plugin'] : origin === 'extension' ? skill.metadata?.['zidane.extension'] : undefined\n byName.set(skill.name, {\n name: skill.name,\n description: skill.description,\n ...(skill.source ? { source: skill.source } : {}),\n ...(skill.location ? { location: skill.location } : {}),\n origin,\n ...(contributedBy ? { contributedBy } : {}),\n enabled: origin === 'disk' ? allows(input.settings.enabledSkills, skill.name) : true,\n toggleable: origin === 'disk',\n })\n }\n for (const skill of input.disk)\n add(skill, 'disk')\n for (const skill of input.plugin)\n add(skill, 'plugin')\n for (const skill of input.extension)\n add(skill, 'extension')\n return [...byName.values()].sort((a, b) => a.name.localeCompare(b.name))\n}\n\nfunction redactValues(record: Readonly<Record<string, string>> | undefined): Record<string, string> | undefined {\n if (!record)\n return undefined\n return Object.fromEntries(Object.keys(record).map(key => [key, REDACTED]))\n}\n\nexport function mcpEntries(servers: readonly DiscoveredMcp[], errors: readonly DiscoveryError[], settings: HostSettings, statuses: ReadonlyMap<string, McpServerStatus>): { servers: HostCatalogMcp[], errors: HostCatalogError[] } {\n return {\n servers: servers.map(({ config, source, path }) => {\n const env = redactValues(config.env)\n const headers = redactValues(config.headers)\n const status = statuses.get(config.name)\n return {\n name: config.name,\n transport: config.transport,\n source,\n path,\n enabled: allows(settings.enabledMcps, config.name),\n toggleable: true,\n ...(config.command !== undefined ? { command: config.command } : {}),\n ...(config.args ? { args: redactArgs(config.args) } : {}),\n ...(config.url !== undefined ? { url: redactUrl(config.url) } : {}),\n ...(config.cwd !== undefined ? { cwd: config.cwd } : {}),\n // Always said for a stdio server, so a client knows where it runs (and whether it can share it).\n ...(config.transport === 'stdio' ? { scope: config.scope === 'context' ? 'context' as const : 'host' as const } : {}),\n ...(config.shared !== undefined ? { shared: config.shared } : {}),\n ...(config.auth !== undefined ? { auth: config.auth } : {}),\n ...(env ? { env } : {}),\n ...(headers ? { headers } : {}),\n ...(status ? { status } : {}),\n }\n }),\n errors: errors.map(e => ({ path: e.path, source: e.source, message: e.message, ...(e.informational ? { informational: true } : {}) })),\n }\n}\n\nfunction capabilities(contributions: NonNullable<LoadedExtension['contributions']>): string[] {\n const labels: string[] = []\n const add = (label: string, present: boolean): void => {\n if (present)\n labels.push(label)\n }\n add('agents', Object.keys(contributions.agents).length > 0)\n add('providers', Object.keys(contributions.providers).length > 0)\n add('tools', Object.keys(contributions.tools).length > 0)\n add('hooks', Object.values(contributions.hooks).some(handlers => handlers !== undefined && handlers.length > 0))\n add('mcps', contributions.mcpServers.length > 0)\n add('skills', contributions.skills.length > 0)\n add('commands', contributions.commands.length > 0)\n add('completions', contributions.completionProviders.length > 0)\n add('themes', Object.keys(contributions.themes).length > 0)\n add('system', contributions.systemFragments.length > 0)\n return labels\n}\n\n/** Loaded, then inactive (disabled or broken), first one of a name wins. */\nexport function extensionEntries(loaded: readonly LoadedExtension[], inactive: readonly LoadedExtension[], settings: HostSettings): HostCatalogExtension[] {\n const rows = new Map<string, HostCatalogExtension>()\n for (const ext of [...loaded, ...inactive]) {\n if (rows.has(ext.name))\n continue\n rows.set(ext.name, {\n name: ext.name,\n source: ext.source,\n enabled: !ext.error && allows(settings.enabledExtensions, ext.name),\n toggleable: !ext.error,\n ...(ext.definition?.version ? { version: ext.definition.version } : {}),\n ...(ext.definition?.description ? { description: ext.definition.description } : {}),\n ...(ext.dir ? { dir: ext.dir } : {}),\n ...(ext.error ? { error: ext.error } : {}),\n ...(ext.contributions ? { capabilities: capabilities(ext.contributions) } : {}),\n })\n }\n return [...rows.values()].sort((a, b) => a.name.localeCompare(b.name))\n}\n\ninterface PluginSource { plugin: DiscoveredPlugin['plugin'], name: string, origin: HostCatalogPlugin['origin'] }\n\n/** Disk plugins, then the ones extensions loaded (a name on disk wins, as the agent's gate decides). */\nexport function pluginEntries(disk: readonly DiscoveredPlugin[], fromExtensions: readonly LoadedPluginRecord[], settings: HostSettings): HostCatalogPlugin[] {\n const sources: PluginSource[] = [\n ...disk.map(p => ({ plugin: p.plugin, name: p.name, origin: { kind: 'disk' as const, scope: p.source, dir: p.path } })),\n ...fromExtensions.map(r => ({ plugin: r.plugin, name: r.name, origin: { kind: 'extension' as const, extensionName: r.extensionName, dir: r.dir } })),\n ]\n const rows = new Map<string, HostCatalogPlugin>()\n for (const { plugin, name, origin } of sources) {\n if (rows.has(name))\n continue\n const error = plugin.ok ? undefined : plugin.diagnostics.find(d => d.severity === 'error')?.message\n rows.set(name, {\n name,\n origin,\n ok: plugin.ok,\n enabled: plugin.ok && allows(settings.enabledPlugins, name),\n toggleable: plugin.ok,\n ...(plugin.manifest?.version !== undefined ? { version: plugin.manifest.version } : {}),\n ...(plugin.manifest?.description !== undefined ? { description: plugin.manifest.description } : {}),\n skills: plugin.skills.map(s => s.name),\n mcpServers: plugin.mcpServers.map(s => s.name),\n ...(error ? { error } : {}),\n })\n }\n return [...rows.values()].sort((a, b) => a.name.localeCompare(b.name))\n}\n","/**\n * What the host discovered for its settings tabs (`catalog.*`), the agent\n * profiles a folder offers (`agents.list`) and the models its credentials\n * can run (`models.list`), so a window on a server lists the server's\n * skills, MCP servers, extensions, plugins, agents and providers, not its own.\n * An MCP server's row carries its state on the host (sign-in, tools, last\n * Test: `mcp.test`, `mcp.signOut`), and the server processes its sessions\n * share can be listed and restarted (`mcp.instances`, `mcp.restart`).\n */\nimport type { ProviderKey } from '../../../chat/auth'\nimport type { ResolvedConfig } from '../../../chat/config'\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { MachineProject } from '../../../chat/host/machines'\nimport type { McpStatusTracker } from '../../../chat/mcp-status'\nimport type { DiscoveredPlugin } from '../../../chat/plugins-discovery'\nimport type { HostModelProvider } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { Handlers } from './types'\nimport { availableAgents } from '../../../chat/agents'\nimport { detectAuth } from '../../../chat/auth'\nimport { listDecisionModels, testDecisionModel } from '../../../chat/decision-models'\nimport { machineDiscoveryCwd } from '../../../chat/host/machines'\nimport { createProviderBuilder } from '../../../chat/host/models/index'\nimport { listImageModels } from '../../../chat/image-models'\nimport { discoverProjectMcps } from '../../../chat/mcps-discovery'\nimport { testModel } from '../../../chat/model-test'\nimport { buildPluginContributions, discoverProjectPlugins } from '../../../chat/plugins-discovery'\nimport { scopeCwd } from '../../../chat/session-cwd'\nimport { discoverProjectSkills } from '../../../chat/skills-discovery'\nimport { filterRegistryPlugins } from '../../../extensions/index'\nimport { extensionEntries, mcpEntries, pluginEntries, skillEntries } from '../catalog-entries'\nimport { optionalString, requiredString } from './params'\n\ntype CatalogMethod = 'catalog.skills' | 'catalog.mcps' | 'catalog.extensions' | 'catalog.plugins' | 'agents.list' | 'models.list' | 'models.test' | 'decisions.test' | 'mcp.test' | 'mcp.signOut' | 'mcp.instances' | 'mcp.restart'\n\nconst kindOf = (kind: unknown): string | undefined => (typeof kind === 'string' ? kind : undefined)\n\n/**\n * The folder a catalog scans: `cwd` (inside the roots on a server), else the\n * host user's home. A machine's folder (`docs/MACHINES.md` § Folders) is\n * never read here: a folder of this host's stands in for the user scope.\n */\nexport function catalogFolder({ env, host }: { env: Pick<DaemonEnvironment, 'userDataDir'>, host: Pick<ChatHost, 'resolveFolder'> }, cwd: unknown, kind?: unknown): string {\n if (cwd !== undefined && typeof cwd !== 'string')\n throw new Error('cwd must be a string.')\n if (!cwd)\n return scopeCwd('')\n const folder = host.resolveFolder(cwd, kindOf(kind))\n return folder.machine ? machineDiscoveryCwd(env.userDataDir()) : scopeCwd(folder.cwd)\n}\n\nexport function createCatalogHandlers({ env, host, mcpStatus }: {\n env: DaemonEnvironment\n host: Pick<ChatHost, 'resolveFolder' | 'folderCatalog' | 'mcpServers'>\n mcpStatus: McpStatusTracker\n}): Handlers<CatalogMethod> {\n const folderOf = (cwd: unknown, kind?: unknown): string => catalogFolder({ env, host }, cwd, kind)\n /** User scope here, project scope read on the machine for a machine's folder. */\n const catalogOf = async (cwd: unknown, kind: unknown, prefix: string): Promise<{ dir: string, project?: MachineProject }> => {\n if (typeof cwd !== 'string' || !cwd || !host.resolveFolder(cwd, kindOf(kind)).machine)\n return { dir: folderOf(cwd, kind) }\n const { discoveryCwd, project } = await host.folderCatalog(cwd, kindOf(kind), prefix)\n return { dir: discoveryCwd, ...(project ? { project } : {}) }\n }\n const scanFlags = () => {\n const settings = env.readSettings()\n return { settings, foreignAgents: settings.importForeignConfigs === true, ruler: settings.importRulerConfigs !== false }\n }\n /** A folder's MCP servers: a machine's project ones first, as in its sessions. */\n const mcpsOf = async (cwd: unknown, kind: unknown) => {\n const { dir, project } = await catalogOf(cwd, kind, env.config.prefix)\n const config = await env.runtimeConfig(dir)\n const { foreignAgents, ruler } = scanFlags()\n const { servers: found, errors } = discoverProjectMcps({ cwd: dir, prefix: config.prefix, foreignAgents, ruler })\n const machineNames = new Set((project?.mcps ?? []).map(server => server.config.name))\n return { servers: [...(project?.mcps ?? []), ...found.filter(server => !machineNames.has(server.config.name))], errors }\n }\n const plugins = async (dir: string, config: ResolvedConfig): Promise<DiscoveredPlugin[]> => {\n const { plugins: found } = await discoverProjectPlugins({\n cwd: dir,\n prefix: config.prefix,\n ...(config.pluginScanPaths.length > 0 ? { extraRoots: config.pluginScanPaths } : {}),\n })\n return found\n }\n\n return {\n 'catalog.skills': async (p) => {\n const { dir, project } = await catalogOf(p?.cwd, p?.kind, env.config.prefix)\n const config = await env.runtimeConfig(dir)\n const { settings, foreignAgents, ruler } = scanFlags()\n const [found, discovered] = await Promise.all([\n discoverProjectSkills({ cwd: dir, prefix: config.prefix, foreignAgents, ruler }),\n plugins(dir, config),\n ])\n // A machine's project skills first: project beats user, as in its sessions.\n const machineNames = new Set((project?.skills ?? []).map(skill => skill.name))\n const disk = [...(project?.skills ?? []), ...found.filter(skill => !machineNames.has(skill.name))]\n const pluginSkills = buildPluginContributions({ discovered, ...(settings.enabledPlugins !== undefined ? { enabled: settings.enabledPlugins } : {}) }).skills\n const live = filterRegistryPlugins(config.extensions, settings.enabledPlugins, new Set(discovered.map(d => d.name)))\n return { skills: skillEntries({ disk, plugin: pluginSkills, extension: live.skills, settings }) }\n },\n 'catalog.mcps': async (p) => {\n const { servers, errors } = await mcpsOf(p?.cwd, p?.kind)\n return mcpEntries(servers, errors, env.readSettings(), mcpStatus.statuses(servers.map(server => server.config)))\n },\n 'mcp.test': async (p) => {\n const name = requiredString(p.name, 'name')\n const found = (await mcpsOf(p.cwd, p.kind)).servers.find(server => server.config.name === name)\n if (!found)\n throw new Error(`No MCP server \"${name}\" in that folder's catalog.`)\n await mcpStatus.test(found.config)\n return mcpStatus.statuses([found.config]).get(name)!\n },\n 'mcp.signOut': (p) => {\n mcpStatus.signOut(requiredString(p.name, 'name'))\n },\n 'mcp.instances': p => host.mcpServers.instances(optionalString(p?.cwd, 'cwd')),\n 'mcp.restart': async p => ({\n restarted: await host.mcpServers.restart(requiredString(p?.name, 'name'), optionalString(p?.cwd, 'cwd')),\n }),\n 'catalog.extensions': async (p) => {\n const config = await env.runtimeConfig(folderOf(p?.cwd, p?.kind))\n return { extensions: extensionEntries(config.extensions.loaded, config.extensions.inactive, env.readSettings()) }\n },\n 'catalog.plugins': async (p) => {\n const dir = folderOf(p?.cwd, p?.kind)\n const config = await env.runtimeConfig(dir)\n return { plugins: pluginEntries(await plugins(dir, config), config.extensions.plugins, env.readSettings()) }\n },\n // A profile a setting turns off (Codemode) is not offered.\n 'agents.list': async (p) => {\n const config = await env.runtimeConfig(folderOf(p.cwd))\n return Object.values(availableAgents(config.agents, env.readSettings())).map(a => ({ id: a.id, label: a.label, description: a.description, accent: a.accent ?? 'accent' }))\n },\n 'models.list': async (p) => {\n const config = p?.cwd ? await env.runtimeConfig(folderOf(p.cwd, p.kind)) : env.config\n const authed = detectAuth(env.userDataDir(), config.providers).filter(auth => auth.available)\n // Decision and image availability read stored API keys from the environment.\n env.applyAuthEnv?.()\n const decisionModels = listDecisionModels({ providers: config.providers, authed })\n const imageModels = listImageModels({ providers: config.providers, authed })\n const providers: HostModelProvider[] = authed.map((auth) => {\n const decisions = decisionModels\n .filter(entry => entry.providerKey === auth.key)\n .map(entry => ({ id: entry.modelId, available: entry.available, ...(entry.reason ? { reason: entry.reason } : {}) }))\n const images = imageModels\n .filter(entry => entry.providerKey === auth.key)\n .map(entry => ({\n id: entry.modelId,\n name: entry.modelName,\n references: entry.references,\n transparency: entry.transparency,\n available: entry.available,\n ...(entry.reason ? { reason: entry.reason } : {}),\n ...(entry.isDefault ? { isDefault: true } : {}),\n }))\n return {\n key: auth.key,\n label: config.providers[auth.key]?.label ?? auth.label,\n // JSON copies: `ModelInfo` is data, but a provider may hand out frozen or shared arrays.\n models: JSON.parse(JSON.stringify(config.modelsFor(auth.key))) as HostModelProvider['models'],\n ...(auth.accounts ? { accounts: auth.accounts.map(({ id, label, active }) => ({ id, label, active })) } : {}),\n ...(decisions.length > 0 ? { decisionModels: decisions } : {}),\n ...(images.length > 0 ? { imageModels: images } : {}),\n }\n })\n return { providers }\n },\n 'models.test': async (p) => {\n if (typeof p?.model !== 'string' || !p.model)\n throw new Error('model must be a \"provider/model\" string.')\n const config = p.cwd ? await env.runtimeConfig(folderOf(p.cwd, p.kind)) : env.config\n const build = createProviderBuilder(env)\n return testModel({\n providers: config.providers,\n buildProvider: (key, account) => build(config.providers, key as ProviderKey, account),\n model: p.model,\n })\n },\n 'decisions.test': async (p) => {\n const config = p?.cwd ? await env.runtimeConfig(folderOf(p.cwd, p.kind)) : env.config\n env.applyAuthEnv?.()\n const model = typeof p?.model === 'string' ? p.model : env.readSettings().decisionModel\n return testDecisionModel({\n providers: config.providers,\n buildProvider: (key) => {\n const descriptor = config.providers[key]\n if (!descriptor)\n throw new Error(`Provider \"${key}\" is not configured`)\n return descriptor.factory()\n },\n ...(model ? { decisionModel: model } : {}),\n })\n },\n }\n}\n","/**\n * Session artifacts: list, delete, upsert, re-resolve (a kind's `resolve()`,\n * run here with the extensions of the folder the artifact landed in), with\n * change fan-out, and the sidebar rows' badges.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { ExtensionRegistry } from '../../../extensions/index'\nimport type { SessionStore } from '../../../session/index'\nimport type { HostSignal } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { Handlers } from './types'\nimport { ARTIFACT_BADGES_MAX, refreshArtifact, sessionsBadges } from '../../../extensions/index'\nimport { normalizeArtifactInput } from '../../../session/artifacts'\nimport { catalogFolder } from './catalogs'\nimport { InvalidParamsError, sessionIdOf } from './params'\n\n/** Wire-supplied limit → sane positive integer capped at 1000, else `undefined` (no limit). */\nfunction boundedLimit(raw: unknown): number | undefined {\n return Number.isInteger(raw) && (raw as number) > 0 ? Math.min(raw as number, 1000) : undefined\n}\n\nexport function createArtifactHandlers({ store, broadcast, env, host }: {\n store: SessionStore\n broadcast: (signal: HostSignal) => void\n env: DaemonEnvironment\n host: Pick<ChatHost, 'resolveFolder'>\n}): Handlers<'sessions.artifacts' | 'artifacts.list' | 'artifacts.delete' | 'artifacts.upsert' | 'artifacts.refresh' | 'artifacts.badges'> {\n /** The registry of the folder an artifact landed in; `undefined` (the built-in kinds) when it can't be built (a folder gone, or outside the roots). */\n const registryOf = async (projectRoot: string | undefined): Promise<ExtensionRegistry | undefined> => {\n try {\n return (await env.runtimeConfig(catalogFolder({ env, host }, projectRoot ?? ''))).extensions\n }\n catch {\n return undefined\n }\n }\n return {\n 'sessions.artifacts': async (p) => {\n if (!store.listArtifacts)\n return []\n return store.listArtifacts({\n sessionId: p.sessionId,\n ...(typeof p.kind === 'string' ? { kind: p.kind } : {}),\n ...(boundedLimit(p.limit) !== undefined ? { limit: boundedLimit(p.limit) } : {}),\n })\n },\n 'artifacts.list': async (p) => {\n if (!store.listArtifacts)\n return []\n return store.listArtifacts({\n // Tri-state: `null` selects untagged sessions, omitted ignores the axis.\n ...(p.projectRoot === null || typeof p.projectRoot === 'string' ? { projectRoot: p.projectRoot } : {}),\n ...(typeof p.kind === 'string' ? { kind: p.kind } : {}),\n ...(typeof p.uri === 'string' ? { uri: p.uri } : {}),\n ...(typeof p.since === 'number' && Number.isFinite(p.since) ? { since: p.since } : {}),\n ...(boundedLimit(p.limit) !== undefined ? { limit: boundedLimit(p.limit) } : {}),\n })\n },\n 'artifacts.delete': async (p) => {\n if (!store.deleteArtifact)\n return false\n await store.deleteArtifact(p.sessionId, p.artifactId)\n broadcast({ kind: 'artifact:changed', sessionId: p.sessionId, op: 'delete', artifactId: p.artifactId })\n return true\n },\n 'artifacts.upsert': async (p) => {\n if (!store.upsertArtifact)\n return null\n // Wire input: re-normalize the presentation fields (bounds, kind\n // shape) before trusting them; identity fields pass through since\n // the store merges onto the existing row anyway.\n const normalized = normalizeArtifactInput(p.artifact)\n if (!normalized || typeof p.artifact?.sessionId !== 'string' || typeof p.artifact?.id !== 'string')\n return null\n const now = Date.now()\n const stored = await store.upsertArtifact({\n ...normalized,\n id: p.artifact.id,\n sessionId: p.artifact.sessionId,\n ...(typeof p.artifact.runId === 'string' ? { runId: p.artifact.runId } : {}),\n ...(typeof p.artifact.turnId === 'string' ? { turnId: p.artifact.turnId } : {}),\n createdAt: typeof p.artifact.createdAt === 'number' ? p.artifact.createdAt : now,\n updatedAt: now,\n })\n if (stored)\n broadcast({ kind: 'artifact:changed', sessionId: stored.sessionId, op: 'upsert', artifactId: stored.id, artifact: stored })\n return stored\n },\n 'artifacts.refresh': async (p) => {\n const sessionId = sessionIdOf(p)\n if (!store.listArtifacts || !store.upsertArtifact)\n return null\n const artifact = (await store.listArtifacts({ sessionId })).find(a => a.id === p.artifactId)\n if (!artifact)\n return null\n const updated = await refreshArtifact(artifact, await registryOf(artifact.projectRoot), p.force === true ? { force: true } : undefined)\n if (!updated)\n return null\n const stored = await store.upsertArtifact(updated)\n if (stored)\n broadcast({ kind: 'artifact:changed', sessionId: stored.sessionId, op: 'upsert', artifactId: stored.id, artifact: stored })\n return stored\n },\n 'artifacts.badges': async (p) => {\n const ids: unknown = p.sessionIds\n if (!Array.isArray(ids) || ids.length > ARTIFACT_BADGES_MAX || ids.some(id => typeof id !== 'string'))\n throw new InvalidParamsError(`sessionIds must be an array of at most ${ARTIFACT_BADGES_MAX} session ids.`)\n if (!store.listArtifacts)\n return {}\n const list = store.listArtifacts.bind(store)\n const lists = Object.fromEntries(await Promise.all([...new Set(ids as string[])].map(async sessionId => [sessionId, await list({ sessionId })] as const)))\n const roots = [...new Set(Object.values(lists).flat().map(a => a.projectRoot ?? ''))]\n const registries = new Map(await Promise.all(roots.map(async root => [root, await registryOf(root)] as const)))\n return sessionsBadges(lists, root => registries.get(root))\n },\n }\n}\n","/**\n * The host's provider credentials, managed by a client (Settings on a\n * window attached to a zidane-server): status, set an API key (with a\n * provider's custom fields: `auth.configure`), remove, pick the active\n * stored credential, rename an OAuth account.\n * Secrets go in, never out: statuses carry sources, labels and env var\n * names only, and nothing here logs a key.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { ProviderDescriptor } from '../../../chat/providers'\nimport type { HostProviderAuth } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { Handlers } from './types'\nimport { detectAuth } from '../../../chat/auth'\nimport { applyApiKeyEnv, configuredProviderFields, configureProviderCredential, providerFieldViews, readProviderCredentials, removeProviderCredential, removeStoredCredential, setCredentialLabel, setPreferredCredential, setProviderCredential } from '../../../chat/credentials'\nimport { InvalidParamsError } from './params'\n\n/** Longest API key accepted (keys are well under 1 KiB; this bounds a mistaken paste). */\nconst MAX_KEY_LENGTH = 8192\n/** Longest account name accepted. */\nconst MAX_LABEL_LENGTH = 200\n\nexport type ProviderAuth = ReturnType<typeof createProviderAuth>\n\n/** The host's providers and their credentials: lookups, statuses, and applying a change. */\nexport function createProviderAuth({ host, env }: { host: Pick<ChatHost, 'rebuildAllAgents'>, env: DaemonEnvironment }) {\n const registry = (): Readonly<Record<string, ProviderDescriptor>> => env.config.providers\n const dataDir = (): string => env.userDataDir()\n\n const descriptorOf = (provider: unknown): ProviderDescriptor => {\n const descriptor = typeof provider === 'string' ? registry()[provider] : undefined\n if (!descriptor)\n throw new Error(`Unknown provider \"${String(provider)}\".`)\n return descriptor\n }\n\n const statusOf = (key: string): HostProviderAuth => {\n const descriptor = registry()[key]!\n const auth = detectAuth(dataDir(), { [key]: descriptor })[0]!\n const customFields = providerFieldViews(descriptor)\n const configuredFields = configuredProviderFields(dataDir(), descriptor)\n return {\n key: auth.key,\n label: auth.label,\n configured: auth.available,\n oauth: registry()[key]?.oauthProvider !== undefined,\n ...(auth.envKey ? { envKey: auth.envKey } : {}),\n methods: auth.methods.map(m => ({\n source: m.source,\n active: m.active === true,\n ...(m.key !== undefined ? { key: m.key } : {}),\n ...(m.label !== undefined ? { label: m.label } : {}),\n detail: m.detail,\n })),\n ...(customFields ? { customFields } : {}),\n ...(configuredFields ? { configuredFields } : {}),\n }\n }\n\n /** The stored API key values of a provider (to clear them from the environment once removed). */\n const storedKeys = (descriptor: ProviderDescriptor): string[] =>\n readProviderCredentials(dataDir(), descriptor).flatMap(s => s.credential.kind === 'apikey' && s.credential.value ? [s.credential.value] : [])\n\n /** Make the change take effect: env re-applied, a removed key out of it, agents rebuilt. */\n const applied = (descriptor: ProviderDescriptor, removedKeys: readonly string[] = []): void => {\n if (env.applyAuthEnv)\n env.applyAuthEnv()\n else\n applyApiKeyEnv(dataDir(), registry(), { log: () => undefined })\n // `applyApiKeyEnv` leaves the env alone when nothing is stored; a key it\n // put there earlier must not outlive its removal.\n const envKey = descriptor.envKey\n if (envKey && removedKeys.includes(process.env[envKey] ?? '') && !storedKeys(descriptor).includes(process.env[envKey]!))\n delete process.env[envKey]\n void host.rebuildAllAgents().catch(() => undefined)\n }\n\n return { registry, dataDir, descriptorOf, statusOf, storedKeys, applied }\n}\n\nexport function createAuthHandlers({ auth }: { auth: ProviderAuth }): Handlers<'auth.status' | 'auth.setApiKey' | 'auth.configure' | 'auth.remove' | 'auth.setPreferred' | 'auth.rename'> {\n const { registry, dataDir, descriptorOf, statusOf, storedKeys, applied } = auth\n return {\n 'auth.status': () => ({ providers: Object.keys(registry()).map(statusOf) }),\n 'auth.setApiKey': (p) => {\n const descriptor = descriptorOf(p.provider)\n const key = typeof p.key === 'string' ? p.key.trim() : ''\n if (!key)\n throw new Error('The API key is empty.')\n if (key.length > MAX_KEY_LENGTH)\n throw new Error(`The API key is longer than ${MAX_KEY_LENGTH} characters.`)\n setProviderCredential(dataDir(), descriptor, { kind: 'apikey', value: key })\n applied(descriptor)\n return statusOf(descriptor.key)\n },\n 'auth.configure': (p) => {\n const descriptor = descriptorOf(p.provider)\n if (p.value !== undefined && (typeof p.value !== 'string' || p.value.length > MAX_KEY_LENGTH))\n throw new InvalidParamsError(`value must be a string of at most ${MAX_KEY_LENGTH} characters.`)\n const fields = p.customFields ?? {}\n if (typeof fields !== 'object' || Array.isArray(fields) || Object.values(fields).some(v => typeof v !== 'string' || v.length > MAX_KEY_LENGTH))\n throw new InvalidParamsError('customFields must map field keys to strings.')\n configureProviderCredential(dataDir(), descriptor, { ...(p.value !== undefined ? { value: p.value } : {}), customFields: fields })\n applied(descriptor)\n return statusOf(descriptor.key)\n },\n 'auth.remove': (p) => {\n const descriptor = descriptorOf(p.provider)\n const before = storedKeys(descriptor)\n let removed: boolean\n if (typeof p.account === 'string') {\n removed = removeStoredCredential(dataDir(), descriptor, p.account)\n }\n else {\n removed = readProviderCredentials(dataDir(), descriptor).length > 0\n removeProviderCredential(dataDir(), descriptor)\n }\n if (removed)\n applied(descriptor, before.filter(k => !storedKeys(descriptor).includes(k)))\n return { removed, provider: statusOf(descriptor.key) }\n },\n 'auth.setPreferred': (p) => {\n const descriptor = descriptorOf(p.provider)\n const target = p.target\n const key = typeof target === 'object' && target !== null ? (target as { key?: unknown }).key : undefined\n if (target !== 'apikey' && target !== 'oauth' && typeof key !== 'string')\n throw new InvalidParamsError('target must be \"apikey\", \"oauth\" or { key }.')\n const outcome = setPreferredCredential(dataDir(), descriptor, typeof key === 'string' ? { key } : target as 'apikey' | 'oauth')\n if (outcome === 'not-stored')\n throw new Error(`No stored ${typeof key === 'string' ? `credential ${key}` : `${String(target)} credential`} for ${descriptor.label}.`)\n if (outcome !== 'already-active')\n applied(descriptor)\n return statusOf(descriptor.key)\n },\n 'auth.rename': (p) => {\n const descriptor = descriptorOf(p.provider)\n if (typeof p.account !== 'string' || typeof p.label !== 'string' || p.label.length > MAX_LABEL_LENGTH)\n throw new InvalidParamsError(`account must be a string and label a string of at most ${MAX_LABEL_LENGTH} characters.`)\n if (!setCredentialLabel(dataDir(), descriptor, p.account, p.label))\n throw new Error(`No stored OAuth account ${p.account} for ${descriptor.label}.`)\n return statusOf(descriptor.key)\n },\n }\n}\n","/** Browser hosts a client registers to serve the agent's browser tool. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\n\nexport function createBrowserHandlers({ host }: { host: ChatHost }): {\n methods: Handlers<'browser.registerHost' | 'browser.unregisterHost' | 'browser.respond'>\n /** The peer dropped: release the browser hosts it registered. */\n releasePeer: (peer: HostPeer) => void\n} {\n return {\n methods: {\n 'browser.registerHost': (p, peer) => {\n ;(peer.browserHosts ??= new Set()).add(p.hostId)\n host.browser.registerHost(p.hostId)\n return { ok: true }\n },\n 'browser.unregisterHost': (p, peer) => {\n peer.browserHosts?.delete(p.hostId)\n host.browser.unregisterHost(p.hostId)\n return { ok: true }\n },\n 'browser.respond': (p, peer) => host.browser.respond(p.requestId, p.response, peer.browserHosts ?? new Set()),\n },\n releasePeer(peer) {\n for (const hostId of peer.browserHosts ?? [])\n host.browser.unregisterHost(hostId)\n },\n }\n}\n","/**\n * Installs and removals from a client (`catalog.install` / `remove` /\n * `update`, `mcp.upsert` / `remove`, a new extension's scaffold\n * `extensions.create`): the local Settings actions, run on the host for a\n * window attached to a zidane-server. The Claude Code import goes through\n * the same gate (`guardedInstall`, `./onboarding`).\n *\n * Scope: the host user's only (`~/.agents/*`, `~/.<prefix>/*`). A\n * project's skills, extensions and MCP servers are files in its folder,\n * which the agent and the files panel already edit; installing into one\n * from a client would run a package manager inside a workspace for no gain.\n *\n * Installs fetch code and may run package managers ON THE HOST, so a\n * zidane-server gates them (`allowRemoteInstalls`, on by default: a client\n * token already runs commands there) and audits every attempt, refused or\n * failed ones too, with the token. Specs are GitHub or npm only (a path is\n * refused), work is bounded in time, progress lines come back with the\n * result. MCP `env` / `headers` values go into the host's `mcps.json` and\n * never come back. After a change the host rebuilds what reads it and\n * every window gets `catalog:changed`.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostSettings } from '../../../chat/host/signals'\nimport type { InstallIo } from '../../../install/source'\nimport type { McpServerConfig } from '../../../types'\nimport type { HostCatalogName, HostSignal } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { existsSync, rmSync } from 'node:fs'\nimport { homedir } from 'node:os'\nimport { join } from 'node:path'\nimport { enabledMcpsWith, enabledMcpsWithout } from '../../../chat/mcp-allowlist'\nimport { createFileMcpCredentialStore } from '../../../chat/mcp-credentials'\nimport { isMcpServerName, mcpsWritePath, removeMcpServer, upsertMcpServer } from '../../../chat/mcps-write'\nimport { findGitRoot } from '../../../chat/project-root'\nimport { projectUserPaths } from '../../../chat/project-user-paths'\nimport { createExtension } from '../../../extension-authoring'\nimport { ExtensionInstallError, installExtensionFromSpec, removeInstalledExtension, updateInstalledExtension } from '../../../extensions/install'\nimport { abortableInstallIo } from '../../../install/source'\nimport { saveMcpClientSecret } from '../../../mcp/oauth-provider'\nimport { installSkillFromSpec } from '../../../skills/install'\nimport { InvalidParamsError } from './params'\n\nexport interface RemoteInstallsOptions {\n /** `allowRemoteInstalls`, read at each call. */\n allowed: () => boolean\n /** One audit line per attempt (the server adds the connection's token). */\n audit?: (peer: HostPeer, entry: Record<string, unknown>) => void\n /** Test seam: the installers' fetch / exec / which. */\n io?: InstallIo\n /** Bound on one install or update. Default 5 minutes. */\n timeoutMs?: number\n}\n\ntype InstallMethod = 'catalog.install' | 'catalog.remove' | 'catalog.update' | 'mcp.upsert' | 'mcp.remove' | 'extensions.create'\n\nconst DEFAULT_TIMEOUT_MS = 5 * 60_000\nconst MAX_SPEC_LENGTH = 500\nconst MAX_MCP_CONFIG_BYTES = 64 * 1024\nconst NAME_RE = /^[\\w@.-]{1,100}$/\nconst MCP_TRANSPORTS = new Set(['stdio', 'sse', 'streamable-http'])\n\nconst OFF_MESSAGE = 'Installs from clients are off on this server (allowRemoteInstalls is off).'\n\n/** A spec a server may fetch: GitHub or npm. Anything path-like is refused before the parsers see it. */\nfunction checkSpec(spec: unknown): string {\n if (typeof spec !== 'string' || spec.trim() === '')\n throw new InvalidParamsError('spec must be a non-empty string.')\n const value = spec.trim()\n if (value.length > MAX_SPEC_LENGTH)\n throw new InvalidParamsError(`spec is longer than ${MAX_SPEC_LENGTH} characters.`)\n const segments = value.split(/[/:#@]/)\n if (/^(?:[./~\\\\]|file:)/i.test(value) || value.includes('\\\\') || segments.includes('.') || segments.includes('..'))\n throw new InvalidParamsError(`\"${value}\" is a path: a server installs from GitHub (owner/repo, a GitHub URL) or npm only.`)\n return value\n}\n\nfunction checkName(name: unknown, what: string): string {\n if (typeof name !== 'string' || !NAME_RE.test(name) || name === '.' || name === '..')\n throw new InvalidParamsError(`${what} must be a plain name (letters, digits, ., _, -, @).`)\n return name\n}\n\nfunction checkMcpName(name: unknown): string {\n if (!isMcpServerName(name))\n throw new InvalidParamsError('name must be a plain name (letters, digits, ., _, -, @, single spaces inside).')\n return name\n}\n\nfunction checkKind(kind: unknown): 'skill' | 'extension' {\n if (kind !== 'skill' && kind !== 'extension')\n throw new InvalidParamsError('kind must be \"skill\" or \"extension\".')\n return kind\n}\n\nfunction isStringRecord(value: unknown): value is Record<string, string> {\n return typeof value === 'object' && value !== null && !Array.isArray(value) && Object.values(value).every(v => typeof v === 'string')\n}\n\nfunction checkMcpConfig(config: unknown): McpServerConfig {\n if (typeof config !== 'object' || config === null || Array.isArray(config))\n throw new InvalidParamsError('config must be an MCP server object.')\n if (JSON.stringify(config).length > MAX_MCP_CONFIG_BYTES)\n throw new InvalidParamsError(`config is larger than ${MAX_MCP_CONFIG_BYTES} bytes.`)\n const c = config as Record<string, unknown>\n checkMcpName(c.name)\n if (c.transport !== undefined && !MCP_TRANSPORTS.has(c.transport as string))\n throw new InvalidParamsError('transport must be stdio, sse or streamable-http.')\n const hasCommand = typeof c.command === 'string' && c.command.trim() !== ''\n let hasUrl = false\n if (typeof c.url === 'string') {\n try {\n hasUrl = ['http:', 'https:'].includes(new URL(c.url).protocol)\n }\n catch {}\n if (!hasUrl)\n throw new InvalidParamsError('url must be an http(s) URL.')\n }\n if (!hasCommand && !hasUrl)\n throw new InvalidParamsError('An MCP server needs a command (stdio) or a url.')\n if (c.args !== undefined && (!Array.isArray(c.args) || !c.args.every(a => typeof a === 'string')))\n throw new InvalidParamsError('args must be strings.')\n for (const key of ['env', 'headers'] as const) {\n if (c[key] !== undefined && !isStringRecord(c[key]))\n throw new InvalidParamsError(`${key} must map names to strings.`)\n }\n return c as unknown as McpServerConfig\n}\n\n/** How long a stopped install may take to roll back before the refusal is answered anyway. */\nconst ROLLBACK_GRACE_MS = 10_000\n\n/**\n * `run` bounded by `ms`: past it, its signal fires (children killed, no next\n * step: `abortableInstallIo`) and the refusal waits for the installer's own\n * rollback (staging dir, transactional target), up to {@link ROLLBACK_GRACE_MS}.\n */\nasync function bounded<T>(run: (signal: AbortSignal) => Promise<T>, ms: number, what: string): Promise<T> {\n const controller = new AbortController()\n const work = run(controller.signal)\n let timer: ReturnType<typeof setTimeout> | undefined\n try {\n return await Promise.race([work, new Promise<never>((_, reject) => {\n timer = setTimeout(() => {\n controller.abort()\n reject(new Error(`${what} took longer than ${Math.round(ms / 1000)}s and was stopped.`))\n }, ms)\n })])\n }\n catch (err) {\n if (controller.signal.aborted) {\n let grace: ReturnType<typeof setTimeout> | undefined\n await Promise.race([work.catch(() => undefined), new Promise((resolve) => {\n grace = setTimeout(resolve, ROLLBACK_GRACE_MS)\n })])\n clearTimeout(grace)\n }\n throw err\n }\n finally {\n clearTimeout(timer)\n }\n}\n\n/**\n * Gate, run, audit a client's install: refused unless the host takes them\n * (`allowRemoteInstalls`); every attempt leaves one line, refusals and\n * failures included.\n */\nexport async function guardedInstall<T>(options: RemoteInstallsOptions | undefined, peer: HostPeer, event: string, fields: Record<string, unknown>, run: () => Promise<T> | T): Promise<T> {\n if (!options)\n throw new Error('This host takes no installs from clients (a zidane-server does, with allowRemoteInstalls on).')\n if (!options.allowed()) {\n options.audit?.(peer, { event, ...fields, ok: false, refused: 'allowRemoteInstalls is off' })\n throw new Error(OFF_MESSAGE)\n }\n try {\n const result = await run()\n options.audit?.(peer, { event, ...fields, ok: true })\n return result\n }\n catch (err) {\n options.audit?.(peer, { event, ...fields, ok: false, error: err instanceof Error ? err.message : String(err) })\n throw err\n }\n}\n\nexport function createCatalogInstallHandlers({ host, env, broadcast, setSettings, options }: {\n host: Pick<ChatHost, 'rebuildAllAgents' | 'workspace' | 'mcpServers'>\n env: DaemonEnvironment\n broadcast: (signal: HostSignal) => void\n /** `settings.set`: writes, rebuilds what the change needs, tells every window. */\n setSettings: (patch: Partial<HostSettings>) => unknown\n options?: RemoteInstallsOptions\n}): Handlers<InstallMethod> {\n const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS\n const io = options?.io\n const prefix = (): string => env.config.prefix\n /** The host user's roots for `subPath` (`~/.agents/<sub>`, `~/.<prefix>/<sub>`), read at call time. */\n const userRoots = (subPath: string): string[] =>\n projectUserPaths({ subPath, cwd: homedir(), home: homedir(), prefix: prefix() }).filter(p => p.source === 'user').map(p => p.path)\n\n const guarded = <T>(peer: HostPeer, event: string, fields: Record<string, unknown>, run: () => Promise<T> | T): Promise<T> =>\n guardedInstall(options, peer, event, fields, run)\n\n const changed = (catalog: HostCatalogName): void => broadcast({ kind: 'catalog:changed', catalog })\n\n /** Skills and MCP servers are read when an agent is built. */\n const rebuild = (): void => {\n void host.rebuildAllAgents({ rediscover: true }).catch(() => undefined)\n }\n\n /** Extensions live in the runtime registry: forget it, rebuild, dispose the old one once idle (as `runtime.reload`). */\n const reloadExtensions = (): void => {\n const disposeOld = env.forgetRuntime()\n void host.rebuildAllAgents({ rediscover: true }).then(disposeOld, disposeOld)\n }\n\n /** `name` dropped from (or added to) an explicit allowlist; an absent list means \"all\", left alone. */\n const allowlist = (key: 'enabledExtensions' | 'enabledSkills', name: string, present: boolean): boolean => {\n const list = env.readSettings()[key]\n if (list === undefined || list.includes(name) === present)\n return false\n setSettings({ [key]: present ? [...list, name] : list.filter(n => n !== name) })\n return true\n }\n\n /** The user-scope install directory named `name` under `subPath`, if any. */\n const userDir = (subPath: string, name: string, marker?: string): string | undefined =>\n userRoots(subPath).map(root => join(root, name)).find(dir => existsSync(marker ? join(dir, marker) : dir))\n\n return {\n 'catalog.install': (p, peer) => guarded(peer, 'catalog.install', { kind: p.kind, spec: typeof p.spec === 'string' ? p.spec.slice(0, MAX_SPEC_LENGTH) : undefined }, async () => {\n const kind = checkKind(p.kind)\n const spec = checkSpec(p.spec)\n if (p.scope !== undefined && p.scope !== 'user')\n throw new InvalidParamsError('A server installs in its user scope only (scope: \"user\").')\n const progress: string[] = []\n const onProgress = (line: string): void => {\n if (progress.length < 200)\n progress.push(line)\n }\n const home = homedir()\n if (kind === 'skill') {\n const result = await bounded(signal => installSkillFromSpec({\n source: spec,\n scope: 'user',\n cwd: home,\n home,\n prefix: prefix(),\n onProgress,\n io: abortableInstallIo(io, signal),\n ...(Array.isArray(p.skills) ? { skills: p.skills.filter(s => typeof s === 'string') } : {}),\n ...(p.all === true ? { all: true } : {}),\n ...(p.overwrite === true ? { overwrite: true } : {}),\n }), timeoutMs, `Installing ${spec}`)\n rebuild()\n changed('skills')\n const skipped = result.skipped?.length ? `. Skipped existing: ${result.skipped.join(', ')}` : ''\n return { installed: [...result.installed], message: `installed ${result.installed.join(', ')} (${result.provenance ?? result.engine})${skipped}`, progress }\n }\n let result\n try {\n result = await bounded(signal => installExtensionFromSpec({\n source: spec,\n scope: 'user',\n cwd: home,\n home,\n prefix: prefix(),\n onProgress,\n io: abortableInstallIo(io, signal),\n ...(typeof p.extension === 'string' ? { extension: p.extension } : {}),\n ...(p.overwrite === true ? { overwrite: true } : {}),\n }), timeoutMs, `Installing ${spec}`)\n }\n catch (err) {\n if (err instanceof ExtensionInstallError && err.code === 'exists')\n throw new Error('already installed on the server: update or remove it first.')\n throw err\n }\n // Enabled in an explicit allowlist (that write reloads the registry); else reload here.\n if (!allowlist('enabledExtensions', result.name, true))\n reloadExtensions()\n changed('extensions')\n const warn = result.warnings.length > 0 ? `. ${result.warnings.join('. ')}` : ''\n return { installed: [result.name], message: `installed \"${result.name}\" (${result.provenance})${warn}`, progress }\n }),\n\n 'catalog.remove': (p, peer) => guarded(peer, 'catalog.remove', { kind: p.kind, name: p.name }, async () => {\n const kind = checkKind(p.kind)\n const name = checkName(p.name, 'name')\n if (kind === 'skill') {\n const dir = userDir('skills', name, 'SKILL.md')\n if (!dir)\n throw new Error(`No user-scope skill \"${name}\" on this server (project skills are files in their folder).`)\n rmSync(dir, { recursive: true, force: true })\n allowlist('enabledSkills', name, false)\n rebuild()\n changed('skills')\n return { removed: name, message: `deleted \"${name}\"` }\n }\n const dir = userDir('extensions', name)\n if (!dir)\n throw new Error(`No user-scope extension \"${name}\" on this server.`)\n removeInstalledExtension({ dir, cwd: homedir(), home: homedir(), prefix: prefix() })\n if (!allowlist('enabledExtensions', name, false))\n reloadExtensions()\n changed('extensions')\n return { removed: name, message: `removed \"${name}\"` }\n }),\n\n 'catalog.update': (p, peer) => guarded(peer, 'catalog.update', { kind: p.kind, name: p.name }, async () => {\n const kind = checkKind(p.kind)\n const name = checkName(p.name, 'name')\n if (kind === 'skill')\n throw new Error('Skills are not updated in place: install again with overwrite.')\n const dir = userDir('extensions', name)\n if (!dir)\n throw new Error(`No user-scope extension \"${name}\" on this server.`)\n const result = await bounded(signal => updateInstalledExtension({ dir, cwd: homedir(), home: homedir(), prefix: prefix(), io: abortableInstallIo(io, signal) }), timeoutMs, `Updating ${name}`)\n if (result.upToDate)\n return { updated: result.name, upToDate: true, message: `\"${result.name}\" is already up to date${result.commit ? ` (${result.commit.slice(0, 7)})` : ''}` }\n reloadExtensions()\n changed('extensions')\n return { updated: result.name, upToDate: false, message: `updated \"${result.name}\" → ${result.provenance}` }\n }),\n\n 'mcp.upsert': (p, peer) => guarded(peer, 'mcp.upsert', { name: (p.config as { name?: unknown } | undefined)?.name, scope: p.scope ?? 'user' }, () => {\n const config = checkMcpConfig(p.config)\n if (p.scope !== undefined && p.scope !== 'user' && p.scope !== 'project')\n throw new InvalidParamsError('scope must be \"user\" or \"project\".')\n if (p.clientSecret !== undefined && (typeof p.clientSecret !== 'string' || p.clientSecret.length > MAX_MCP_CONFIG_BYTES))\n throw new InvalidParamsError('clientSecret must be a string.')\n if (p.scope === 'project' && (typeof p.cwd !== 'string' || !p.cwd))\n throw new InvalidParamsError('A project MCP server needs the project\\'s cwd.')\n // The project's checkout, which must lie in the roots too.\n const folder = p.scope === 'project' ? host.workspace.resolveFolder(p.cwd!) : homedir()\n const cwd = p.scope === 'project' ? host.workspace.resolveFolder(findGitRoot(folder) ?? folder) : folder\n const result = upsertMcpServer(mcpsWritePath(p.scope ?? 'user', { home: homedir(), cwd, prefix: prefix() }), config)\n const store = env.mcpCredentialStore?.() ?? createFileMcpCredentialStore(env.userDataDir())\n // The secret stays out of mcps.json; an entry without an oauth client must not keep sending one.\n if (!config.oauth)\n saveMcpClientSecret(store, config.name, undefined)\n else if (p.clientSecret)\n saveMcpClientSecret(store, config.name, p.clientSecret)\n // Added from a client: on, like a server added in local Settings. An edit keeps its toggle.\n const enabled = result.action === 'added' ? enabledMcpsWith(env.readSettings().enabledMcps, config.name) : undefined\n if (enabled)\n setSettings({ enabledMcps: enabled })\n // An edited server must not keep running on its old config.\n host.mcpServers.retire(config.name)\n rebuild()\n changed('mcps')\n return { name: config.name, created: result.action === 'added' }\n }),\n\n 'mcp.remove': (p, peer) => guarded(peer, 'mcp.remove', { name: p.name }, () => {\n const name = checkMcpName(p.name)\n const path = mcpsWritePath('user', { home: homedir(), cwd: homedir(), prefix: prefix() })\n try {\n removeMcpServer(path, name)\n }\n catch (err) {\n // No file, or no entry of that name: nothing to remove. A malformed file is an error.\n if (!existsSync(path) || /no entry named/.test(err instanceof Error ? err.message : ''))\n return { removed: false }\n throw err\n }\n const enabled = enabledMcpsWithout(env.readSettings().enabledMcps, name)\n if (enabled)\n setSettings({ enabledMcps: enabled })\n host.mcpServers.retire(name)\n rebuild()\n changed('mcps')\n return { removed: true }\n }),\n\n 'extensions.create': (p, peer) => guarded(peer, 'extensions.create', { name: p.name, scope: p.scope ?? 'user' }, () => {\n if (p.scope !== undefined && p.scope !== 'user' && p.scope !== 'project')\n throw new InvalidParamsError('scope must be \"user\" or \"project\".')\n const project = p.scope === 'project'\n if (project && (typeof p.cwd !== 'string' || !p.cwd))\n throw new InvalidParamsError('A project extension needs the project\\'s cwd.')\n const result = createExtension({ name: typeof p.name === 'string' ? p.name : '', ...(project ? { scope: 'project', cwd: p.cwd } : {}) }, {\n userDir: join(homedir(), prefix()),\n // The checkout holding `cwd`, which must lie in the roots too: the session that writes the extension works there.\n resolveCheckoutRoot: (cwd) => {\n const folder = host.workspace.resolveFolder(cwd)\n return host.workspace.resolveFolder(findGitRoot(folder) ?? folder)\n },\n })\n // A project extension loads once its project is trusted; a user one is enabled now.\n if (project || !allowlist('enabledExtensions', result.name, true))\n reloadExtensions()\n changed('extensions')\n return result\n }),\n\n }\n}\n\n/** For `ipc.hello`: installs are offered when the server allows them. */\nexport function remoteInstallsAllowed(options: RemoteInstallsOptions | undefined): boolean {\n return options?.allowed() === true\n}\n","/**\n * Who or what a text block of a user turn comes from, when it is not the\n * session's own user typing in a window. Dependency-free, like\n * `thinking-levels.ts`, so any surface can read and check it.\n */\n\n/** Where a text block came from: the {@link SessionContentBlock} text member's `origin`. Absent: the session's own user. */\nexport interface TextOrigin {\n /** 'user': the session's user, through another surface; 'signal': someone else (a channel participant); 'event': something that happened (orchestration, a webhook). */\n kind: 'user' | 'signal' | 'event'\n /** Where it came from: 'slack', 'github', 'orchestration'… */\n source: string\n /** Who, when known: a provider id and a display name. */\n sender?: { id: string, name?: string }\n /** The client's id for this message (see clientMessageId), so a client can find it in the transcript after a restart. */\n messageId?: string\n}\n\n/** Longest string a {@link TextOrigin} field may hold. */\nconst MAX_FIELD_CHARS = 1024\n\nconst TEXT_ORIGIN_KINDS: readonly string[] = ['user', 'signal', 'event'] satisfies readonly TextOrigin['kind'][]\n\nfunction isField(value: unknown): value is string {\n return typeof value === 'string' && value.length > 0 && value.length <= MAX_FIELD_CHARS\n}\n\n/**\n * Type guard for a {@link TextOrigin} read off the wire: a known `kind`, a\n * non-empty `source`, and well-formed optional fields, each string at most\n * 1024 characters.\n *\n * @param value - Any value, usually a peer's request param.\n */\nexport function isTextOrigin(value: unknown): value is TextOrigin {\n if (!value || typeof value !== 'object')\n return false\n const { kind, source, sender, messageId } = value as Record<string, unknown>\n if (typeof kind !== 'string' || !TEXT_ORIGIN_KINDS.includes(kind) || !isField(source))\n return false\n if (messageId !== undefined && !isField(messageId))\n return false\n if (sender === undefined)\n return true\n if (!sender || typeof sender !== 'object')\n return false\n const { id, name } = sender as Record<string, unknown>\n return isField(id) && (name === undefined || isField(name))\n}\n","/**\n * Idempotent sends: the optional `requestId` of `chat.send`,\n * `chat.pushQueued` and `queue.add`.\n *\n * A client that lost a send's reply retries with the same `requestId`. Per\n * session, the first send with an id runs; a later one with the same id and\n * the same content gets the first one's result without running again, and\n * one with other content is refused. The claim and the result live in the\n * session store (`claimSendRequest`), so this holds across a host restart.\n *\n * - A duplicate of a send still running in this process waits for it and\n * gets its result (or its error).\n * - A send that failed drops its claim: nothing ran, so the retry runs.\n * - A claim with no result and no send running here (still running in another\n * process, or its process died before it settled) answers\n * {@link SendRequestPendingError}: the prompt may have been accepted, so it\n * is not submitted again.\n * - If dropping a failed send's claim fails too, this process remembers it, so\n * a retry here still runs.\n * - A store without `claimSendRequest` deduplicates in this process only.\n */\nimport type { SessionStore } from '../../session'\nimport type { SendRequestClaim } from '../../session/send-requests'\nimport type { JsonValue } from '../../types'\nimport { createHash } from 'node:crypto'\nimport { createSendRequestBook } from '../../session/send-requests'\nimport { InvalidParamsError } from './handlers/params'\n\n/** Longest `requestId` accepted (a UUID is 36 characters). */\nconst MAX_REQUEST_ID_LENGTH = 128\n\n/** Params that never change what a send submits: left out of its fingerprint. */\nconst NOT_CONTENT = new Set(['sessionId', 'requestId', 'keepDraft', 'wake'])\n\n/** A retried `requestId` whose first send was accepted but has not settled (still running elsewhere, or its host stopped first). */\nexport class SendRequestPendingError extends Error {\n constructor(requestId: string) {\n super(`Send request \"${requestId}\" was already accepted; its outcome is unknown (it may still be running in another host process, or its host stopped before it settled), so it was not submitted again.`)\n this.name = 'SendRequestPendingError'\n }\n}\n\nexport interface SendDedup {\n /** Run `call` for the send `params` of `method`, or answer the first outcome of its `requestId`. Without one, just runs `call`. */\n run: <T>(method: string, params: { sessionId: string, requestId?: unknown }, call: () => Promise<T>) => Promise<T>\n /** The content hash a send's `requestId` is bound to. */\n fingerprint: (method: string, params: object) => string\n}\n\nexport function createSendDedup({ store }: { store: SessionStore }): SendDedup {\n const local = createSendRequestBook()\n const claim = async (sessionId: string, requestId: string, fp: string): Promise<SendRequestClaim> =>\n store.claimSendRequest ? store.claimSendRequest(sessionId, requestId, fp) : local.claim(sessionId, requestId, fp)\n const settle = async (sessionId: string, requestId: string, result: JsonValue | null): Promise<void> => {\n if (store.settleSendRequest)\n await store.settleSendRequest(sessionId, requestId, result)\n else\n local.settle(sessionId, requestId, result)\n }\n /** Sends running here, by `sessionId \\0 requestId`: a duplicate waits for the first. */\n const running = new Map<string, { fingerprint: string, outcome: Promise<unknown> }>()\n /** Failed sends whose claim could not be dropped from the store, by key: a retry here runs anyway. */\n const failedHere = new Set<string>()\n\n const fingerprint = (method: string, params: object): string => {\n const content = Object.fromEntries(Object.entries(params).filter(([key]) => !NOT_CONTENT.has(key)))\n return createHash('sha256').update(stableJson({ method, ...content })).digest('hex')\n }\n\n const refuse = (requestId: string): never => {\n throw new InvalidParamsError(`requestId \"${requestId}\" was already used for a different send in this session; use a new requestId for new content.`)\n }\n\n return {\n fingerprint,\n async run<T>(method: string, params: { sessionId: string, requestId?: unknown }, call: () => Promise<T>): Promise<T> {\n const { sessionId, requestId } = params\n if (requestId === undefined)\n return call()\n if (typeof requestId !== 'string' || requestId.length === 0 || requestId.length > MAX_REQUEST_ID_LENGTH)\n throw new InvalidParamsError(`requestId must be a non-empty string of at most ${MAX_REQUEST_ID_LENGTH} characters.`)\n const fp = fingerprint(method, params)\n const key = `${sessionId}\\0${requestId}`\n\n const live = running.get(key)\n if (live) {\n if (live.fingerprint !== fp)\n refuse(requestId)\n return live.outcome as Promise<T>\n }\n\n // Registered before the first await, so a concurrent duplicate waits\n // here instead of racing the store claim.\n const outcome = (async () => {\n const claimed = await claim(sessionId, requestId, fp)\n if (!claimed.claimed) {\n if (claimed.record.fingerprint !== fp)\n refuse(requestId)\n if (claimed.record.result !== undefined)\n return claimed.record.result as T\n if (!failedHere.has(key))\n throw new SendRequestPendingError(requestId)\n }\n failedHere.delete(key)\n let result: T\n try {\n result = await call()\n }\n catch (err) {\n // Nothing ran: drop the claim so a retry runs. Retried once; if it still fails, a retry here re-runs anyway.\n const dropped = await settle(sessionId, requestId, null).then(() => true, () => false)\n || await settle(sessionId, requestId, null).then(() => true, () => false)\n if (!dropped)\n failedHere.add(key)\n throw err\n }\n // The send ran: a store failure here must not turn it into an error the client would retry.\n await settle(sessionId, requestId, result as JsonValue).catch(() => undefined)\n return result\n })()\n running.set(key, { fingerprint: fp, outcome })\n try {\n return await outcome\n }\n finally {\n running.delete(key)\n }\n },\n }\n}\n\nconst dedupByStore = new WeakMap<SessionStore, SendDedup>()\n\n/** The one dedup of `store`: every send method of a host shares it (and its in-process waits). */\nexport function sendDedupFor(store: SessionStore): SendDedup {\n let dedup = dedupByStore.get(store)\n if (!dedup) {\n dedup = createSendDedup({ store })\n dedupByStore.set(store, dedup)\n }\n return dedup\n}\n\n/** `dedup.run`, or just `call` without a dedup. */\nexport async function deduped<T>(dedup: SendDedup | undefined, method: string, params: { sessionId: string, requestId?: unknown }, call: () => Promise<T>): Promise<T> {\n return dedup ? dedup.run(method, params, call) : call()\n}\n\n/** JSON with object keys sorted, so a fingerprint does not depend on key order. */\nfunction stableJson(value: unknown): string {\n return JSON.stringify(value, (_key, v: unknown) => {\n if (!v || typeof v !== 'object' || Array.isArray(v))\n return v\n return Object.fromEntries(Object.entries(v).sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0)))\n })\n}\n","/** Runs: send, interrupt, steer, follow-up, running work, and slash-command discovery. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { QueuedPromptFields } from '../../../chat/host/signals'\nimport type { TextOrigin } from '../../../text-origin'\nimport type { SendOptions } from '../../protocol'\nimport type { HostPeer } from '../peers'\nimport type { SendDedup } from '../send-requests'\nimport type { Handlers } from './types'\nimport { isTextOrigin } from '../../../text-origin'\nimport { deduped } from '../send-requests'\nimport { InvalidParamsError } from './params'\n\ntype ChatMethod\n = | 'chat.send' | 'chat.interrupt' | 'chat.steer' | 'chat.followUp' | 'chat.pushQueued'\n | 'chat.isRunning' | 'chat.rebuildAgent' | 'chat.listWork' | 'chat.cancelWork'\n | 'commands.list' | 'commands.completeArgs'\n\nexport function createChatHandlers({ host, clearDraft, dedup }: {\n host: ChatHost\n clearDraft: (sessionId: string, origin: HostPeer | null) => void\n /** Answers a retried `requestId` with its first outcome (`../send-requests`). Absent: `requestId` is ignored. */\n dedup?: SendDedup\n}): Handlers<ChatMethod> {\n return {\n 'chat.send': async (p, peer) => {\n // `wake` is host-internal: a wire peer must not run a session with\n // the `user-prompt` broadcast suppressed (params are unchecked JSON\n // — the Omit<> in the method type is not a runtime guarantee).\n const { wake: _stripped, keepDraft, requestId: _id, origin: _origin, literal: _literal, clientMessageId: _clientMessageId, ...params } = p as SendOptions & { requestId?: string }\n const result = await deduped(dedup, 'chat.send', p, () => host.sendPrompt({ ...params, ...promptFields(p) }))\n // A composer submit consumed the shared draft — clear it everywhere\n // else (the sender's input is already empty; excluding it means a user\n // already typing their NEXT message is never clobbered). A prompt sent\n // from elsewhere (Continue, Retry, the palette) did not.\n if (!keepDraft)\n clearDraft(p.sessionId, peer)\n return result\n },\n 'chat.interrupt': p => host.interrupt(p.sessionId),\n 'chat.steer': p => host.steer(p.sessionId, p.message, clientMessageId(p.clientMessageId)),\n 'chat.followUp': p => host.followUp(p.sessionId, p.message, clientMessageId(p.clientMessageId)),\n 'chat.pushQueued': async (p, peer) => {\n const result = await deduped(dedup, 'chat.pushQueued', p, () => host.pushQueued(p.sessionId, p.message, p.activatedSkills, promptFields(p)))\n if (!p.keepDraft)\n clearDraft(p.sessionId, peer)\n return result\n },\n 'chat.isRunning': p => host.isSessionRunning(p.sessionId),\n 'chat.rebuildAgent': p => host.disposeAgentForRebuild(p.sessionId),\n 'chat.listWork': p => host.listRunningWork(p.sessionId, p.children === true ? { children: true } : undefined),\n 'chat.cancelWork': p => host.cancelRunningWork(p.sessionId, p.id, p.reason),\n\n 'commands.list': p => host.listCommands(p.cwd, typeof p.kind === 'string' ? p.kind : undefined),\n 'commands.completeArgs': p => host.completeCommandArgs(p.cwd, p.name, p.argsPrefix, typeof p.kind === 'string' ? p.kind : undefined),\n }\n}\n\n/** A peer's `origin` / `literal` / `clientMessageId` params, checked (params are unchecked JSON): a malformed origin or id is refused. */\nexport function promptFields(p: { origin?: unknown, literal?: unknown, clientMessageId?: unknown }): QueuedPromptFields {\n if (p.origin !== undefined && !isTextOrigin(p.origin))\n throw new InvalidParamsError('origin: must be { kind: \\'user\\' | \\'signal\\' | \\'event\\', source, sender?: { id, name? }, messageId? } with non-empty strings of at most 1024 characters.')\n const id = clientMessageId(p.clientMessageId)\n return {\n ...(p.origin !== undefined ? { origin: knownOriginFields(p.origin) } : {}),\n ...(p.literal === true ? { literal: true } : {}),\n ...(id !== undefined ? { clientMessageId: id } : {}),\n }\n}\n\n/** A checked origin with only its known fields: it is stored with the turn, so a peer's extra keys are not. */\nfunction knownOriginFields({ kind, source, sender, messageId }: TextOrigin): TextOrigin {\n return {\n kind,\n source,\n ...(sender ? { sender: { id: sender.id, ...(sender.name !== undefined ? { name: sender.name } : {}) } } : {}),\n ...(messageId !== undefined ? { messageId } : {}),\n }\n}\n\n/** A peer's `clientMessageId`, checked: absent, or a non-empty string of at most 256 characters. */\nfunction clientMessageId(value: unknown): string | undefined {\n if (value === undefined)\n return undefined\n if (typeof value !== 'string' || value.length === 0 || value.length > 256)\n throw new InvalidParamsError('clientMessageId: must be a non-empty string of at most 256 characters.')\n return value\n}\n","/**\n * What a host keeps for its clients' apps in its `state.json`, so a web app\n * finds it again in any browser: the picks remembered across apps\n * (`prefs.*`: effort and options per model, the next chat's model chain)\n * and the sidebar's view (`sidebar.*`: each space's filters, checked by the\n * client when read, and the space on show).\n */\nimport type { HostComposerPrefs } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { Handlers } from './types'\nimport { isThinkingLevel } from '../../../types'\nimport { InvalidParamsError } from './params'\n\ntype ClientStateMethod = 'prefs.get' | 'prefs.set' | 'sidebar.getViews' | 'sidebar.setView' | 'sidebar.getSpace' | 'sidebar.setSpace'\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\n/** Each pref's shape: `state.json` is read by every app on the host, a client's junk must not reach it. */\nconst PREF_CHECKS: { [K in keyof Required<HostComposerPrefs>]: (value: unknown) => boolean } = {\n lastEffortByModel: v => isRecord(v) && Object.values(v).every(isThinkingLevel),\n lastModelOptionsByModel: v => isRecord(v) && Object.values(v).every(options => isRecord(options) && Object.values(options).every(on => typeof on === 'boolean')),\n lastModelChain: v => Array.isArray(v) && v.every(entry => isRecord(entry) && typeof entry.provider === 'string' && typeof entry.model === 'string' && (entry.account === undefined || typeof entry.account === 'string')),\n}\nconst PREF_KEYS = Object.keys(PREF_CHECKS) as (keyof HostComposerPrefs)[]\n\n/** Space ids are short slugs (`default`, `space-1`). */\nconst MAX_SPACE_ID = 200\n/** A view is five short fields. */\nconst MAX_VIEW_JSON = 4096\n/** Spaces with a saved view; a client can't grow `state.json` without bound. */\nconst MAX_VIEWS = 100\n\nfunction spaceIdOf(value: unknown): string {\n if (typeof value !== 'string' || value.length === 0 || value.length > MAX_SPACE_ID)\n throw new InvalidParamsError(`spaceId must be a non-empty string of at most ${MAX_SPACE_ID} characters.`)\n return value\n}\n\nexport function createClientStateHandlers({ env }: { env: Pick<DaemonEnvironment, 'config'> }): Handlers<ClientStateMethod> {\n const { stateStore } = env.config\n return {\n 'prefs.get': () => {\n const state = stateStore.load()\n const prefs: HostComposerPrefs = Object.fromEntries(PREF_KEYS.flatMap(key => (state[key] === undefined ? [] : [[key, state[key]]])))\n return Object.keys(prefs).length > 0 ? prefs : null\n },\n 'prefs.set': (p) => {\n const patch: unknown = p.patch\n if (!isRecord(patch))\n throw new InvalidParamsError('patch must be an object.')\n const bad = PREF_KEYS.find(key => key in patch && !PREF_CHECKS[key](patch[key]))\n if (bad)\n throw new InvalidParamsError(`patch.${bad} has the wrong shape.`)\n stateStore.save({ ...stateStore.load(), ...Object.fromEntries(PREF_KEYS.flatMap(key => (key in patch ? [[key, patch[key]]] : []))) })\n },\n 'sidebar.getViews': () => stateStore.load().sidebarViews ?? {},\n 'sidebar.setView': (p) => {\n const spaceId = spaceIdOf(p.spaceId)\n if (!isRecord(p.view))\n throw new InvalidParamsError('view must be an object.')\n if (JSON.stringify(p.view).length > MAX_VIEW_JSON)\n throw new InvalidParamsError(`view must be at most ${MAX_VIEW_JSON} characters of JSON.`)\n const state = stateStore.load()\n const views = state.sidebarViews ?? {}\n if (!(spaceId in views) && Object.keys(views).length >= MAX_VIEWS)\n throw new Error(`This host keeps the views of ${MAX_VIEWS} spaces at most.`)\n stateStore.save({ ...state, sidebarViews: { ...views, [spaceId]: p.view } })\n },\n 'sidebar.getSpace': () => stateStore.load().sidebarSpaceId ?? null,\n 'sidebar.setSpace': (p) => {\n const sidebarSpaceId = spaceIdOf(p.spaceId)\n stateStore.save({ ...stateStore.load(), sidebarSpaceId })\n },\n }\n}\n","/** What a session's model sees: context breakdown and segments, the session's system prompt override, and its prompt cache. */\nimport type { CacheImpactChange, ChatHost } from '../../../chat/host/engine'\nimport type { ThinkingLevel } from '../../../types'\nimport type { Handlers } from './types'\nimport { THINKING_LEVELS } from '../../../types'\nimport { InvalidParamsError, nonNegativeInt, optionalString } from './params'\n\nexport function createContextHandlers({ host }: { host: ChatHost }): Handlers<'sessions.contextBreakdown' | 'sessions.contextSegments' | 'sessions.createSystemOverride' | 'sessions.systemMd' | 'sessions.cacheImpact' | 'sessions.cacheReport'> {\n return {\n 'sessions.systemMd': p => host.sessionSystemMd(p.sessionId),\n 'sessions.contextSegments': p => host.getContextSegments(p.sessionId),\n 'sessions.createSystemOverride': p => host.createSystemOverride(p.sessionId),\n 'sessions.contextBreakdown': p => host.getContextBreakdown(p.sessionId),\n 'sessions.cacheImpact': p => host.cacheImpact(p.sessionId, cacheImpactChange(p.change)),\n 'sessions.cacheReport': p => host.cacheReport(p.sessionId, nonNegativeInt(p.limit, 'limit')),\n }\n}\n\nfunction cacheImpactChange(value: unknown): CacheImpactChange {\n if (typeof value !== 'object' || value === null || Array.isArray(value))\n throw new InvalidParamsError('change must be an object.')\n const raw = value as Record<string, unknown>\n const change: CacheImpactChange = {}\n const modelId = optionalString(raw.modelId, 'change.modelId')\n const providerKey = optionalString(raw.providerKey, 'change.providerKey')\n const agentId = optionalString(raw.agentId, 'change.agentId')\n const effort = optionalString(raw.effort, 'change.effort')\n if (effort !== undefined && !(THINKING_LEVELS as readonly string[]).includes(effort))\n throw new InvalidParamsError('change.effort must be a thinking level.')\n if (modelId !== undefined)\n change.modelId = modelId\n if (providerKey !== undefined)\n change.providerKey = providerKey\n if (agentId !== undefined)\n change.agentId = agentId\n if (effort !== undefined)\n change.effort = effort as ThinkingLevel\n return change\n}\n","/** The daemon process itself: identity, the processes it started for its own work and for each session, and shutdown. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HelloResult } from '../../protocol'\nimport type { Handlers } from './types'\nimport { listOwnedProcesses } from '../../../contexts/owned-processes'\nimport { listSessionProcesses } from '../../../contexts/session-processes'\nimport { IPC_PROTOCOL_VERSION } from '../../protocol'\n\nexport function createDaemonHandlers({ host, appVersion, startedAt, lifecycle, identity }: {\n host: ChatHost\n appVersion: string\n startedAt: number\n lifecycle: { shutdown: () => void, retireWhenIdle: () => void, isRetiring?: () => boolean }\n /** The host identity fields `ipc.hello` reports. */\n identity: Pick<HelloResult, 'hostId' | 'hostKind' | 'hostName'>\n}): Handlers<'daemon.info' | 'daemon.ownedProcesses' | 'daemon.sessionProcesses' | 'daemon.shutdown'> {\n return {\n 'daemon.info': (): HelloResult => ({\n protocolVersion: IPC_PROTOCOL_VERSION,\n appVersion,\n pid: process.pid,\n startedAt,\n ...identity,\n activeWork: host.hasActiveRuns(),\n // Live, unlike the hello: a daemon starts retiring after windows attached (a newer install landed).\n ...(lifecycle.isRetiring?.() ? { retiring: true } : {}),\n }),\n 'daemon.ownedProcesses': () => listOwnedProcesses(),\n 'daemon.sessionProcesses': () => listSessionProcesses(),\n 'daemon.shutdown': async (p) => {\n // Version-skew retirement never aborts live work: exit once idle.\n if (p?.whenIdle === true && host.hasActiveWork()) {\n lifecycle.retireWhenIdle()\n return { deferred: true }\n }\n // Reply first (return), then drain on the next tick.\n setImmediate(lifecycle.shutdown)\n },\n }\n}\n","/**\n * Shared per-session composer state: prompt drafts, draft attachments, and\n * transcript-search state, synced across windows. Ephemeral by design —\n * in-memory only, cleared when any window submits, gone on daemon restart.\n */\nimport type { HostSignal, PromptAttachment } from '../../protocol'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\n\ninterface DraftEntry { text?: string, shell?: boolean, attachments?: PromptAttachment[], search?: { active: boolean, query: string } }\n\n/**\n * Bound a peer-supplied attachment list: shape-guarded entries only,\n * 24 MiB of base64 per list. Shared by `queue.add` and\n * `drafts.setAttachments`.\n */\nexport function boundAttachments(list: unknown[]): PromptAttachment[] {\n let budget = 24 * 1024 * 1024\n const out: PromptAttachment[] = []\n for (const entry of list) {\n const a = entry as Partial<PromptAttachment>\n if (typeof a?.mediaType !== 'string' || typeof a?.data !== 'string')\n continue\n budget -= a.data.length\n if (budget < 0)\n break\n // Names render in every window's UI — cap them so a hostile peer\n // can't pin megabytes of \"name\" per attachment.\n out.push({ mediaType: a.mediaType, data: a.data, ...(typeof a.name === 'string' ? { name: a.name.slice(0, 256) } : {}) })\n }\n return out\n}\n\nexport function createDraftHandlers({ broadcastExcept }: {\n broadcastExcept: (origin: HostPeer | null, signal: HostSignal) => void\n}): {\n methods: Handlers<'drafts.get' | 'drafts.set' | 'drafts.setAttachments' | 'search.set'>\n /** Consume the draft after a submit — every window except the sender clears. */\n clearDraft: (sessionId: string, origin: HostPeer | null) => void\n /** The session was deleted: drop its draft silently. */\n forget: (sessionId: string) => void\n} {\n /**\n * Shared per-session prompt drafts. Ephemeral by design — in-memory\n * only, cleared when any window submits, gone on daemon restart.\n */\n const drafts = new Map<string, DraftEntry>()\n\n /** Total base64 bytes currently pinned by ALL draft attachments. */\n function draftAttachmentBytes(): number {\n let total = 0\n for (const entry of drafts.values()) {\n for (const attachment of entry.attachments ?? [])\n total += attachment.data.length\n }\n return total\n }\n\n function clearDraft(sessionId: string, origin: HostPeer | null): void {\n const entry = drafts.get(sessionId)\n if (!entry)\n return\n drafts.delete(sessionId)\n if (entry.text)\n broadcastExcept(origin, { kind: 'draft:changed', sessionId, text: '' })\n if (entry.attachments?.length)\n broadcastExcept(origin, { kind: 'draft:attachments', sessionId, attachments: [] })\n }\n\n /** Drop empty draft entries so the map only holds live composing state. */\n function compactDraft(sessionId: string, entry: DraftEntry): void {\n if (!entry.text && !entry.shell && !entry.attachments?.length && !entry.search?.active)\n drafts.delete(sessionId)\n else\n drafts.set(sessionId, entry)\n }\n\n const methods: Handlers<'drafts.get' | 'drafts.set' | 'drafts.setAttachments' | 'search.set'> = {\n 'drafts.get': (p) => {\n const entry = drafts.get(p.sessionId)\n return {\n text: entry?.text ?? '',\n ...(entry?.shell ? { shell: true } : {}),\n ...(entry?.attachments?.length ? { attachments: entry.attachments } : {}),\n ...(entry?.search?.active ? { search: entry.search } : {}),\n }\n },\n 'drafts.set': (p, peer) => {\n // Bound the ephemeral draft store: a buggy/looping client must not\n // grow daemon memory without limit (drafts only evict on submit or\n // session delete). 64 KiB is far above any real prompt.\n const text = typeof p.text === 'string' ? p.text.slice(0, 64 * 1024) : ''\n // When the cap actually truncated, INCLUDE the origin in the fan-out\n // so its local buffer converges to the stored truth — otherwise the\n // origin silently diverges from what every other window (and a\n // remote submit) sees.\n const truncated = typeof p.text === 'string' && p.text.length > text.length\n // Also bound the KEY count: drafts only evict on submit / session\n // delete, so a client writing under many bogus session ids could\n // otherwise grow the map unbounded. 256 concurrent drafts is far\n // beyond any real multi-window session set.\n if (!drafts.has(p.sessionId) && drafts.size >= 256)\n return\n const entry = drafts.get(p.sessionId) ?? {}\n entry.text = text.length > 0 ? text : undefined\n // Shell mode rides out of band — never sniffed from the text.\n entry.shell = p.shell === true ? true : undefined\n compactDraft(p.sessionId, entry)\n broadcastExcept(truncated ? null : peer, { kind: 'draft:changed', sessionId: p.sessionId, text, ...(p.shell === true ? { shell: true } : {}) })\n },\n 'search.set': (p, peer) => {\n // Shared transcript-search state — same lifecycle + caps as drafts.\n const active = p.active === true\n const query = typeof p.query === 'string' ? p.query.slice(0, 4 * 1024) : ''\n if (!drafts.has(p.sessionId) && drafts.size >= 256)\n return\n const entry = drafts.get(p.sessionId) ?? {}\n entry.search = active || query.length > 0 ? { active, query } : undefined\n compactDraft(p.sessionId, entry)\n broadcastExcept(peer, { kind: 'search:changed', sessionId: p.sessionId, active, query })\n },\n 'drafts.setAttachments': (p, peer) => {\n /*\n * Composing attachments (payloads included, so a remote window can\n * submit the shared draft attachments-and-all). Bounded three ways:\n * shape-guarded entries, 24 MiB of base64 per session, and a 96 MiB\n * GLOBAL budget across every draft — the per-session cap times the\n * 256-key cap would otherwise let a looping client pin gigabytes.\n */\n const bounded = Array.isArray(p.attachments) ? boundAttachments(p.attachments) : []\n if (!drafts.has(p.sessionId) && drafts.size >= 256)\n return\n const current = drafts.get(p.sessionId)?.attachments ?? []\n const currentBytes = current.reduce((sum, a) => sum + a.data.length, 0)\n const incomingBytes = bounded.reduce((sum, a) => sum + a.data.length, 0)\n if (draftAttachmentBytes() - currentBytes + incomingBytes > 96 * 1024 * 1024)\n return\n const entry = drafts.get(p.sessionId) ?? {}\n entry.attachments = bounded.length > 0 ? bounded : undefined\n compactDraft(p.sessionId, entry)\n broadcastExcept(peer, { kind: 'draft:attachments', sessionId: p.sessionId, attachments: bounded })\n },\n }\n\n return {\n methods,\n clearDraft,\n forget: (sessionId) => {\n drafts.delete(sessionId)\n },\n }\n}\n","/** Execution environments: the catalog, verification, settings, and a session's provisioning and actions. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostSettings } from '../../../chat/index'\nimport type { DaemonEnvironment } from '../environment'\nimport type { Handler, Handlers } from './types'\nimport { applyEnvironmentSettingsChange } from '../../../chat/environment-settings'\nimport { loadOrThrow } from './session-load'\n\ntype EnvironmentMethod\n = | 'environments.list' | 'environments.verify' | 'environments.update'\n | 'sessions.retryEnvironment' | 'sessions.moveEnvironment' | 'sessions.environmentActions' | 'sessions.runEnvironmentAction'\n\nexport function createEnvironmentHandlers({ host, env, setSettings }: {\n host: ChatHost\n env: DaemonEnvironment\n /** The `settings.set` handler, so an environment edit fans out like any settings edit. */\n setSettings: Handler<'settings.set'>\n}): Handlers<EnvironmentMethod> {\n return {\n 'sessions.retryEnvironment': async (p) => {\n await loadOrThrow(env.store, p.sessionId)\n // Provisioning can take minutes (a sandbox, a clone): respond once the\n // row shows `provisioning` (a poller must not read the old failure) and\n // let `prepare` run in the background, announced as `sessions:changed`.\n await host.retryEnvironment(p.sessionId, { background: true })\n },\n 'sessions.moveEnvironment': async (p) => {\n await loadOrThrow(env.store, p.sessionId)\n return host.moveSessionEnvironment(p.sessionId, p.environment, typeof p.cwd === 'string' ? p.cwd : undefined, p.removeOldWorktree === true ? { removeOldWorktree: true } : undefined)\n },\n 'sessions.environmentActions': p => host.listEnvironmentActions(p.sessionId),\n 'sessions.runEnvironmentAction': p => host.runEnvironmentAction(p.sessionId, p.actionId),\n 'environments.list': p => host.listEnvironments(p.cwd ?? '', typeof p.kind === 'string' ? p.kind : undefined),\n 'environments.verify': p => host.verifyEnvironment(p.kind),\n 'environments.update': async (p, peer) => {\n const write = applyEnvironmentSettingsChange(host.environments, env.readSettings(), p)\n for (const secret of write.secrets)\n host.environmentSecrets.set(p.kind, secret.key, secret.value)\n // Through `settings.set` so the change fans out (and tears down what a\n // bound key like `sandbox` requires) exactly like any settings edit.\n await setSettings({ patch: write.settingsPatch as Partial<HostSettings> }, peer)\n },\n }\n}\n","/**\n * What an extension adds to a client's app, run here and answered as data:\n * composer completions (`completions.*`: the providers, a provider's items,\n * the submit hooks), text references in prose (`references.*`: the\n * providers' patterns, then the views of the keys a client found), badge\n * menu items (`badges.*`), and Settings › Extensions (`extensions.*`: the\n * options a folder's extensions declare, their action rows, the actions'\n * status probes, a run). A badge item runs outside any session's scope: its\n * `ctx.artifacts` reads nothing.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { CompletionRunner, ExtensionRegistry, ReferenceResolver } from '../../../extensions/index'\nimport type { DaemonEnvironment } from '../environment'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport {\n completionProviderSummaries,\n createCompletionRunner,\n createReferenceResolver,\n extensionBadgeActions,\n listActionSummaries,\n normalizeBadgeTarget,\n probeActionStatuses,\n referenceProviderWires,\n runBadgeAction,\n runExtensionAction,\n toWireConfigSchema,\n} from '../../../extensions/index'\nimport { catalogFolder } from './catalogs'\nimport { InvalidParamsError } from './params'\n\ntype ExtensionUiMethod\n = | 'completions.providers' | 'completions.suggest' | 'completions.submit'\n | 'references.providers' | 'references.resolve' | 'badges.actions' | 'badges.run'\n | 'extensions.configSchema' | 'extensions.actions' | 'extensions.actionStatuses' | 'extensions.runAction'\n\n/** Keys per `references.resolve` call. */\nconst RESOLVE_MAX = 50\n/** Longest reference key resolved. */\nconst MAX_KEY_LENGTH = 512\n\n/** The text and cursor of a completion call. */\nfunction composerText(p: { text?: unknown, cursor?: unknown }): { text: string, cursor: number } {\n if (typeof p.text !== 'string' || typeof p.cursor !== 'number' || !Number.isSafeInteger(p.cursor) || p.cursor < 0 || p.cursor > p.text.length)\n throw new InvalidParamsError('text must be a string and cursor a position in it.')\n return { text: p.text, cursor: p.cursor }\n}\n\n/** One value per owner (a connection, a registry), dropped with it. */\nfunction weakMemo<K extends object, V>(make: (owner: K) => V): (owner: K) => V {\n const memo = new WeakMap<K, V>()\n return (owner) => {\n let value = memo.get(owner)\n if (value === undefined) {\n value = make(owner)\n memo.set(owner, value)\n }\n return value\n }\n}\n\nexport function createExtensionUiHandlers({ host, env }: {\n host: Pick<ChatHost, 'resolveFolder'>\n env: DaemonEnvironment\n}): Handlers<ExtensionUiMethod> {\n const folderOf = (cwd: unknown): string => catalogFolder({ env, host }, cwd)\n const configOf = (cwd: unknown) => env.runtimeConfig(folderOf(cwd))\n const registryOf = async (cwd: unknown): Promise<ExtensionRegistry> => (await configOf(cwd)).extensions\n /** One completion runner per connection: a newer suggest aborts only that window's older one. */\n const runnerOf = weakMemo<HostPeer, CompletionRunner>(() => createCompletionRunner())\n /** One reference resolver (and so one view cache) per registry: a rebuilt registry starts fresh. */\n const resolverOf = weakMemo<ExtensionRegistry, ReferenceResolver>(registry => createReferenceResolver(registry))\n /** Actions running now, by folder, extension and key: a second click waits for the first. */\n const running = new Set<string>()\n\n return {\n 'completions.providers': async p => completionProviderSummaries((await registryOf(p.cwd)).completionProviders),\n 'completions.suggest': async (p, peer) => {\n const context = composerText(p)\n if (typeof p.providerId !== 'string' || typeof p.query !== 'string')\n throw new InvalidParamsError('providerId and query must be strings.')\n const cwd = folderOf(p.cwd)\n const provider = (await env.runtimeConfig(cwd)).extensions.completionProviders.find(c => c.id === p.providerId)\n if (!provider || typeof provider.suggest !== 'function')\n return []\n return runnerOf(peer).suggest(`${cwd}\\u001E${provider.id}`, provider, p.query, context)\n },\n 'completions.submit': async (p, peer) => {\n const { text, cursor } = composerText(p)\n await runnerOf(peer).submit((await registryOf(p.cwd)).completionProviders, text, cursor)\n },\n\n 'references.providers': async (p) => {\n if (p.peek !== true)\n return referenceProviderWires(await registryOf(p.cwd))\n const cached = env.peekRuntimeConfig?.(folderOf(p.cwd))\n return cached ? referenceProviderWires((await cached).extensions) : null\n },\n 'references.resolve': async (p) => {\n const asked = Array.isArray(p.items) ? p.items.slice(0, RESOLVE_MAX) : []\n const resolver = resolverOf(await registryOf(p.cwd))\n return Promise.all(asked.map((item) => {\n const { providerId, key } = (item ?? {}) as { providerId?: unknown, key?: unknown }\n if (typeof providerId !== 'string' || typeof key !== 'string' || key.length > MAX_KEY_LENGTH)\n return null\n return resolver.resolve(providerId, key)\n }))\n },\n 'badges.actions': async (p) => {\n const target = normalizeBadgeTarget(p.target)\n return target ? extensionBadgeActions(target, await registryOf(p.cwd)) : []\n },\n 'badges.run': async (p) => {\n const target = normalizeBadgeTarget(p.target)\n if (!target || typeof p.source !== 'string' || typeof p.id !== 'string')\n return { notice: 'Unknown badge.' }\n const ctx = {\n ...(target.sessionId ? { sessionId: target.sessionId } : {}),\n ...(typeof p.cwd === 'string' && p.cwd ? { cwd: p.cwd } : {}),\n }\n return runBadgeAction(p.source, p.id, target, await registryOf(p.cwd), ctx)\n },\n\n 'extensions.configSchema': async (p) => {\n const config = await configOf(p.cwd)\n return toWireConfigSchema({ configCategories: config.extensionConfigCategories, configItems: config.extensionConfigItems })\n },\n 'extensions.actions': async (p) => {\n const config = await configOf(p.cwd)\n return listActionSummaries(config.extensionConfigCategories, config.extensionConfigItems)\n },\n 'extensions.actionStatuses': async p => probeActionStatuses((await configOf(p.cwd)).extensionConfigItems),\n 'extensions.runAction': async (p) => {\n if (typeof p.extension !== 'string' || typeof p.key !== 'string')\n throw new InvalidParamsError('extension and key must be strings.')\n const cwd = folderOf(p.cwd)\n const guard = `${cwd}\\u001E${p.extension}\\u001E${p.key}`\n if (running.has(guard))\n throw new Error('action is already running.')\n running.add(guard)\n try {\n return await runExtensionAction((await env.runtimeConfig(cwd)).extensionConfigItems, p.extension, p.key)\n }\n finally {\n running.delete(guard)\n }\n },\n }\n}\n","/** Extension bus emits from clients whose extensions run client-side, and the extensions' HUD the host holds. */\nimport type { HostSignal } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { EXTENSION_BUS_MAX_PAYLOAD_BYTES, serializedPayloadBytes } from '../../../extensions/index'\nimport { loadOrThrow } from './session-load'\n\nexport function createExtensionHandlers({ env, broadcastExcept }: {\n env: DaemonEnvironment\n broadcastExcept: (origin: HostPeer | null, signal: HostSignal) => void\n}): Handlers<'extension.emit' | 'hud.get'> {\n return {\n 'hud.get': () => env.hudState?.() ?? { statuses: {}, banners: {}, sessions: {}, badges: {} },\n 'extension.emit': async (p, peer) => {\n /*\n * Extension bus emit from a client whose extensions run client-side\n * (TUI daemon mode). Trust boundary: params are unchecked JSON —\n * same cheap shape guards as `drafts.set`, the payload cap\n * re-enforced daemon-side, and the extension id validated against\n * the session cwd's registry (spoof-resistance: a hand-rolled peer\n * can't ride an id that isn't a loaded, `'ipc'`-permitted extension).\n */\n const extensionId = typeof p.extensionId === 'string' ? p.extensionId : ''\n if (extensionId.length === 0 || extensionId.length > 256)\n return\n if (typeof p.seq !== 'number' || !Number.isFinite(p.seq))\n return\n const sessionId = typeof p.sessionId === 'string' ? p.sessionId : undefined\n const bytes = serializedPayloadBytes(p.payload)\n if (bytes === null || bytes > EXTENSION_BUS_MAX_PAYLOAD_BYTES)\n return\n // Registry for the session's cwd (same derivation as `suggest.resolve`);\n // sessionless emits validate against the boot-config registry.\n let registry = env.config.extensions\n if (sessionId !== undefined) {\n try {\n const data = await loadOrThrow(env.store, sessionId)\n const meta = data.metadata ?? {}\n const cwd = typeof meta.cwd === 'string' ? meta.cwd : (data.projectRoot ?? '')\n registry = (await env.runtimeConfig(cwd)).extensions\n }\n catch {\n return // Unknown session — nothing to validate against, drop.\n }\n }\n const known = registry.loaded.some(ext =>\n !ext.error && ext.name === extensionId && ext.definition?.permissions?.includes('ipc') === true)\n if (!known)\n return\n const nonce = typeof p.nonce === 'string' ? p.nonce : undefined\n const envelope = { extensionId, ...(sessionId !== undefined ? { sessionId } : {}), payload: p.payload, seq: p.seq, ...(nonce !== undefined ? { nonce } : {}) }\n // Daemon-side subscribers first (loopback for extensions living in\n // per-cwd daemon registries), then every OTHER window — the origin\n // already delivered to its local subscribers at emit.\n env.extensionBus?.deliver(envelope)\n broadcastExcept(peer, { kind: 'extension:signal', ...envelope })\n },\n }\n}\n","/**\n * A folder's files beyond a session's workspace (`files.*`): the files `@`\n * completes and where the folder sits, search in files, what prose names on disk, the project's own diagnostics, and the ticket a\n * connection's media play under (a zidane-server serves them over HTTP,\n * `src/server/media.ts`). The work is the desktop app's own\n * (`src/chat/workspace`); this slice confines every folder to the host's\n * workspace roots.\n */\nimport type { HostPeer } from '../peers'\nimport type { WorkspaceRoots } from '../workspace-roots'\nimport type { Handlers } from './types'\nimport { randomUUID } from 'node:crypto'\nimport { listProjectFiles } from '../../../chat/files-discovery'\nimport { folderLocation } from '../../../chat/project-root'\nimport { invalidateDiagnostics, listDiagnosticsTools, runDiagnostics } from '../../../chat/workspace/diagnostics/runner'\nimport { resolvePaths } from '../../../chat/workspace/path-resolve'\nimport { searchWorkspace } from '../../../chat/workspace/search'\nimport { InvalidParamsError, optionalString } from './params'\n\ntype FilesMethod = 'files.list' | 'files.location' | 'files.search' | 'files.resolvePaths' | 'files.diagnostics' | 'files.diagnosticsInvalidate' | 'files.diagnosticsTools' | 'files.mediaTicket'\n\n/** The connections' media tickets: a zidane-server's (`src/server/media.ts`). */\nexport interface MediaTicketRegistry {\n /** Lets `peer`'s media play under `ticket`, replacing its previous one. Throws when another connection holds it. */\n register: (ticket: string, peer: HostPeer) => void\n /** Drops `peer`'s ticket (its connection closed). */\n release: (peer: HostPeer) => void\n}\n\n/** A media ticket: random, URL-safe, long enough not to be guessed. */\nconst MEDIA_TICKET = /^[\\w-]{32,128}$/\n\n/** Longest query searched; the rest is cut. */\nconst MAX_QUERY_LENGTH = 500\n/** Most texts one `files.resolvePaths` resolves. */\nconst MAX_TEXTS = 500\n\nfunction stringList(value: unknown, name: string, max = Infinity): string[] {\n if (!Array.isArray(value) || value.length > max || value.some(v => typeof v !== 'string'))\n throw new InvalidParamsError(`${name} must be an array of at most ${max} strings.`)\n return value\n}\n\nexport function createFilesHandlers({ workspace, media, onClose }: {\n workspace: WorkspaceRoots\n /** Absent: this host serves no media (`files.mediaTicket` refuses). */\n media?: MediaTicketRegistry\n onClose: (release: (peer: HostPeer) => void) => void\n}): Handlers<FilesMethod> {\n if (media)\n onClose(peer => media.release(peer))\n const folder = (cwd: unknown): string => {\n if (typeof cwd !== 'string' || cwd.length === 0)\n throw new InvalidParamsError('cwd must be a non-empty string.')\n return workspace.resolveFolder(cwd)\n }\n // Search ids are per connection: one client's search never cancels another's.\n const connectionIds = new WeakMap<HostPeer, string>()\n const connectionId = (peer: HostPeer): string => {\n let id = connectionIds.get(peer)\n if (!id)\n connectionIds.set(peer, id = randomUUID())\n return id\n }\n return {\n 'files.list': p => listProjectFiles({ cwd: folder(p.cwd) }),\n 'files.location': p => folderLocation(folder(p.cwd)),\n 'files.search': (p, peer) => {\n if (typeof p.query !== 'string')\n throw new InvalidParamsError('query must be a string.')\n return searchWorkspace(folder(p.cwd), p.query.slice(0, MAX_QUERY_LENGTH), {\n caseSensitive: p.caseSensitive === true,\n searchId: `${connectionId(peer)}:${optionalString(p.searchId, 'searchId') ?? ''}`,\n })\n },\n 'files.resolvePaths': p => resolvePaths(folder(p.cwd), stringList(p.texts, 'texts', MAX_TEXTS)),\n 'files.diagnostics': p => runDiagnostics(folder(p.cwd), stringList(p.paths, 'paths'), {\n disabled: p.disabled === undefined ? [] : stringList(p.disabled, 'disabled'),\n ...(typeof p.timeoutMs === 'number' ? { timeoutMs: p.timeoutMs } : {}),\n }),\n 'files.diagnosticsInvalidate': (p) => {\n invalidateDiagnostics(folder(p.cwd))\n },\n 'files.diagnosticsTools': p => listDiagnosticsTools(folder(p.cwd)),\n 'files.mediaTicket': (p, peer) => {\n if (!media)\n throw new Error('This host serves no media (only a zidane-server does).')\n if (typeof p.ticket !== 'string' || !MEDIA_TICKET.test(p.ticket))\n throw new InvalidParamsError('ticket must be 32 to 128 URL-safe characters.')\n media.register(p.ticket, peer)\n },\n }\n}\n","/**\n * The host's machine: folders within its workspace roots (`fs.roots`,\n * `fs.listDirs`, `fs.searchDirs`, and `fs.mkdir` while `createFolders`\n * allows it) and what it can do (`host.capabilities`).\n */\nimport type { HostCapabilities } from '../../../chat/capabilities'\nimport type { EnvironmentDescriptor } from '../../../chat/environment-settings'\nimport type { WorkspaceRoots } from '../workspace-roots'\nimport type { Handlers } from './types'\nimport { createCapabilityProbe } from '../../../chat/capabilities-probe'\nimport { optionalString, requiredString } from './params'\n\n/** What `fs.mkdir` answers while a zidane-server's `allowCreateFolders` is off. */\nexport const CREATE_FOLDERS_OFF_MESSAGE = 'Creating folders is off on this server (allowCreateFolders).'\n\nexport function createFsHandlers({ workspace, environments, allows, createFolders = () => true }: {\n workspace: WorkspaceRoots\n /** The host's environment kinds (`environments.list`). */\n environments?: () => Promise<EnvironmentDescriptor[]>\n /** What it lets clients do (the hello flags). */\n allows?: () => HostCapabilities['allows']\n /** Clients may create folders (`fs.mkdir`): a zidane-server's `allowCreateFolders`. Default: yes. */\n createFolders?: () => boolean\n}): Handlers<'fs.roots' | 'fs.listDirs' | 'fs.mkdir' | 'fs.searchDirs' | 'host.capabilities'> {\n const probe = createCapabilityProbe({\n environments: async () => (await (environments?.() ?? Promise.resolve([])))\n .filter(d => d.enabled)\n .map(d => ({ kind: d.kind, label: d.label, available: d.available, ...(d.reason ? { reason: d.reason } : {}) })),\n roots: () => workspace.describe().roots,\n allows: allows ?? (() => ({ remoteInstalls: false, asMachine: false, sync: false, clone: true, createFolders: createFolders() })),\n })\n return {\n 'fs.roots': () => workspace.describe(),\n 'fs.listDirs': p => workspace.list(optionalString(p?.path, 'path')),\n 'fs.mkdir': (p) => {\n if (!createFolders())\n throw new Error(CREATE_FOLDERS_OFF_MESSAGE)\n return workspace.mkdir(requiredString(p.parent, 'parent'), requiredString(p.name, 'name'))\n },\n 'fs.searchDirs': p => workspace.search(requiredString(p.query, 'query'), optionalString(p.path, 'path')),\n 'host.capabilities': p => probe(p?.refresh === true),\n }\n}\n","/**\n * The wire checks of a session's rules (`sessions.create`'s `policy`,\n * `sessions.setPolicy`): the shape (`chat/session-policy`), and the scope\n * loosening needs. A client whose token can't approve calls may only tighten\n * the session's current rules: a looser `approvalMode` ('ask' > 'decide' > 'off'), or\n * removing or weakening a rule, lets the agent do more, so it needs a token\n * that may approve calls itself. A local connection (no grant) reaches\n * everything.\n */\nimport type { SessionPolicy } from '../../../chat/session-policy'\nimport type { ClientScope } from '../../scopes'\nimport type { HostPeer } from '../peers'\nimport { parseSessionPolicy, policyLoosening, SessionPolicyError } from '../../../chat/session-policy'\nimport { IpcErrorCode } from '../../protocol'\nimport { scopeAllows } from '../../scopes'\nimport { InvalidParamsError } from './params'\n\n/** A policy the connection's token may not set, worded like the dispatcher's scope refusal. */\nexport class PolicyScopeError extends Error {\n readonly code = IpcErrorCode.Forbidden\n readonly data: { required: ClientScope, granted: ClientScope }\n /**\n * @param method - The refused method.\n * @param what - The loosening, as {@link policyLoosening} words it.\n * @param granted - The connection's scope.\n */\n constructor(method: string, what: string, granted: ClientScope) {\n super(`\"${method}\" ${what} needs an approve token; this connection's token is ${granted}.`)\n this.name = 'PolicyScopeError'\n this.data = { required: 'approve', granted }\n }\n}\n\n/**\n * `value` as a clean policy that `peer` may set in place of `previous`.\n *\n * @param value - The `policy` param, untrusted.\n * @param peer - The calling connection (`null` for a host-internal call).\n * @param method - The method, named in the refusal.\n * @param previous - The session's current policy, read only when the token can't approve (default: none, a new session).\n * @throws {InvalidParamsError} When the policy does not validate.\n * @throws {PolicyScopeError} When it loosens `previous` and the token can't approve.\n */\nexport async function checkPolicyParam(\n value: unknown,\n peer: HostPeer | null | undefined,\n method: string,\n previous: () => SessionPolicy | Promise<SessionPolicy> = () => ({}),\n): Promise<SessionPolicy> {\n let policy: SessionPolicy\n try {\n policy = parseSessionPolicy(value, 'policy')\n }\n catch (err) {\n throw err instanceof SessionPolicyError ? new InvalidParamsError(err.message) : err\n }\n const grant = peer?.grant\n if (grant && !scopeAllows(grant, 'approve')) {\n const loosened = policyLoosening(await previous(), policy)\n if (loosened !== undefined)\n throw new PolicyScopeError(method, loosened, grant)\n }\n return policy\n}\n","/** Session rows: list, create, delete, and metadata edits (title, archive, agent, model, folder, policy). */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { SessionPolicy } from '../../../chat/session-policy'\nimport type { SessionData, SessionStore } from '../../../session/index'\nimport type { CreateSessionParams, HostSignal, IpcParams, SessionRow } from '../../protocol'\nimport type { WorkspaceRoots } from '../workspace-roots'\nimport type { Handlers } from './types'\nimport { TITLE_SOURCE_KEY } from '../../../chat/auto-title'\nimport { isStaleRunMarker } from '../../../chat/host/engine'\nimport { readSessionAccount, sessionModelFallbacks } from '../../../chat/model-chain-metadata'\nimport { isMainSession, isSideSession, sideSessionParent } from '../../../chat/orchestration'\nimport { PINNED_SKILLS_META_KEY, pinnedSkillsValue, readPinnedSkills } from '../../../chat/pinned-skills'\nimport { SESSION_POLICY_KEY, sessionPolicyOf } from '../../../chat/session-policy'\nimport { DEFAULT_SPACE_ID, readSessionSpaceId, SPACE_METADATA_KEY } from '../../../chat/spaces'\nimport { deriveSessionTitle, runInProgress, sessionEnvironmentSummary } from '../../../chat/store'\nimport { loadOrThrow } from './session-load'\nimport { checkPolicyParam } from './session-policy'\n\ntype SessionMethod\n = | 'sessions.list' | 'sessions.create' | 'sessions.delete' | 'sessions.sideSession' | 'sessions.setTitle' | 'sessions.setArchived' | 'sessions.setFavorite' | 'sessions.setSpace'\n | 'sessions.setAgentId' | 'sessions.setEffort' | 'sessions.setModel' | 'sessions.setModelOptions' | 'sessions.setFolder'\n | 'sessions.setPolicy'\n\nexport function createSessionHandlers({ host, store, broadcast, forgetSession, hostId, workspace }: {\n host: ChatHost\n store: SessionStore\n broadcast: (signal: HostSignal) => void\n /** Drop the per-session wire state other handlers keep, before the host deletes the session. */\n forgetSession: (sessionId: string) => void\n /** Stamped on every returned row (`SessionRow.hostId`). */\n hostId: string | undefined\n /** Where session folders may be (a server confines them to its workspace roots). */\n workspace?: WorkspaceRoots\n}): Handlers<SessionMethod> {\n const stamp = (row: SessionRow): SessionRow => hostId ? { ...row, hostId } : row\n /** Each session's last `sessions.setPolicy`: the next one checks against what it wrote, not against what was there before it. */\n const policyWrites = new Map<string, Promise<unknown>>()\n /**\n * Apply a metadata-only patch. Prefers the host's live-session path (safe\n * mid-run — routes through the in-memory `Session` whose turns are the\n * source of truth); only falls back to a store-level full-document\n * `save()` when the session is idle, where no run is appending turns so\n * `load → mutate → save` can't drop concurrently-persisted turns.\n *\n * `bumpUpdatedAt: false` skips the recency bump so a rename doesn't yank\n * the row to the top of recency-sorted lists (mirrors the GUI).\n */\n async function patchSessionMeta(\n sessionId: string,\n patch: Record<string, unknown>,\n opts: { bumpUpdatedAt?: boolean } = {},\n ): Promise<void> {\n /*\n * Live path: route through the in-memory `Session` so the full-document\n * save() re-persists the CURRENT turns; `bumpUpdatedAt` holds there too.\n */\n await host.patchSessionMeta(sessionId, patch, opts)\n broadcast({ kind: 'sessions:changed', op: 'update', sessionId })\n }\n\n async function patchSession(\n sessionId: string,\n mutate: (data: SessionData) => void,\n ): Promise<void> {\n const data = await loadOrThrow(store, sessionId)\n mutate(data)\n data.updatedAt = Date.now()\n await store.save(data)\n broadcast({ kind: 'sessions:changed', op: 'update', sessionId })\n }\n\n async function createSessionRow(params: CreateSessionParams, policy?: SessionPolicy): Promise<SessionRow> {\n // Creation lives in the host (shared with the embedded GUI host and\n // orchestration); this adds only the wire row + the change broadcast.\n // Forward the wire fields by name: the host factory also accepts an\n // explicit `id` and raw `metadata`, which a wire client must not set\n // (only the validated keys below).\n const metadata = policy && Object.keys(policy).length > 0 ? { ...creationMetadata(params), [SESSION_POLICY_KEY]: policy } : creationMetadata(params)\n // A machine's folder (`local@<machine>`) is not on this host: the host checks it against the machine's roots instead.\n const onMachine = params.environment?.kind ? host.environments.get(params.environment.kind)?.checkFolder !== undefined : false\n const cwd = workspace?.describe().confined && !onMachine ? workspace.sessionFolder(params.cwd ?? '') : params.cwd\n const id = await host.createSession({\n cwd,\n ...(metadata ? { metadata } : {}),\n ...(params.title ? { title: params.title } : {}),\n ...(params.agentId ? { agentId: params.agentId } : {}),\n ...(params.providerKey && params.modelId ? { providerKey: params.providerKey, modelId: params.modelId } : {}),\n ...(params.providerKey && params.modelId && typeof params.account === 'string' && params.account ? { account: params.account } : {}),\n ...(params.fallbacks ? { fallbacks: params.fallbacks } : {}),\n ...(params.extensionEdit ? { extensionEdit: true } : {}),\n ...(params.skillEdit?.name ? { skillEdit: { name: params.skillEdit.name } } : {}),\n ...(typeof params.spaceId === 'string' && params.spaceId ? { spaceId: params.spaceId } : {}),\n ...(typeof params.sideOf === 'string' && params.sideOf ? { sideOf: params.sideOf } : {}),\n ...(params.environment?.kind\n ? {\n environment: {\n kind: params.environment.kind,\n ...(params.environment.branch ? { branch: params.environment.branch } : {}),\n ...(params.environment.base ? { base: params.environment.base } : {}),\n },\n }\n : {}),\n })\n const data = await loadOrThrow(store, id)\n broadcast({ kind: 'sessions:changed', op: 'create', sessionId: id })\n return stamp(toRow(host, data))\n }\n\n return {\n 'sessions.list': async p => (await listSessionRows(host, store, p)).map(stamp),\n // Awaited, not returned: a rejection handed back unawaited reaches Bun's unhandled-rejection check first.\n 'sessions.create': async (p, peer) => await createSessionRow(p, p.policy === undefined ? undefined : await checkPolicyParam(p.policy, peer, 'sessions.create')),\n 'sessions.delete': async (p) => {\n forgetSession(p.sessionId)\n // Agent retirement + environment + row + on-disk artifacts: the shared host delete.\n const { environment } = await host.deleteSession(p.sessionId)\n broadcast({ kind: 'sessions:changed', op: 'delete', sessionId: p.sessionId })\n return environment.removed && !environment.reason ? {} : { environment }\n },\n 'sessions.sideSession': async (p) => {\n const rowOf = async (id: string | undefined): Promise<SessionRow | null> => {\n const data = id ? await store.load(id) : null\n return data ? stamp(toRow(host, data)) : null\n }\n const [side, parent] = await Promise.all([rowOf(await newestSideSession(store, p.sessionId)), rowOf(p.sessionId)])\n return { side, parent }\n },\n // Rename skips the recency bump so it doesn't yank the row to the top\n // of recency-sorted lists (mirrors the GUI).\n // A typed title: auto-titling never replaces it (`metadata.titleSource`).\n 'sessions.setTitle': p => patchSessionMeta(p.sessionId, { title: p.title, [TITLE_SOURCE_KEY]: 'user' }, { bumpUpdatedAt: false }),\n 'sessions.setArchived': async (p) => {\n await patchSessionMeta(p.sessionId, { archived: p.archived })\n // An archived session's shells on this machine end (in the background:\n // archiving never waits on a slow one); its environment's are left to idle suspension.\n if (p.archived)\n void host.terminals.archiveSession(p.sessionId)\n },\n // Like a rename: not activity, so the row keeps its place by recency.\n 'sessions.setFavorite': p => patchSessionMeta(p.sessionId, { favorite: p.favorite }, { bumpUpdatedAt: false }),\n // Replaces the whole policy; `{}` clears it. Not activity: no recency bump.\n 'sessions.setPolicy': (p, peer) => {\n const write = async (): Promise<void> => {\n // Live metadata first: it is what the host enforces.\n const current = async () => sessionPolicyOf((host.getLiveSession(p.sessionId) ?? await loadOrThrow(store, p.sessionId)).metadata)\n const policy = await checkPolicyParam(p.policy, peer, 'sessions.setPolicy', current)\n return patchSessionMeta(p.sessionId, { [SESSION_POLICY_KEY]: Object.keys(policy).length > 0 ? policy : undefined }, { bumpUpdatedAt: false })\n }\n const next = (policyWrites.get(p.sessionId) ?? Promise.resolve()).then(write, write)\n const settled = next.catch(() => undefined)\n policyWrites.set(p.sessionId, settled)\n void settled.then(() => {\n if (policyWrites.get(p.sessionId) === settled)\n policyWrites.delete(p.sessionId)\n })\n return next\n },\n // Default is stored as its id rather than deleted: the patch is a shallow\n // spread, and every reader maps the Default id to \"no space\".\n // A move is not activity: no recency bump.\n 'sessions.setSpace': p => patchSessionMeta(\n p.sessionId,\n { [SPACE_METADATA_KEY]: typeof p.spaceId === 'string' && p.spaceId ? p.spaceId : DEFAULT_SPACE_ID },\n { bumpUpdatedAt: false },\n ),\n 'sessions.setAgentId': async (p) => {\n /*\n * `agentId` is a top-level field (not metadata) and rebuilds the\n * agent. Patch the LIVE document when the host holds one — a bare\n * store patch loads a stale copy whose full save would clobber\n * mid-run turn appends, and the untouched live doc would revert the\n * label on its next save. Idle sessions take the store patch (no\n * concurrent writer). Then retire the agent (deferred to run end\n * while running) so a swap doesn't abort a shared run mid-stream —\n * unless the live agent's composition fits the new profile\n * (`ChatHost.agentSwitchRebuilds`).\n */\n const rebuild = host.agentSwitchRebuilds(p.sessionId, p.agentId)\n if (await host.setLiveSessionAgentId(p.sessionId, p.agentId)) {\n broadcast({ kind: 'sessions:changed', op: 'update', sessionId: p.sessionId })\n }\n else {\n await patchSession(p.sessionId, (d) => {\n d.agentId = p.agentId\n })\n }\n if (rebuild)\n host.disposeAgentForRebuild(p.sessionId)\n },\n 'sessions.setEffort': p => patchSessionMeta(p.sessionId, { effort: p.effort }),\n 'sessions.setModel': async (p) => {\n // The one model-swap contract (`ChatHost.setSessionModel`): patch\n // race-free, replace the chain, reset effort/options, retire the agent\n // (run-end deferred mid-run). Documented in protocol.ts.\n await host.setSessionModel(p.sessionId, {\n providerKey: p.providerKey,\n modelId: p.modelId,\n ...(typeof p.account === 'string' && p.account ? { account: p.account } : {}),\n ...(p.fallbacks ? { fallbacks: p.fallbacks } : {}),\n ...(p.effort ? { effort: p.effort } : {}),\n ...(p.modelOptions ? { modelOptions: p.modelOptions } : {}),\n })\n broadcast({ kind: 'sessions:changed', op: 'update', sessionId: p.sessionId })\n },\n 'sessions.setModelOptions': p => patchSessionMeta(p.sessionId, { modelOptions: p.options }),\n 'sessions.setFolder': (p) => {\n const cwd = typeof p.cwd === 'string' ? p.cwd : ''\n // The host checks it: against this host's roots, or a machine session's machine's (`docs/MACHINES.md` § Folders).\n return host.setSessionFolder(p.sessionId, cwd)\n },\n }\n}\n\n/** The creation-time metadata a client may stamp: the pick's effort and options, pinned skills. */\nfunction creationMetadata(params: CreateSessionParams): Record<string, unknown> | undefined {\n const metadata: Record<string, unknown> = {}\n if (typeof params.effort === 'string')\n metadata.effort = params.effort\n if (params.modelOptions && typeof params.modelOptions === 'object') {\n const options = Object.fromEntries(Object.entries(params.modelOptions).filter(([, on]) => typeof on === 'boolean'))\n if (Object.keys(options).length > 0)\n metadata.modelOptions = options\n }\n if (Array.isArray(params.pinnedSkills)) {\n const pins = readPinnedSkills(params.pinnedSkills.slice(0, 64))\n if (pins.size > 0)\n metadata[PINNED_SKILLS_META_KEY] = pinnedSkillsValue(pins)\n }\n return Object.keys(metadata).length > 0 ? metadata : undefined\n}\n\nexport async function listSessionRows(host: ChatHost, store: SessionStore, p: IpcParams<'sessions.list'>): Promise<SessionRow[]> {\n const filter\n = p?.projectRoot !== undefined ? { projectRoot: p.projectRoot as string | null } : undefined\n\n const applyArchive = (rows: SessionRow[]): SessionRow[] => {\n const filtered = rows.filter((row) => {\n if (p?.archive === 'active')\n return !row.archived\n if (p?.archive === 'archived')\n return row.archived\n return true\n })\n filtered.sort((a, b) => b.updatedAt - a.updatedAt)\n return filtered\n }\n\n /*\n * Fast path: `listMeta` returns header rows without materializing\n * turn arrays — O(sessions), not O(total turns). Falls back to the\n * load-per-id path for stores that don't implement it.\n */\n if (store.listMeta) {\n const metas = await store.listMeta(filter)\n return applyArchive(metas.filter(meta => !isSideSession(meta.metadata)).map((meta) => {\n const md = meta.metadata\n // Canonical derivation — the same helper the TUI list uses, so\n // daemon-fed rows can't render a different title for the same\n // session (the hand-rolled fallback had its own truncation).\n const title = deriveSessionTitle(meta.firstUserTurn ? [meta.firstUserTurn] : [], md)\n const running = host.isSessionRunning(meta.id)\n return {\n id: meta.id,\n title,\n projectRoot: meta.projectRoot ?? null,\n cwd: typeof md.cwd === 'string' ? md.cwd : (meta.projectRoot ?? ''),\n ...(meta.agentId ? { agentId: meta.agentId } : {}),\n // A crashed process's leftover 'running' marker must not render\n // forever — apply the same freshness bound the run guard uses.\n status: running\n ? 'running' as const\n : isStaleRunMarker(meta.status, meta.updatedAt, Date.now(), meta.runOwner)\n ? 'idle' as const\n : (meta.status ?? 'idle'),\n ...(running ? runStartOf(host, meta.id) : {}),\n createdAt: meta.createdAt ?? 0,\n updatedAt: meta.updatedAt,\n archived: md.archived === true,\n ...(md.favorite === true ? { favorite: true } : {}),\n ...(() => {\n const environment = sessionEnvironmentSummary(md)\n return environment ? { environment } : {}\n })(),\n ...(typeof md.providerKey === 'string' ? { providerKey: md.providerKey } : {}),\n ...(typeof md.modelId === 'string' ? { modelId: md.modelId } : {}),\n ...(readSessionAccount(md) ? { account: readSessionAccount(md) } : {}),\n ...(typeof md.effort === 'string' ? { effort: md.effort as SessionRow['effort'] } : {}),\n ...(md.modelOptions && typeof md.modelOptions === 'object'\n ? { modelOptions: md.modelOptions as Record<string, boolean> }\n : {}),\n ...(() => {\n const fallbacks = sessionModelFallbacks(md)\n return fallbacks ? { modelFallbacks: fallbacks } : {}\n })(),\n }\n }))\n }\n\n const ids = await store.list(filter)\n const rows: SessionRow[] = []\n for (const id of ids) {\n const data = await store.load(id)\n if (!data || isSideSession(data.metadata))\n continue\n rows.push(toRow(host, data))\n }\n return applyArchive(rows)\n}\n\n/** The newest `/side` session of `parentId` (`metadata.sideOf`). */\nasync function newestSideSession(store: SessionStore, parentId: string): Promise<string | undefined> {\n const rows = store.listMeta\n ? (await store.listMeta()).map(row => ({ id: row.id, metadata: row.metadata, updatedAt: row.updatedAt }))\n : (await Promise.all((await store.list()).map(async (id) => {\n const data = await store.load(id)\n return { id, metadata: data?.metadata, updatedAt: data?.updatedAt ?? 0 }\n })))\n return rows\n .filter(row => row.id !== parentId && sideSessionParent(row.metadata) === parentId)\n .sort((a, b) => b.updatedAt - a.updatedAt)[0]\n ?.id\n}\n\n/** A running session's `runStartedAt`: its top-level run in progress, as the agent recorded it. */\nfunction runStartOf(host: ChatHost, sessionId: string): { runStartedAt?: number } {\n const run = runInProgress(host.getLiveSession(sessionId)?.runs ?? [])\n return run ? { runStartedAt: run.startedAt } : {}\n}\n\nfunction toRow(host: ChatHost, data: SessionData): SessionRow {\n const meta = data.metadata ?? {}\n // Canonical derivation — same helper as the TUI list (see the\n // listMeta fast path above).\n const title = deriveSessionTitle(data.turns, meta)\n const running = host.isSessionRunning(data.id)\n\n return {\n id: data.id,\n title,\n ...(isMainSession(meta) ? { isMain: true } : {}),\n ...(readSessionSpaceId(meta) ? { spaceId: readSessionSpaceId(meta) } : {}),\n projectRoot: data.projectRoot ?? null,\n cwd: typeof meta.cwd === 'string' ? meta.cwd : (data.projectRoot ?? ''),\n ...(typeof data.agentId === 'string' ? { agentId: data.agentId } : {}),\n status: running\n ? 'running'\n : isStaleRunMarker(data.status, data.updatedAt, Date.now(), data.runOwner)\n ? 'idle'\n : data.status,\n ...(running ? runStartOf(host, data.id) : {}),\n createdAt: data.createdAt,\n updatedAt: data.updatedAt,\n archived: meta.archived === true,\n ...(meta.favorite === true ? { favorite: true } : {}),\n ...(() => {\n const environment = sessionEnvironmentSummary(meta)\n return environment ? { environment } : {}\n })(),\n ...(typeof meta.providerKey === 'string' ? { providerKey: meta.providerKey } : {}),\n ...(typeof meta.modelId === 'string' ? { modelId: meta.modelId } : {}),\n ...(readSessionAccount(meta) ? { account: readSessionAccount(meta) } : {}),\n ...(typeof meta.effort === 'string' ? { effort: meta.effort as SessionRow['effort'] } : {}),\n ...(meta.modelOptions && typeof meta.modelOptions === 'object'\n ? { modelOptions: meta.modelOptions as Record<string, boolean> }\n : {}),\n ...(() => {\n const fallbacks = sessionModelFallbacks(meta)\n return fallbacks ? { modelFallbacks: fallbacks } : {}\n })(),\n }\n}\n","import type { CloneRun } from '../../../chat/git/clone'\n/**\n * A folder's git checkout (`git.*`): the composer's git bar, the branch menu,\n * the Files tab's changed marks and working-tree diffs, a commit chip's facts,\n * sync, the repository import (while `clone` allows it), and a checkout's refs moving (`git.watch`:\n * `git:refs` to the connections that follow it). The git and `gh` work is\n * the desktop app's own (`src/chat/git`, `src/chat/workspace/files`); this\n * slice confines every folder to the host's workspace roots and finds the\n * sessions in a checkout.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { SessionStore } from '../../../session/index'\nimport type { HostPeer } from '../peers'\nimport type { WorkspaceRoots } from '../workspace-roots'\nimport type { Handlers } from './types'\nimport { realpathSync } from 'node:fs'\nimport { cloneRepository } from '../../../chat/git/clone'\nimport { forgetGitCaches, gitBranches, gitCommit, gitCreateBranch, gitInfo, gitPr, gitPrList, gitSwitch } from '../../../chat/git/info'\nimport { parseRepoInput } from '../../../chat/git/repo-url'\nimport { gitSync } from '../../../chat/git/sync'\nimport { createGitWatches } from '../../../chat/git/watch'\nimport { findGitRoot } from '../../../chat/project-root'\nimport { isInside } from '../../../chat/workspace-confinement'\nimport { gitDiff, gitStatus } from '../../../chat/workspace/files'\nimport { InvalidParamsError, optionalString, requiredString } from './params'\nimport { listSessionRows } from './sessions'\n\n/** What `git.clone` answers while a zidane-server's `allowClone` is off. */\nexport const CLONE_OFF_MESSAGE = 'Cloning is off on this server (allowClone).'\n\ntype GitMethod\n = | 'git.status' | 'git.branches' | 'git.pullRequests' | 'git.branchPullRequest' | 'git.commit' | 'git.fileStatus'\n | 'git.diff' | 'git.checkout' | 'git.createBranch' | 'git.sync' | 'git.clone' | 'git.cloneCancel' | 'git.watch' | 'git.unwatch'\n\n/** The checkout holding `folder` (a nested worktree or repository is its own), or the folder outside git. */\nfunction checkoutOf(folder: string): string | null {\n try {\n const real = realpathSync.native(folder)\n return findGitRoot(real) ?? real\n }\n catch {\n return null\n }\n}\n\nexport function createGitHandlers({ host, store, workspace, isConnected, onClose, clone = () => true }: {\n host: ChatHost\n store: SessionStore\n workspace: WorkspaceRoots\n isConnected: (peer: HostPeer) => boolean\n /** Registers a peer-close hook: a dropped connection's clone is cancelled, its watches released. */\n onClose: (release: (peer: HostPeer) => void) => void\n /** Clients may clone (`git.clone`): a zidane-server's `allowClone`. Default: yes. */\n clone?: () => boolean\n}): Handlers<GitMethod> {\n const clones = new Map<HostPeer, CloneRun>()\n onClose(peer => clones.get(peer)?.cancel())\n // Keyed by the folder as each client names it: `git:refs` carries that name back.\n const refs = createGitWatches<HostPeer>((cwd, change) => {\n forgetGitCaches(cwd, change === 'refs' ? 'git:refs' : 'git:config')\n if (change === 'refs') {\n for (const peer of refs.owners(cwd))\n peer.send({ kind: 'git:refs', cwd })\n }\n })\n onClose(peer => refs.release(peer))\n const folder = (cwd: unknown): string => workspace.resolveFolder(requiredString(cwd, 'cwd'))\n /** `folder`, when the checkout holding it is inside the roots too: git reports on the whole repository, not the folder it runs in. */\n const repoFolder = (cwd: unknown): string => {\n const at = folder(cwd)\n workspace.resolveFolder(findGitRoot(at) ?? at)\n return at\n }\n\n /** The unarchived sessions working in `cwd`'s checkout, `except` left out. */\n async function sessionsInCheckout(cwd: string, except?: string): Promise<string[]> {\n const checkout = checkoutOf(cwd)\n if (!checkout)\n return []\n const rows = await listSessionRows(host, store, { archive: 'active' })\n return rows.filter(row => row.id !== except && row.cwd && checkoutOf(row.cwd) === checkout).map(row => row.id)\n }\n\n /** An agent runs in `cwd`'s checkout (the asking session included). */\n async function agentRunsIn(cwd: string, sessionId: string | undefined): Promise<boolean> {\n if (sessionId && host.isSessionRunning(sessionId))\n return true\n return (await sessionsInCheckout(cwd, sessionId)).some(id => host.isSessionRunning(id))\n }\n\n return {\n 'git.status': p => gitInfo(folder(p.cwd)),\n 'git.branches': p => gitBranches(folder(p.cwd)),\n 'git.pullRequests': p => gitPrList(folder(p.cwd), optionalString(p.search, 'search'), p.fresh === true),\n 'git.branchPullRequest': p => gitPr(folder(p.cwd), requiredString(p.branch, 'branch'), p.fresh === true),\n 'git.commit': p => gitCommit(repoFolder(p.cwd), requiredString(p.sha, 'sha')),\n 'git.fileStatus': p => gitStatus(repoFolder(p.cwd)),\n 'git.diff': (p) => {\n if (p.context !== undefined && p.context !== null && (typeof p.context !== 'number' || p.context < 0))\n throw new InvalidParamsError('context must be a non-negative number or null.')\n return gitDiff(repoFolder(p.cwd), optionalString(p.path, 'path'), p.context === null ? Infinity : p.context)\n },\n 'git.checkout': async (p) => {\n const cwd = folder(p.cwd)\n const target = p.target as unknown\n const pr = typeof target === 'object' && target !== null ? (target as { pr?: unknown }).pr : undefined\n if (typeof target !== 'string' && typeof pr !== 'number')\n throw new InvalidParamsError('target must be a branch name or { pr: number }.')\n const sessionId = optionalString(p.sessionId, 'sessionId')\n const result = await gitSwitch(cwd, typeof target === 'string' ? target : { pr: pr as number }, await agentRunsIn(cwd, sessionId))\n if (result.ok || !result.worktree)\n return result\n // git names the worktree resolved: only one inside the roots is told apart by its sessions.\n const inRoots = workspace.describe().roots.some(root => isInside(root, result.worktree!))\n return { ...result, chats: inRoots ? await sessionsInCheckout(result.worktree, sessionId) : [] }\n },\n 'git.createBranch': async (p) => {\n const cwd = folder(p.cwd)\n return gitCreateBranch(cwd, requiredString(p.name, 'name'), await agentRunsIn(cwd, optionalString(p.sessionId, 'sessionId')))\n },\n 'git.sync': async (p) => {\n const cwd = folder(p.cwd)\n return gitSync(cwd, await agentRunsIn(cwd, optionalString(p.sessionId, 'sessionId')))\n },\n 'git.clone': async (p, peer) => {\n if (!clone())\n throw new Error(CLONE_OFF_MESSAGE)\n const input = requiredString(p.input, 'input')\n const parent = workspace.resolveFolder(requiredString(p.parent, 'parent'))\n // A `file://` source is a folder on this machine: confined like `parent`, or a client copies out what the roots keep from it.\n const spec = parseRepoInput(input)\n if (spec && /^file:/i.test(spec.cloneUrl)) {\n const source = new URL(spec.cloneUrl)\n if (source.host && source.host !== 'localhost')\n throw new InvalidParamsError('A file:// source must be on this machine.')\n workspace.resolveFolder(decodeURIComponent(source.pathname))\n }\n if (clones.has(peer))\n return { ok: false, error: 'A clone is already running.' }\n const run = cloneRepository(input, parent, ({ phase, percent }) => {\n if (isConnected(peer))\n peer.send({ kind: 'git:clone:progress', phase, percent })\n })\n clones.set(peer, run)\n try {\n return await run.result\n }\n finally {\n clones.delete(peer)\n }\n },\n 'git.cloneCancel': (_p, peer) => {\n clones.get(peer)?.cancel()\n },\n 'git.watch': (p, peer) => {\n folder(p.cwd)\n return refs.watch(p.cwd, peer)\n },\n 'git.unwatch': (p, peer) => {\n refs.unwatch(peer, requiredString(p.cwd, 'cwd'))\n },\n }\n}\n","/** Transcript history search, per session and across sessions, over one shared index cache. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { SessionHistoryMatch, SessionSearchIndex } from '../../../chat/index'\nimport type { SessionStore } from '../../../session/index'\nimport type { SessionTurn } from '../../../types'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { buildSessionSearchIndexAsync, searchSessionHistoryIndexAsync, searchSessionIndexAsync } from '../../../chat/history-search'\n\n/*\n * Daemon-side history search — one index cache shared by EVERY window,\n * so repeat queries (and other windows' queries) pay match cost only.\n * Off the UI thread by construction (this process has no renderer), so\n * no Worker indirection is needed. Live sessions index the host's\n * in-memory turns (fresh mid-run); idle sessions index store turns.\n * LRU-bounded — full-text indexes can reach 512k chars per turn.\n */\nconst SEARCH_INDEX_CACHE_MAX = 64\n\nexport function createHistoryHandlers({ host, store }: {\n host: ChatHost\n store: SessionStore\n}): Handlers<'history.searchSession' | 'history.searchAll'> {\n /** Latest `history.searchAll` generation per peer — see the handler. */\n const searchGenerations = new WeakMap<HostPeer, number>()\n const searchIndexCache = new Map<string, { key: string, index: SessionSearchIndex }>()\n\n async function sessionSearchIndex(sessionId: string): Promise<SessionSearchIndex | null> {\n const liveTurns = host.getLiveTurns(sessionId)\n let turns: readonly SessionTurn[]\n let key: string\n if (liveTurns) {\n /*\n * SNAPSHOT before the async index build — the agent may append\n * mid-build and the builder yields between turns. The cache key\n * folds in the last turn id so a same-count content change (e.g.\n * compaction replacing turns) can't serve a stale index.\n */\n turns = [...liveTurns]\n key = `live:${turns.length}:${turns.at(-1)?.id ?? ''}`\n }\n else {\n const data = await store.load(sessionId)\n if (!data)\n return null\n turns = data.turns\n key = `store:${data.updatedAt}:${data.turns.length}`\n }\n\n const cached = searchIndexCache.get(sessionId)\n if (cached?.key === key) {\n // Refresh LRU recency (Map preserves insertion order).\n searchIndexCache.delete(sessionId)\n searchIndexCache.set(sessionId, cached)\n return cached.index\n }\n\n const index = await buildSessionSearchIndexAsync(turns)\n searchIndexCache.set(sessionId, { key, index })\n while (searchIndexCache.size > SEARCH_INDEX_CACHE_MAX) {\n const oldest = searchIndexCache.keys().next().value\n if (oldest === undefined)\n break\n searchIndexCache.delete(oldest)\n }\n return index\n }\n\n return {\n 'history.searchSession': async (p) => {\n const index = await sessionSearchIndex(p.sessionId)\n if (!index)\n return []\n // Wire-supplied limit: unchecked JSON — coerce to a sane positive\n // integer bounded by the corpus (same policy as queue/draft bounds).\n const limit = Number.isInteger(p.limit) && (p.limit as number) > 0\n ? Math.min(p.limit as number, index.turns.length)\n : index.turns.length\n const matches = await searchSessionIndexAsync(index, p.query, { limit })\n // Turn order, not relevance — search is a transcript filter, and\n // sorting here spares clients from re-fetching the turn list.\n const order = new Map(index.turns.map((entry, i) => [entry.turn.id, i]))\n matches.sort((a, b) => (order.get(a.turn.id) ?? 0) - (order.get(b.turn.id) ?? 0))\n return matches\n },\n 'history.searchAll': async (p, peer) => {\n /*\n * Per-peer supersession: search fires per debounced keystroke and\n * the client discards stale responses, but without this the daemon\n * would still run every superseded full-corpus pass to completion —\n * stacked CPU that delays signal fan-out for every window. A newer\n * query from the same peer makes older loops bail at the next\n * session boundary (partial result; the client ignores it anyway).\n */\n const generation = (searchGenerations.get(peer) ?? 0) + 1\n searchGenerations.set(peer, generation)\n\n const results: Record<string, SessionHistoryMatch> = {}\n // Bound the per-request corpus: `store.load` materializes full turn\n // arrays, and supersession only cancels SAME-peer re-queries — one\n // oversized request must not run the shared daemon to completion.\n const ids = Array.isArray(p.sessionIds) ? p.sessionIds.slice(0, 500) : []\n for (const sessionId of ids) {\n if (searchGenerations.get(peer) !== generation)\n break\n try {\n const index = await sessionSearchIndex(sessionId)\n if (!index)\n continue\n const match = await searchSessionHistoryIndexAsync(index, p.query, p.excerptLimit ?? 3)\n if (match)\n results[sessionId] = match\n }\n catch {\n // One bad session must not sink the whole cross-session search.\n }\n }\n return results\n },\n }\n}\n","/**\n * Human-in-the-loop: tool approvals and interactions (questions, plans)\n * awaiting an answer, and the \"Always allow\" entries approvals saved (the\n * host user's `projects.json`).\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { PendingInteraction } from '../../../chat/host/signals'\nimport type { SessionStore } from '../../../session/index'\nimport type { Handlers } from './types'\nimport { pendingInteractionsFromTurns } from '../../../chat/interactions-protocol'\nimport { listSafelists, removeFromSafelist } from '../../../chat/safe-mode'\nimport { requiredString } from './params'\n\ntype HitlMethod\n = | 'interactions.list' | 'interactions.respond' | 'interactions.cancel' | 'interactions.rehydrate' | 'interactions.rehydrateSessions'\n | 'approvals.resolve' | 'approvals.denyAll' | 'approvals.listPending'\n | 'safelist.list' | 'safelist.remove'\n\n/** Turns read back from a session's end to find a question its run stopped on (notes may follow it). */\nconst OPEN_PROMPT_TAIL = 20\n\n/**\n * Whether the session's last turns hold a question or plan with no answer,\n * read without loading the session. A store with no header index answers\n * `true`: it is loaded, as a window opening it would.\n */\nasync function endsOnOpenPrompt(store: SessionStore, sessionId: string): Promise<boolean> {\n if (!store.getMeta)\n return true\n const meta = await store.getMeta(sessionId)\n if (!meta)\n return false\n // `turnCount` leaves out system turns: from there, the tail still reaches the last turn.\n const tail = await store.getTurns(sessionId, Math.max(0, (meta.turnCount ?? 0) - OPEN_PROMPT_TAIL))\n return pendingInteractionsFromTurns(tail).length > 0\n}\n\nexport function createHitlHandlers({ host, store, userDataDir }: { host: ChatHost, store: SessionStore, userDataDir: () => string }): Handlers<HitlMethod> {\n return {\n 'interactions.list': p => host.interactions.list(p?.sessionId),\n 'interactions.respond': p => host.interactions.respond(p.requestId, p.response),\n 'interactions.cancel': p => host.interactions.cancel(p.requestId, p.reason),\n // A window opening a session: a durable run a dead process left resumes, or its question goes up first, so the list below has it.\n 'interactions.rehydrate': async (p) => {\n await host.resumePending({ sessionId: p.sessionId }).catch(() => undefined)\n return host.interactions.rehydrate(p.sessionId)\n },\n // A channel start, over every conversation it ever had: a session is loaded only when its run waits to resume or its last turns ask.\n 'interactions.rehydrateSessions': async (p) => {\n const out: PendingInteraction[] = []\n for (const sessionId of Array.isArray(p.sessionIds) ? p.sessionIds : []) {\n if (typeof sessionId !== 'string' || host.isSessionRunning(sessionId))\n continue\n await host.resumePending({ sessionId }).catch(() => undefined)\n if (await endsOnOpenPrompt(store, sessionId).catch(() => false))\n out.push(...await host.interactions.rehydrate(sessionId))\n }\n return out\n },\n\n 'approvals.resolve': p => host.approvals.resolve(p.requestId, p.decision),\n 'approvals.denyAll': p => host.approvals.denyAll(p?.sessionId),\n 'approvals.listPending': () => host.approvals.listPending(),\n\n 'safelist.list': () => ({ projects: listSafelists(userDataDir()) }),\n 'safelist.remove': p => ({ removed: removeFromSafelist(userDataDir(), requiredString(p.project, 'project'), requiredString(p.entry, 'entry')) }),\n }\n}\n","/** Per-client launch overrides: each window's own, the latest connected setter's applied. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { SessionLaunchOverrides } from '../../../chat/host/launch-overrides'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { normalizeLaunchOverrides } from '../../../chat/host/launch-overrides'\n\n/**\n * A confined host (a server) drops a `cwd` outside its workspace roots\n * itself (`ChatHost.setLaunchOverrides`): a window's own folder is a path on\n * ITS machine, which the session must not move to.\n */\nexport function createLaunchOverrideHandlers({ host }: { host: ChatHost }): {\n methods: Handlers<'sessions.setLaunchOverrides'>\n /** The peer dropped: forget its overrides, so the previous setter's apply again. */\n releasePeer: (peer: HostPeer) => void\n /** The session was deleted: forget every setter's overrides. */\n forget: (sessionId: string) => void\n} {\n /**\n * Each client's launch overrides per session, oldest setter first. The\n * session runs the most recent connected setter's; a client clearing, or\n * disconnecting, drops only its own, and the previous setter's apply again.\n */\n const launchOverridesByPeer = new Map<string, Map<HostPeer, SessionLaunchOverrides>>()\n\n /** Run the latest connected setter's overrides (see `launchOverridesByPeer`). */\n const applyLaunchOverrides = (sessionId: string): void => {\n const setters = launchOverridesByPeer.get(sessionId)\n const latest = setters ? [...setters.values()].at(-1) : undefined\n if (!latest)\n launchOverridesByPeer.delete(sessionId)\n host.setLaunchOverrides(sessionId, latest ?? null)\n }\n\n return {\n methods: {\n 'sessions.setLaunchOverrides': (p, peer) => {\n const { sessionId, ...rest } = p\n const next = normalizeLaunchOverrides(rest)\n const setters = launchOverridesByPeer.get(sessionId) ?? new Map<HostPeer, SessionLaunchOverrides>()\n // Re-inserted, so a client setting again becomes the latest setter.\n setters.delete(peer)\n if (next)\n setters.set(peer, next)\n launchOverridesByPeer.set(sessionId, setters)\n applyLaunchOverrides(sessionId)\n },\n },\n releasePeer(peer) {\n for (const [sessionId, setters] of launchOverridesByPeer) {\n if (setters.delete(peer))\n applyLaunchOverrides(sessionId)\n }\n },\n forget(sessionId) {\n launchOverridesByPeer.delete(sessionId)\n },\n }\n}\n","/**\n * Reverse direction (`docs/MACHINES.md` § Reverse direction): this server\n * lends itself as a machine to a client's host over that client's own\n * connection, because a local host (a laptop) has no listener to be dialed.\n * The client sends `machine.attach`, then one `machine.call` per\n * host→machine request; the server's confined executor\n * (`../../machine/executor`, loaded on first attach) answers them inside the\n * server's workspace roots. Machine notifications go back to that connection\n * only, as `machine:notification` signals.\n *\n * Off unless the server allows it (`allowAsMachine`). It does not widen what a\n * client token can do: `sessions.workspaceExec` and terminals already run\n * commands in the same roots with the same token.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { MachineRegisterParams } from '../../../chat/machine-protocol'\nimport type { LooseSandboxSettings } from '../../../chat/sandbox-settings'\nimport type { JsonValue } from '../../../types'\nimport type { MachineExecutor } from '../../machine/executor'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { join } from 'node:path'\nimport { MACHINE_PROTOCOL_VERSION, MachineErrorCode, toMachineName } from '../../../chat/machine-protocol'\nimport { ZIDANE_VERSION } from '../../../version'\n\n/**\n * Executors kept between their connections (tasks, terminals), keyed by the\n * token that attached them and the host id it named: a host id is the\n * client's word, so another token naming it gets an executor of its own,\n * never the first one's tasks, terminals or exits. Each token holds at most\n * {@link MAX_PER_PRINCIPAL} and evicts only its own idle ones.\n */\nconst MAX_PER_PRINCIPAL = 4\nconst MAX_ATTACHED_HOSTS = 32\n\nexport interface MachineServeOptions {\n /** `allowAsMachine`: read per attach, so a restart is not needed to turn it off for new links. */\n allowed: () => boolean\n}\n\nclass MachineServeError extends Error {\n readonly code: number = MachineErrorCode.MethodNotAllowed\n}\n\n/** A capacity limit: the client retries later (`../../machine/reverse.ts`). */\nclass MachineServeBusyError extends MachineServeError {\n override readonly code: number = MachineErrorCode.Busy\n}\n\ninterface Served {\n executor: MachineExecutor\n peer: HostPeer | null\n principal: string\n}\n\n/** Who attached: the token's id (`''` on a host without auth, a loopback test server). */\nconst principalOf = (peer: HostPeer): string => peer.principal ?? ''\n\nexport function createMachineServeHandlers(input: {\n host: ChatHost\n dataDir: () => string\n hostName: string\n settings: () => LooseSandboxSettings\n options?: MachineServeOptions\n isConnected: (peer: HostPeer) => boolean\n}): { methods: Handlers<'machine.attach' | 'machine.call' | 'machine.detach'>, releasePeer: (peer: HostPeer) => void, allowed: () => boolean } {\n const { host } = input\n const allowed = (): boolean => input.options?.allowed() === true\n const served = new Map<string, Served>()\n const byPeer = new Map<HostPeer, string>()\n\n const roots = (): string[] => {\n const { roots: list, confined } = host.workspace\n if (!confined || list.length === 0)\n throw new MachineServeError('This host has no workspace roots to lend.')\n return [...list]\n }\n\n /** Make room for one more of `principal`'s: its own idle executor goes, never another token's. */\n const makeRoom = (principal: string): void => {\n const own = [...served].filter(([, entry]) => entry.principal === principal)\n if (own.length < MAX_PER_PRINCIPAL && served.size < MAX_ATTACHED_HOSTS)\n return\n const idle = own.find(([, entry]) => entry.peer === null)\n if (!idle)\n throw new MachineServeBusyError(own.length >= MAX_PER_PRINCIPAL ? `This token already has ${MAX_PER_PRINCIPAL} hosts attached here.` : `This server already lends itself to ${MAX_ATTACHED_HOSTS} hosts.`)\n served.delete(idle[0])\n void idle[1].executor.close()\n }\n\n async function executorFor(hostId: string, peer: HostPeer): Promise<MachineExecutor> {\n const principal = principalOf(peer)\n const key = `${principal}:${hostId}`\n const existing = served.get(key)\n if (existing) {\n const previous = existing.peer\n if (previous && previous !== peer)\n byPeer.delete(previous)\n existing.peer = peer\n return existing.executor\n }\n makeRoom(principal)\n const { createMachineExecutor } = await import('../../machine/executor')\n const entry: Served = { peer, principal, executor: undefined as unknown as MachineExecutor }\n entry.executor = createMachineExecutor({\n roots: roots().map(path => ({ path })),\n dataDir: join(input.dataDir(), 'machine-self'),\n // The server's own sandbox settings apply to what it runs as a machine, as to its own sessions.\n sandbox: input.settings(),\n credentialsDataDir: input.dataDir(),\n notify: (method, params) => {\n const target = entry.peer\n if (!target || !input.isConnected(target))\n return false\n target.send({ kind: 'machine:notification', method, params: params as JsonValue })\n return true\n },\n })\n served.set(key, entry)\n return entry.executor\n }\n\n const attachedOf = (peer: HostPeer): Served => {\n const key = byPeer.get(peer)\n const entry = key ? served.get(key) : undefined\n if (!entry || entry.peer !== peer)\n throw new MachineServeError('Send machine.attach first on this connection.')\n return entry\n }\n\n return {\n allowed,\n methods: {\n 'machine.attach': async (p, peer) => {\n if (!allowed())\n throw new MachineServeError('This server does not lend itself as a machine (allowAsMachine is off).')\n if (typeof p.hostId !== 'string' || !/^[\\w-]{1,64}$/.test(p.hostId))\n throw new MachineServeError('machine.attach: \"hostId\" must be 1 to 64 letters, digits, \"-\" or \"_\".')\n const executor = await executorFor(p.hostId, peer)\n byPeer.set(peer, `${principalOf(peer)}:${p.hostId}`)\n executor.linkUp()\n const { machineIdentity } = await import('../../machine/identity')\n const result: MachineRegisterParams = {\n machineId: machineIdentity(join(input.dataDir(), 'machine-self')),\n name: toMachineName(input.hostName),\n roots: roots().map(path => ({ path })),\n capabilities: { shell: true, terminals: typeof (globalThis as { Bun?: unknown }).Bun !== 'undefined', background: true, worktrees: true, stream: true, sandboxed: executor.sandbox.on },\n version: ZIDANE_VERSION,\n protocolVersion: MACHINE_PROTOCOL_VERSION,\n }\n return result\n },\n 'machine.call': async (p, peer) => {\n if (!allowed())\n throw new MachineServeError('This server does not lend itself as a machine (allowAsMachine is off).')\n if (typeof p.method !== 'string')\n throw new MachineServeError('machine.call: \"method\" must be a string.')\n return (await attachedOf(peer).executor.handle(p.method, p.params ?? {})) as JsonValue\n },\n 'machine.detach': (_p, peer) => {\n const key = byPeer.get(peer)\n if (!key)\n return { detached: false }\n byPeer.delete(peer)\n const entry = served.get(key)\n if (entry?.peer === peer) {\n entry.peer = null\n entry.executor.linkLost()\n }\n return { detached: true }\n },\n },\n releasePeer(peer) {\n const key = byPeer.get(peer)\n if (!key)\n return\n byPeer.delete(peer)\n const entry = served.get(key)\n if (entry?.peer === peer) {\n entry.peer = null\n entry.executor.linkLost()\n }\n },\n }\n}\n","/**\n * OAuth sign-in over the wire (`auth.oauth.*`): the browser on the client,\n * the tokens on the host.\n *\n * `begin` runs the login HERE (a provider's `runOAuthLogin`, an MCP server's\n * `loginMcpServer`), so the PKCE verifier, `state` and the token exchange\n * never leave the host, and answers with the authorization URL as soon as\n * the login produces it. The redirect lands on the client's loopback (a\n * provider's fixed `redirect_uri`, or the loopback URI the client chose for\n * an MCP server; a browser client's MCP sign-in comes back to this server's\n * own callback instead: `deliverCallback`); the client sends the code back with `complete`, which\n * checks `state` here and hands the code to the waiting login: zidane's\n * providers read it through their manual-input path (`callbackServer:\n * false`: nothing listens on this machine), an MCP login through an\n * injected callback. Paste-back and device-code flows ride the same calls.\n *\n * A provider's questions (a choice between flows, a free-text prompt) are\n * the client's to answer, never picked here: `begin` answers with a `step`\n * when one comes before the URL, `complete` when one comes after, and\n * `respond` delivers the answer. A provider that would listen on this\n * machine for the redirect (one that ignores `callbackServer: false`) is\n * refused: the client's browser could never reach that port.\n *\n * A flow is bound to the connection that began it, takes one code, and\n * expires; a dropped connection abandons its flows. Codes and tokens are\n * never logged nor returned.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { McpStatusTracker } from '../../../chat/mcp-status'\nimport type { McpServerConfig } from '../../../types'\nimport type { HostOAuthBegin, HostOAuthComplete, HostOAuthStep } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { HostPeer } from '../peers'\nimport type { ProviderAuth } from './auth'\nimport type { Handlers } from './types'\nimport { randomBytes } from 'node:crypto'\nimport { setProviderCredential } from '../../../chat/credentials'\nimport { createFileMcpCredentialStore } from '../../../chat/mcp-credentials'\nimport { discoverProjectMcps } from '../../../chat/mcps-discovery'\nimport { runOAuthLogin } from '../../../chat/oauth'\nimport { canSignInRemotely } from '../../../chat/oauth-page/server'\nimport { loginMcpServer } from '../../../mcp/login'\nimport { pinnedMcpRedirectUri } from '../../../mcp/server-config'\nimport { SERVER_OAUTH_CALLBACK_PATH } from '../../browser'\nimport { catalogFolder } from './catalogs'\nimport { InvalidParamsError } from './params'\n\n/** How long a flow waits for its code. */\nexport const OAUTH_FLOW_TTL_MS = 10 * 60_000\n/** Open flows per connection. */\nconst MAX_FLOWS_PER_PEER = 4\n/** How long a login may take to produce its URL. */\nconst BEGIN_TIMEOUT_MS = 30_000\n\ntype Delivery = { code: string, state?: string } | { input: string }\n\ninterface Flow {\n id: string\n peer: HostPeer\n expiresAt: number\n /** The `state` the authorization URL carries; a code must come back with it. */\n expectedState?: string\n /** Where the browser is sent back (rebuilds a callback URL from a code + state). */\n redirectUri?: string\n /** The code comes back to this server's own callback (`deliverCallback`): the MCP server signed in to. */\n held?: string\n delivered: boolean\n deliver: (delivery: Delivery) => void\n result: Promise<HostOAuthComplete>\n abort: AbortController\n timer: ReturnType<typeof setTimeout>\n /** The provider's questions (absent: an MCP sign-in, which asks none). */\n steps?: StepChannel\n /** Where the flow stands for `respond`: its URL once known. */\n started?: Promise<Omit<HostOAuthBegin, 'flowId' | 'expiresAt'>>\n /** Set once the URL was handed out: later questions come through `complete`. */\n begun?: Omit<HostOAuthBegin, 'flowId' | 'expiresAt'>\n}\n\ntype StepInput = { kind: 'select', message: string, options: Array<{ id: string, label: string }> } | { kind: 'prompt', message: string, placeholder?: string, allowEmpty?: boolean }\n\n/** A provider's questions, one at a time: asked by its login, answered by the client. */\ninterface StepChannel {\n ask: (step: StepInput) => Promise<string | undefined>\n /** The question waiting for its answer. */\n pending: () => HostOAuthStep | undefined\n /** The next question (the pending one, if any). */\n next: () => Promise<HostOAuthStep>\n answer: (stepId: string, value: string | undefined) => void\n}\n\nfunction stepChannel(signal: AbortSignal): StepChannel {\n let current: { step: HostOAuthStep, resolve: (value: string | undefined) => void } | undefined\n const waiters: Array<(step: HostOAuthStep) => void> = []\n return {\n ask: step => new Promise((resolve, reject) => {\n if (signal.aborted)\n return reject(new Error('The sign-in was cancelled.'))\n const full = { ...step, id: randomBytes(9).toString('base64url') } as HostOAuthStep\n current = { step: full, resolve }\n signal.addEventListener('abort', () => reject(new Error('The sign-in was cancelled.')), { once: true })\n for (const waiter of waiters.splice(0))\n waiter(full)\n }),\n pending: () => current?.step,\n next: () => (current ? Promise.resolve(current.step) : new Promise(resolve => waiters.push(resolve))),\n answer(stepId, value) {\n const step = current?.step\n if (!step || step.id !== stepId)\n throw new Error('That sign-in is not waiting on this question (answered already, or another one).')\n if (step.kind === 'select' && value !== undefined && !step.options.some(option => option.id === value))\n throw new InvalidParamsError(`\"${value}\" is not one of the choices.`)\n if (step.kind === 'prompt' && (value === undefined || (value.trim() === '' && !step.allowEmpty)))\n throw new InvalidParamsError('That question needs an answer.')\n const { resolve } = current!\n current = undefined\n resolve(value)\n },\n }\n}\n\ninterface Deferred<T> {\n promise: Promise<T>\n resolve: (value: T) => void\n}\n\nfunction deferred<T>(): Deferred<T> {\n let resolve!: (value: T) => void\n const promise = new Promise<T>((r) => {\n resolve = r\n })\n return { promise, resolve }\n}\n\nconst LOOPBACK_HOSTS = new Set(['127.0.0.1', 'localhost', '[::1]', '::1'])\n\n/**\n * Where an MCP sign-in may send the browser: `http://<loopback>:<port>/<path>`\n * on the client, or (`held`) this server's own callback at the origin the\n * client reaches it by, when it serves one. Nothing else.\n */\nfunction mcpRedirect(raw: unknown, serverCallback: boolean): { uri: string, held: boolean } {\n let url: URL | undefined\n try {\n url = typeof raw === 'string' ? new URL(raw) : undefined\n }\n catch {}\n const plain = url !== undefined && !url.username && !url.password && !url.search && !url.hash\n if (plain && serverCallback && (url!.protocol === 'https:' || url!.protocol === 'http:') && url!.pathname === SERVER_OAUTH_CALLBACK_PATH)\n return { uri: url!.toString(), held: true }\n if (!plain || url!.protocol !== 'http:' || !LOOPBACK_HOSTS.has(url!.hostname) || !url!.port)\n throw new InvalidParamsError(`redirectUri must be a loopback URL on the client (http://127.0.0.1:<port>/callback)${serverCallback ? ` or this server's ${SERVER_OAUTH_CALLBACK_PATH}` : ''}.`)\n return { uri: url!.toString(), held: false }\n}\n\n/** `state` in what a user pasted: a callback URL, a `code=…&state=…` query, or Anthropic's `code#state`. */\nfunction stateIn(input: string): string | undefined {\n const value = input.trim()\n try {\n return new URL(value).searchParams.get('state') ?? undefined\n }\n catch {}\n if (value.includes('#'))\n return value.split('#', 2)[1]\n if (value.includes('state='))\n return new URLSearchParams(value).get('state') ?? undefined\n return undefined\n}\n\n/** The code in a pasted callback URL / query / `code#state`. */\nfunction codeIn(input: string): string | undefined {\n const value = input.trim()\n try {\n return new URL(value).searchParams.get('code') ?? undefined\n }\n catch {}\n if (value.includes('#'))\n return value.split('#', 2)[0]\n if (value.includes('code='))\n return new URLSearchParams(value).get('code') ?? undefined\n return value || undefined\n}\n\nfunction isLoopbackUrl(raw: string | null): raw is string {\n if (!raw)\n return false\n try {\n const url = new URL(raw)\n return url.protocol === 'http:' && LOOPBACK_HOSTS.has(url.hostname)\n }\n catch {\n return false\n }\n}\n\n/** What a provider's manual-input path reads: the pasted text, or the callback URL rebuilt from a code + state. */\nfunction manualInput(delivery: Delivery, redirectUri: string | undefined): string {\n if ('input' in delivery)\n return delivery.input\n const query = new URLSearchParams({ code: delivery.code, ...(delivery.state !== undefined ? { state: delivery.state } : {}) }).toString()\n return redirectUri ? `${redirectUri}?${query}` : query\n}\n\n/** First of: what the login produced, its early end, a timeout, the abort. */\nasync function firstOf<T>(started: Promise<T>, login: Promise<unknown>, signal: AbortSignal): Promise<T> {\n let timer: ReturnType<typeof setTimeout> | undefined\n try {\n return await Promise.race([\n started,\n login.then(() => {\n throw new Error('The sign-in finished without a browser step (already signed in?).')\n }),\n new Promise<never>((_, reject) => {\n timer = setTimeout(reject, BEGIN_TIMEOUT_MS, new Error(`The sign-in did not produce an authorization URL within ${BEGIN_TIMEOUT_MS / 1000}s.`))\n signal.addEventListener('abort', () => reject(new Error('The sign-in was cancelled.')), { once: true })\n }),\n ])\n }\n finally {\n clearTimeout(timer)\n }\n}\n\n/**\n * A provider's login, running here for a client: its URL (once known), its\n * questions, the code the client delivers, its stored result. Refused for a\n * provider that would listen on this machine (see the module header).\n */\nfunction startProviderLogin(auth: ProviderAuth, provider: unknown) {\n const descriptor = auth.descriptorOf(provider)\n if (!descriptor.oauthProvider)\n throw new Error(`OAuth not supported for ${descriptor.label} (${descriptor.key}). Use an API key instead.`)\n if (!canSignInRemotely(descriptor.oauthProvider))\n throw new Error(`${descriptor.label}'s sign-in can't run from another computer: it waits for the browser on a port of the server's own machine. Sign in on the server machine or use an API key.`)\n const abort = new AbortController()\n const code = deferred<string>()\n const steps = stepChannel(abort.signal)\n const url = deferred<{ url: string, instructions?: string, userCode?: string, device?: true }>()\n const login = runOAuthLogin(descriptor, {\n onUrl: (u, instructions) => url.resolve({ url: u, ...(instructions ? { instructions } : {}) }),\n onDeviceCode: info => url.resolve({ url: info.verificationUri, userCode: info.userCode, device: true }),\n // The loopback's callback URL, or what the user pasted.\n onManualCodeInput: () => code.promise,\n // The provider's own questions go to the client (never answered here).\n onPrompt: prompt => steps.ask({ kind: 'prompt', message: prompt.message, ...(prompt.placeholder ? { placeholder: prompt.placeholder } : {}), ...(prompt.allowEmpty ? { allowEmpty: true } : {}) }).then(value => value ?? ''),\n onSelect: prompt => steps.ask({ kind: 'select', message: prompt.message, options: prompt.options.map(option => ({ id: option.id, label: option.label })) }),\n signal: abort.signal,\n callbackServer: false,\n openBrowser: false,\n })\n login.catch(() => undefined)\n // Where the flow stands once it has its URL (the loopback redirect the code is rebuilt for).\n let redirectUri: string | undefined\n const started = url.promise.then((first): Omit<HostOAuthBegin, 'flowId' | 'expiresAt'> => {\n if (!first.device) {\n const redirect = new URL(first.url).searchParams.get('redirect_uri')\n if (isLoopbackUrl(redirect))\n redirectUri = redirect\n }\n return {\n url: first.url,\n mode: first.device ? 'device' : redirectUri ? 'loopback' : 'browser',\n ...(redirectUri ? { redirectUri } : {}),\n ...(first.userCode ? { userCode: first.userCode } : {}),\n ...(first.instructions ? { instructions: first.instructions } : {}),\n }\n })\n started.catch(() => undefined)\n const result = login.then((credentials): HostOAuthComplete => {\n setProviderCredential(auth.dataDir(), descriptor, { kind: 'oauth', ...credentials })\n auth.applied(descriptor)\n return { provider: auth.statusOf(descriptor.key) }\n })\n return { login, abort, result, steps, started, deliver: (delivery: Delivery) => code.resolve(manualInput(delivery, redirectUri)) }\n}\n\n/** The flow `flowId` names, if it exists and belongs to this connection. */\nfunction flowOf(flows: ReadonlyMap<string, Flow>, flowId: unknown, peer: HostPeer): Flow {\n const flow = typeof flowId === 'string' ? flows.get(flowId) : undefined\n if (!flow)\n throw new Error('No sign-in with that id: it finished, expired or was cancelled. Start it again.')\n if (flow.peer !== peer)\n throw new Error('That sign-in belongs to another connection.')\n return flow\n}\n\n/** Hand the flow its code (from the client's loopback) or pasted input, once, after checking its `state`. */\nfunction deliverCode(flow: Flow, p: { code?: unknown, state?: unknown, input?: unknown }, end: (flow: Flow, reason: string) => void): void {\n const code = typeof p.code === 'string' && p.code !== '' ? p.code : undefined\n const input = typeof p.input === 'string' && p.input.trim() !== '' ? p.input : undefined\n if (code === undefined && input === undefined)\n return\n if (flow.delivered)\n throw new Error('That sign-in already received its code.')\n const state = code !== undefined ? (typeof p.state === 'string' ? p.state : undefined) : stateIn(input!)\n // A code from the loopback must carry the flow's state; a pasted bare code (Anthropic's page) may omit it.\n if (flow.expectedState !== undefined && (state !== undefined || code !== undefined) && state !== flow.expectedState) {\n end(flow, 'OAuth state mismatch.')\n throw new Error('OAuth state mismatch: the sign-in was refused. Start it again.')\n }\n flow.delivered = true\n flow.deliver(code !== undefined ? { code, ...(state !== undefined ? { state } : {}) } : { input: input! })\n}\n\n/** The browser back at the server's callback: the code to the held flow its `state` names (or the refusal ends it). */\nfunction deliverCallback(flows: ReadonlyMap<string, Flow>, query: URLSearchParams, end: (flow: Flow, reason: string) => void): string | undefined {\n const state = query.get('state')\n const flow = state ? [...flows.values()].find(f => f.held && f.expectedState === state) : undefined\n if (!flow?.held || flow.delivered)\n return undefined\n const code = query.get('code')\n if (!code) {\n end(flow, query.get('error_description') ?? query.get('error') ?? 'The sign-in was refused.')\n return flow.held\n }\n flow.delivered = true\n flow.deliver({ code, state: state! })\n return flow.held\n}\n\nexport function createOAuthFlowHandlers({ host, env, auth, mcpStatus, isConnected, serverCallback = false, ttlMs = OAUTH_FLOW_TTL_MS }: {\n host: Pick<ChatHost, 'resolveFolder' | 'rebuildAllAgents'>\n env: DaemonEnvironment\n auth: ProviderAuth\n /** Follows each MCP sign-in, so the MCP servers page shows it. */\n mcpStatus: McpStatusTracker\n isConnected: (peer: HostPeer) => boolean\n /** This host serves {@link SERVER_OAUTH_CALLBACK_PATH} (a zidane-server): a browser client's MCP sign-in may redirect there. */\n serverCallback?: boolean\n ttlMs?: number\n}): {\n methods: Handlers<'auth.oauth.begin' | 'auth.oauth.complete' | 'auth.oauth.respond' | 'auth.oauth.cancel'>\n releasePeer: (peer: HostPeer) => void\n /** The browser came back to the server's callback: hands the code to the flow its `state` names. The MCP server it signs in to; `undefined`: no such flow waits. */\n deliverCallback: (query: URLSearchParams) => string | undefined\n} {\n const flows = new Map<string, Flow>()\n\n const end = (flow: Flow, reason: string): void => {\n clearTimeout(flow.timer)\n flows.delete(flow.id)\n if (!flow.abort.signal.aborted)\n flow.abort.abort(new Error(reason))\n }\n\n /** Register a flow whose login is already running; it ends at expiry, on cancel, or once settled and collected. */\n function register(peer: HostPeer, parts: { abort: AbortController, deliver: Flow['deliver'], result: Promise<HostOAuthComplete>, expectedState?: string, redirectUri?: string, held?: string, steps?: StepChannel, started?: Flow['started'] }): Flow {\n const id = randomBytes(24).toString('base64url')\n const flow: Flow = {\n id,\n peer,\n expiresAt: Date.now() + ttlMs,\n delivered: false,\n ...parts,\n timer: undefined as unknown as ReturnType<typeof setTimeout>,\n }\n flow.timer = setTimeout(end, ttlMs, flow, 'The sign-in expired.')\n flow.timer.unref?.()\n // Nobody may be waiting on it (expired, abandoned): never an unhandled rejection.\n flow.result.catch(() => undefined)\n flows.set(id, flow)\n return flow\n }\n\n const ownFlows = (peer: HostPeer): Flow[] => [...flows.values()].filter(flow => flow.peer === peer)\n /** MCP begins in flight per connection: counted against the cap before their flow registers. */\n const startingMcp = new Map<HostPeer, number>()\n\n async function beginProvider(peer: HostPeer, provider: unknown): Promise<HostOAuthBegin> {\n const { login, ...parts } = startProviderLogin(auth, provider)\n const flow = register(peer, parts)\n try {\n return await stateOf(flow, login)\n }\n catch (err) {\n end(flow, 'The sign-in did not start.')\n throw err\n }\n }\n\n /** The flow's URL, or the question it waits on first; its `state` and redirect recorded once the URL is known. */\n async function stateOf(flow: Flow, login: Promise<unknown>): Promise<HostOAuthBegin> {\n const steps = flow.steps!\n const next = await firstOf<{ step: HostOAuthStep } | { begin: Omit<HostOAuthBegin, 'flowId' | 'expiresAt'> }>(\n Promise.race([flow.started!.then(begin => ({ begin })), steps.next().then(step => ({ step }))]),\n login,\n flow.abort.signal,\n )\n if ('step' in next)\n return { flowId: flow.id, url: '', mode: 'step', step: next.step, expiresAt: flow.expiresAt }\n const begin = next.begin\n flow.begun = begin\n if (begin.mode !== 'device') {\n const authorize = new URL(begin.url)\n flow.expectedState = authorize.searchParams.get('state') ?? undefined\n if (begin.redirectUri)\n flow.redirectUri = begin.redirectUri\n }\n return { flowId: flow.id, ...begin, expiresAt: flow.expiresAt }\n }\n\n async function beginMcp(peer: HostPeer, p: { mcpServer: string, cwd?: string, kind?: string, redirectUri?: string }): Promise<HostOAuthBegin> {\n const asked = mcpRedirect(p.redirectUri, serverCallback)\n const dir = catalogFolder({ env, host }, p.cwd, p.kind)\n const config = await env.runtimeConfig(dir)\n const settings = env.readSettings()\n const { servers } = discoverProjectMcps({ cwd: dir, prefix: config.prefix, foreignAgents: settings.importForeignConfigs === true, ruler: settings.importRulerConfigs !== false })\n const entry: McpServerConfig | undefined = servers.find(server => server.config.name === p.mcpServer)?.config\n if (!entry)\n throw new Error(`No MCP server \"${p.mcpServer}\" in that folder's catalog.`)\n // A pre-registered client's redirect is the one registered with the\n // provider; the client rebinds its listener to it (`redirectUri` below),\n // or a browser client has the user paste it.\n const redirectUri = pinnedMcpRedirectUri(entry) ?? asked.uri\n const held = redirectUri === asked.uri && asked.held ? entry.name : undefined\n const abort = new AbortController()\n const state = randomBytes(24).toString('base64url')\n const callbackCode = deferred<{ code: string, state?: string }>()\n const started = deferred<{ url: string }>()\n const login = loginMcpServer(entry, {\n store: env.mcpCredentialStore?.() ?? createFileMcpCredentialStore(env.userDataDir()),\n signal: abort.signal,\n state,\n timeoutMs: ttlMs,\n // The client's loopback; the code comes back through `complete`.\n callback: { redirectUri, promise: callbackCode.promise, close: async () => undefined },\n onAuthorizationUrl: url => started.resolve({ url: url.toString() }),\n })\n login.catch(() => undefined)\n const first = await firstOf(started.promise, login, abort.signal).catch((err) => {\n abort.abort()\n throw err\n })\n const result = login.then(() => {\n void host.rebuildAllAgents({ rediscover: true }).catch(() => undefined)\n return { mcpServer: entry.name }\n })\n void mcpStatus.signingIn(entry.name, login, abort.signal)\n const flow = register(peer, {\n abort,\n result,\n expectedState: state,\n redirectUri,\n ...(held ? { held } : {}),\n deliver: (delivery) => {\n if ('input' in delivery) {\n const code = codeIn(delivery.input)\n const pastedState = stateIn(delivery.input)\n if (code)\n callbackCode.resolve({ code, ...(pastedState !== undefined ? { state: pastedState } : {}) })\n return\n }\n callbackCode.resolve(delivery)\n },\n })\n return { flowId: flow.id, url: first.url, ...(held ? { mode: 'browser' } : { mode: 'loopback', redirectUri }), expiresAt: flow.expiresAt }\n }\n\n return {\n methods: {\n 'auth.oauth.begin': async (p, peer) => {\n const target = [p.provider, p.mcpServer].filter(value => value !== undefined)\n if (target.length !== 1 || typeof target[0] !== 'string' || target[0] === '')\n throw new InvalidParamsError('auth.oauth.begin needs exactly one of \"provider\" or \"mcpServer\".')\n if (ownFlows(peer).length + (startingMcp.get(peer) ?? 0) >= MAX_FLOWS_PER_PEER)\n throw new Error(`This connection already has ${MAX_FLOWS_PER_PEER} sign-ins open: finish or cancel one first.`)\n let begun: HostOAuthBegin\n if (p.provider !== undefined) {\n begun = await beginProvider(peer, p.provider)\n }\n else {\n // An MCP flow registers only once its URL is known; hold its slot meanwhile.\n startingMcp.set(peer, (startingMcp.get(peer) ?? 0) + 1)\n try {\n begun = await beginMcp(peer, { mcpServer: p.mcpServer!, ...(p.cwd !== undefined ? { cwd: p.cwd } : {}), ...(p.kind !== undefined ? { kind: p.kind } : {}), ...(p.redirectUri !== undefined ? { redirectUri: p.redirectUri } : {}) })\n }\n finally {\n const left = (startingMcp.get(peer) ?? 1) - 1\n if (left > 0)\n startingMcp.set(peer, left)\n else\n startingMcp.delete(peer)\n }\n }\n // Dropped while it started: nobody will finish it.\n if (!isConnected(peer)) {\n const flow = flows.get(begun.flowId)\n if (flow)\n end(flow, 'The connection closed.')\n }\n return begun\n },\n\n 'auth.oauth.complete': async (p, peer) => {\n const flow = flowOf(flows, p.flowId, peer)\n deliverCode(flow, p, end)\n let asking = false\n try {\n // The login may ask something first: the client answers (`respond`), then calls again.\n const outcome = await (flow.steps\n ? Promise.race([flow.result, flow.steps.next().then(step => ({ step }))])\n : flow.result)\n asking = outcome.step !== undefined\n return outcome\n }\n catch (err) {\n throw new Error(flow.abort.signal.aborted && flow.abort.signal.reason instanceof Error ? flow.abort.signal.reason.message : err instanceof Error ? err.message : String(err))\n }\n finally {\n if (!asking)\n end(flow, 'The sign-in finished.')\n }\n },\n\n 'auth.oauth.respond': async (p, peer) => {\n const flow = flowOf(flows, p.flowId, peer)\n if (!flow.steps || typeof p.stepId !== 'string')\n throw new InvalidParamsError('auth.oauth.respond needs the flow\\'s \"stepId\".')\n if (p.value !== undefined && typeof p.value !== 'string')\n throw new InvalidParamsError('\"value\" must be a string.')\n const cancelled = p.value === undefined && flow.steps.pending()?.kind === 'select'\n flow.steps.answer(p.stepId, p.value)\n if (cancelled) {\n end(flow, 'The sign-in was cancelled.')\n throw new Error('The sign-in was cancelled (no choice made).')\n }\n // After the URL: where it stands (`complete` again waits for the rest).\n return flow.begun ? { flowId: flow.id, ...flow.begun, expiresAt: flow.expiresAt } : stateOf(flow, flow.result)\n },\n\n 'auth.oauth.cancel': (p, peer) => {\n const flow = typeof p.flowId === 'string' ? flows.get(p.flowId) : undefined\n if (!flow || flow.peer !== peer)\n return { cancelled: false }\n end(flow, 'The sign-in was cancelled.')\n return { cancelled: true }\n },\n },\n releasePeer(peer) {\n for (const flow of ownFlows(peer))\n end(flow, 'The connection closed.')\n },\n deliverCallback: query => deliverCallback(flows, query, end),\n }\n}\n","/**\n * What the setup wizard reads on the host's machine for a client: what it\n * finds there (`onboarding.detect`: credentials, other agents, local model\n * servers), the providers Connect lists with their custom fields and default\n * model (`onboarding.providers`), a Claude Code setup and its import\n * (`claudeImport.*`; the import copies commands the host will run, so it\n * goes through the install gate, `guardedInstall`) and a skill source's\n * skills (`skills.browse`).\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostSignal } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { RemoteInstallsOptions } from './catalog-install'\nimport type { Handlers } from './types'\nimport { detectAuth } from '../../../chat/auth'\nimport { countClaudeSessionFiles, hasClaudeCodeSetup, importFromClaudeCode, previewClaudeImport } from '../../../chat/claude-import'\nimport { connectorGithubToken, detectOnboardingEnvironment, onboardingProviders } from '../../../chat/host/onboarding/index'\nimport { browseSkillSource } from '../../../skills/browse'\nimport { guardedInstall } from './catalog-install'\nimport { catalogFolder } from './catalogs'\nimport { InvalidParamsError } from './params'\n\ntype OnboardingMethod = 'onboarding.detect' | 'onboarding.providers' | 'claudeImport.detect' | 'claudeImport.preview' | 'claudeImport.run' | 'skills.browse'\n\n/** Longest source spec browsed. */\nconst MAX_SOURCE_LENGTH = 500\n\nexport function createOnboardingHandlers({ host, env, broadcast, installs }: {\n host: Pick<ChatHost, 'resolveFolder' | 'rebuildAllAgents'>\n env: DaemonEnvironment\n broadcast: (signal: HostSignal) => void\n /** A zidane-server's `allowRemoteInstalls` and audit (`./catalog-install`). Absent: the import is refused. */\n installs?: RemoteInstallsOptions\n}): Handlers<OnboardingMethod> {\n const folderOf = (cwd: unknown): string => catalogFolder({ env, host }, cwd)\n /** The providers of `folder`, extension ones included. */\n const registryOf = async (folder: string) => (await env.runtimeConfig(folder)).providers\n const hasSessions = async (): Promise<boolean> => {\n try {\n return (await env.store.list({ limit: 1 })).length > 0\n }\n catch {\n // An unreadable store: the other signals decide.\n return false\n }\n }\n\n return {\n 'onboarding.detect': async (p) => {\n const cwd = folderOf(p.cwd)\n return detectOnboardingEnvironment({\n dataDir: env.userDataDir(),\n registry: await registryOf(cwd),\n state: env.config.stateStore.load(),\n sessions: await hasSessions(),\n // A browser's first visit says nothing about this machine.\n surfaceFirstRun: false,\n cwd,\n })\n },\n 'onboarding.providers': async (p) => {\n const registry = await registryOf(folderOf(p.cwd))\n return onboardingProviders(registry, detectAuth(env.userDataDir(), registry)).map((provider) => {\n const defaultModel = registry[provider.key]?.defaultModel\n return defaultModel ? { ...provider, defaultModel } : provider\n })\n },\n 'claudeImport.detect': (p) => {\n if (!hasClaudeCodeSetup())\n return { available: false, counts: { project: 0, all: 0 } }\n return { available: true, counts: countClaudeSessionFiles({ cwd: folderOf(p.cwd) }) }\n },\n 'claudeImport.preview': p => previewClaudeImport({ cwd: folderOf(p.cwd), prefix: env.config.prefix }),\n 'claudeImport.run': (p, peer) => guardedInstall(installs, peer, 'claudeImport.run', { sessions: p.sessions === true, mcps: p.mcps === true, skills: p.skills === true, commands: p.commands === true }, async () => {\n const commands = p.commands === true\n const summary = await importFromClaudeCode(env.store, {\n cwd: folderOf(p.cwd),\n prefix: env.config.prefix,\n sessions: p.sessions === true,\n mcps: p.mcps === true,\n skills: p.skills === true,\n commands,\n agents: typeof p.agents === 'boolean' ? p.agents : commands,\n allProjects: p.allProjects === true,\n })\n // MCP servers, skills and subagents are read when an agent is built.\n if (summary.mcps || summary.skills || summary.agents)\n void host.rebuildAllAgents({ rediscover: true }).catch(() => undefined)\n if (summary.mcps)\n broadcast({ kind: 'catalog:changed', catalog: 'mcps' })\n if (summary.skills)\n broadcast({ kind: 'catalog:changed', catalog: 'skills' })\n return summary\n }),\n // The GitHub login raises GitHub's limit from 60 to 5,000 calls an hour.\n 'skills.browse': async (p) => {\n if (typeof p.source !== 'string' || p.source.trim() === '' || p.source.length > MAX_SOURCE_LENGTH)\n throw new InvalidParamsError(`source must be a non-empty string of at most ${MAX_SOURCE_LENGTH} characters.`)\n const token = (await connectorGithubToken())?.token\n return browseSkillSource(p.source, token ? { token } : {})\n },\n }\n}\n","/** The main session driving worker sessions. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { Handlers } from './types'\n\ntype OrchestrationMethod\n = | 'orchestration.main' | 'orchestration.createWorker' | 'orchestration.list' | 'orchestration.read'\n | 'orchestration.send' | 'orchestration.steer' | 'orchestration.cancel' | 'orchestration.transcript'\n\nexport function createOrchestrationHandlers({ host }: { host: ChatHost }): Handlers<OrchestrationMethod> {\n return {\n 'orchestration.main': () => host.orchestration.ensureMain(),\n 'orchestration.createWorker': ({ mainId, ...params }) => host.orchestration.createWorker(mainId, params),\n 'orchestration.list': p => host.orchestration.list(p.mainId, p.limit),\n 'orchestration.read': async p =>\n (await host.orchestration.canOrchestrate(p.mainId, p.sessionId)) ? host.orchestration.read(p.sessionId) : null,\n 'orchestration.send': p => host.orchestration.send(p.mainId, p.sessionId, p.prompt, p.wake),\n 'orchestration.steer': p => host.orchestration.steer(p.mainId, p.sessionId, p.message),\n 'orchestration.cancel': p => host.orchestration.cancel(p.mainId, p.sessionId),\n 'orchestration.transcript': p => host.orchestration.transcript(p.mainId, p.sessionId, p.limit),\n }\n}\n","import type { ChatHost } from '../../../chat/host/engine'\n/**\n * Extension side panels and command palette items for a client's app\n * (`panels.*`, `palette.*`): run here (`../../../extensions/panel-host`),\n * answered as data. A panel runs in a read-only scope of its folder's\n * project and the session it shows beside (that session's artifacts, the\n * project's). Live updates go to the connections watching: `panel:changed`,\n * `palette:changed`, one subscription per panel or folder however many\n * watch it; a dropped connection releases its own.\n */\nimport type { PanelHostDeps } from '../../../extensions/panel-host'\nimport type { SessionStore } from '../../../session/index'\nimport type { DaemonEnvironment } from '../environment'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { isPaletteContext } from '../../../chat/palette'\nimport { projectRootOf } from '../../../chat/project-root'\nimport { listExtensionPaletteItems, loadExtensionPanel, panelSummaries, runExtensionPaletteItem, runExtensionPanelAction, subscribeExtensionPalette, subscribeExtensionPanel } from '../../../extensions/panel-host'\nimport { createSharedWatches } from '../../../extensions/shared-watches'\nimport { catalogFolder } from './catalogs'\nimport { InvalidParamsError, requiredString } from './params'\n\ntype PanelMethod\n = | 'panels.list' | 'panels.load' | 'panels.action' | 'panels.watch' | 'panels.unwatch'\n | 'palette.list' | 'palette.run' | 'palette.watch' | 'palette.unwatch'\n\nexport function createPanelHandlers({ host, env, store, onClose }: {\n host: Pick<ChatHost, 'resolveFolder'>\n env: DaemonEnvironment\n store: Pick<SessionStore, 'listArtifacts'>\n onClose: (release: (peer: HostPeer) => void) => void\n}): Handlers<PanelMethod> {\n const folderOf = (cwd: unknown): string => catalogFolder({ env, host }, requiredString(cwd, 'cwd'))\n const registryOf = async (folder: string) => (await env.runtimeConfig(folder)).extensions\n const panelOf = async (folder: string, panelId: unknown) => (await registryOf(folder)).panels.find(p => p.id === panelId)\n const deps: PanelHostDeps = {\n ...(env.hostRuntime ? { hostRuntime: env.hostRuntime } : {}),\n listArtifacts: async query => (await store.listArtifacts?.(query)) ?? [],\n artifactsEnabled: () => env.readSettings().artifacts !== false,\n projectRootOf,\n }\n const paletteContext = (ctx: unknown) => {\n if (!isPaletteContext(ctx))\n throw new InvalidParamsError('ctx must be a palette context.')\n return ctx\n }\n\n // Keyed by the folder as each client names it: the signals carry that name back.\n const panelWatches = createSharedWatches<HostPeer>()\n const paletteWatches = createSharedWatches<HostPeer>()\n onClose((peer) => {\n panelWatches.release(peer)\n paletteWatches.release(peer)\n })\n const panelKey = (cwd: string, panelId: string): string => `${cwd}\\u0000${panelId}`\n\n return {\n 'panels.list': async p => panelSummaries((await registryOf(folderOf(p.cwd))).panels),\n 'panels.load': async (p) => {\n const folder = folderOf(p.cwd)\n return loadExtensionPanel(await panelOf(folder, p.panelId), p.ctx, folder, deps)\n },\n 'panels.action': async (p) => {\n const folder = folderOf(p.cwd)\n return runExtensionPanelAction(await panelOf(folder, p.panelId), requiredString(p.actionId, 'actionId'), p.payload, p.ctx, folder, deps)\n },\n 'panels.watch': (p, peer) => {\n const folder = folderOf(p.cwd)\n const panelId = requiredString(p.panelId, 'panelId')\n const key = panelKey(p.cwd, panelId)\n return panelWatches.watch(key, peer, async () => subscribeExtensionPanel(await panelOf(folder, panelId), () => {\n for (const watcher of panelWatches.owners(key))\n watcher.send({ kind: 'panel:changed', cwd: p.cwd, panelId })\n }))\n },\n 'panels.unwatch': (p, peer) => {\n panelWatches.unwatch(panelKey(requiredString(p.cwd, 'cwd'), requiredString(p.panelId, 'panelId')), peer)\n },\n\n 'palette.list': async (p) => {\n const folder = folderOf(p.cwd)\n return listExtensionPaletteItems((await registryOf(folder)).palette, folder, paletteContext(p.ctx))\n },\n 'palette.run': async (p) => {\n const folder = folderOf(p.cwd)\n return runExtensionPaletteItem((await registryOf(folder)).palette, requiredString(p.source, 'source'), requiredString(p.itemId, 'itemId'), folder, paletteContext(p.ctx))\n },\n 'palette.watch': (p, peer) => {\n const folder = folderOf(p.cwd)\n return paletteWatches.watch(p.cwd, peer, async () => subscribeExtensionPalette((await registryOf(folder)).palette, () => {\n for (const watcher of paletteWatches.owners(p.cwd))\n watcher.send({ kind: 'palette:changed', cwd: p.cwd })\n }))\n },\n 'palette.unwatch': (p, peer) => {\n paletteWatches.unwatch(requiredString(p.cwd, 'cwd'), peer)\n },\n }\n}\n","/**\n * The host's own performance, for a client's Settings › Performance on it:\n * the samples held (`perf.history`), each new one to the connections\n * watching (`perf.watch`, `perf:sample`), and the OS threads of a process\n * it lists (`perf.threads`). The monitor (`src/perf/host.ts`) is made on\n * the first call and samples only while a connection watches; a dropped\n * connection releases its watches, and the host's shutdown stops them all.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostPerf } from '../../../perf/host'\nimport type { SessionStore } from '../../../session'\nimport type { HostKind } from '../../protocol'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { createSharedWatches } from '../../../extensions/shared-watches'\nimport { createHostPerf } from '../../../perf/host'\nimport { InvalidParamsError } from './params'\n\n/** The host process's row in its samples. */\nconst LABEL: Record<HostKind, string> = { 'server': 'Server', 'daemon': 'Daemon', 'in-process': 'Host' }\n\n/**\n * This host's monitor, made on the first call: its process labelled by its\n * kind, its sessions' MCP processes, its sessions' titles from its store.\n *\n * @param host - The host: its kind, engine and store.\n * @param host.kind - What it reports itself as (`ipc.hello`'s `hostKind`).\n * @param host.host - Its engine (the MCP server processes).\n * @param host.store - Its session store (the titles).\n */\nexport function lazyHostPerf({ kind, host, store }: { kind: HostKind, host: Pick<ChatHost, 'mcpServers'>, store: Pick<SessionStore, 'getMeta'> }): () => HostPerf {\n let monitor: HostPerf | null = null\n return () => monitor ??= createHostPerf({\n label: LABEL[kind],\n mcpInstances: () => host.mcpServers.instances(),\n sessionTitle: async (sessionId) => {\n const title = (await store.getMeta?.(sessionId))?.metadata.title\n return typeof title === 'string' && title.trim() ? title : undefined\n },\n })\n}\n\nexport function createPerfHandlers({ perf, onPeerClose, onShutdown }: {\n /** The host's monitor (made once, on first use). */\n perf: () => HostPerf\n /** Registers what to release when a connection drops (its watches). */\n onPeerClose: (release: (peer: HostPeer) => void) => void\n /** Registers what to stop when the host shuts down. */\n onShutdown: (stop: () => void) => void\n}): Handlers<'perf.watch' | 'perf.unwatch' | 'perf.history' | 'perf.threads'> {\n const watchers = createSharedWatches<HostPeer>()\n onPeerClose(peer => watchers.release(peer))\n onShutdown(() => watchers.reset())\n return {\n 'perf.watch': (_p, peer) => watchers.watch('perf', peer, async () => perf().watch((sample) => {\n for (const watcher of watchers.owners('perf'))\n watcher.send({ kind: 'perf:sample', sample })\n })),\n 'perf.unwatch': (_p, peer) => {\n watchers.unwatch('perf', peer)\n },\n 'perf.history': () => ({ samples: perf().history() }),\n 'perf.threads': async (p) => {\n if (!Number.isInteger(p?.pid) || p.pid <= 0)\n throw new InvalidParamsError('perf.threads: \"pid\" must be a process id.')\n return { threads: await perf().threads(p.pid) }\n },\n }\n}\n","/**\n * The integrations the host's clients registered (`integrations.*`): each one\n * belongs to the peer that registered it and goes away when that peer\n * disconnects. State only; the methods and the signal live in\n * `./handlers/integrations`, as presence's do next to `./peers`.\n */\nimport type { IntegrationInfo, IntegrationState } from '../../chat/integrations'\nimport type { HostPeer } from './peers'\n\n/** Integrations one connection may hold at once. */\nexport const MAX_INTEGRATIONS_PER_PEER = 32\n\n/** What a client registers: an {@link IntegrationInfo} without its `since`. */\nexport interface IntegrationEntry {\n name: string\n kind: string\n state: IntegrationState\n detail?: string\n}\n\nexport interface IntegrationRegistry {\n /**\n * Add `peer`'s integration, or replace the one it registered under that name.\n * @returns Whether the list changed.\n * @throws {Error} When another peer registered the name, or `peer` already holds {@link MAX_INTEGRATIONS_PER_PEER} others.\n */\n register: (peer: HostPeer, entry: IntegrationEntry) => boolean\n /**\n * Set the state and detail of `peer`'s integration (an absent detail clears it).\n * @returns Whether the list changed.\n * @throws {Error} When `peer` registered no integration under that name.\n */\n update: (peer: HostPeer, entry: Omit<IntegrationEntry, 'kind'>) => boolean\n /** Every integration, in registration order. */\n list: () => IntegrationInfo[]\n /**\n * Drop every integration `peer` registered.\n * @returns Whether the list changed.\n */\n release: (peer: HostPeer) => boolean\n}\n\n/**\n * @param now - The clock `since` reads (epoch ms).\n */\nexport function createIntegrationRegistry(now: () => number = Date.now): IntegrationRegistry {\n const entries = new Map<string, { owner: HostPeer, info: IntegrationInfo }>()\n\n /** Store `entry` for `owner`; `since` moves only when the state does. */\n function put(owner: HostPeer, entry: IntegrationEntry): boolean {\n const previous = entries.get(entry.name)?.info\n const info: IntegrationInfo = {\n name: entry.name,\n kind: entry.kind,\n state: entry.state,\n ...(entry.detail !== undefined ? { detail: entry.detail } : {}),\n since: previous && previous.state === entry.state ? previous.since : now(),\n }\n entries.set(entry.name, { owner, info })\n return !previous || previous.kind !== info.kind || previous.state !== info.state || previous.detail !== info.detail\n }\n\n return {\n register(peer, entry) {\n const existing = entries.get(entry.name)\n if (existing && existing.owner !== peer)\n throw new Error(`Integration \"${entry.name}\" is registered by another connection.`)\n if (!existing && [...entries.values()].filter(e => e.owner === peer).length >= MAX_INTEGRATIONS_PER_PEER)\n throw new Error(`This connection already registered ${MAX_INTEGRATIONS_PER_PEER} integrations, the most one may.`)\n return put(peer, entry)\n },\n update(peer, entry) {\n const existing = entries.get(entry.name)\n if (!existing || existing.owner !== peer)\n throw new Error(`Integration \"${entry.name}\" is not registered by this connection.`)\n return put(peer, { ...entry, kind: existing.info.kind })\n },\n list: () => [...entries.values()].map(entry => ({ ...entry.info })),\n release(peer) {\n let changed = false\n for (const [name, entry] of entries) {\n if (entry.owner === peer) {\n entries.delete(name)\n changed = true\n }\n }\n return changed\n },\n }\n}\n","/** Integrations the host's clients run (a channel), as they report them, and the signal that follows each change. */\nimport type { IntegrationState } from '../../../chat/integrations'\nimport type { HostSignal } from '../../protocol'\nimport type { IntegrationRegistry } from '../integrations'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { CHANNEL_KIND_PREFIX, hasControlCharacters, INTEGRATION_STATES, isIntegrationState } from '../../../chat/integrations'\nimport { scopeAllows } from '../../scopes'\nimport { createIntegrationRegistry } from '../integrations'\nimport { InvalidParamsError } from './params'\nimport { PolicyScopeError } from './session-policy'\n\n/** Longest `name` and `kind`. */\nconst MAX_NAME_LENGTH = 200\n/** Longest `detail`. */\nconst MAX_DETAIL_LENGTH = 2000\n\nfunction boundedString(value: unknown, name: string, max: number): string {\n if (typeof value !== 'string' || value.length === 0 || value.length > max)\n throw new InvalidParamsError(`${name} must be a non-empty string of at most ${max} characters.`)\n return printable(value, name)\n}\n\n/** `value`, refused when it holds a control character (`channels status` and windows print it). */\nfunction printable(value: string, name: string): string {\n if (hasControlCharacters(value))\n throw new InvalidParamsError(`${name} must not contain control characters.`)\n return value\n}\n\n/** `kind`, refused when it claims to be a channel and the connection's token can't approve (a local connection can). */\nfunction kindFor(peer: HostPeer, kind: string): string {\n if (kind.startsWith(CHANNEL_KIND_PREFIX) && peer.grant && !scopeAllows(peer.grant, 'approve'))\n throw new PolicyScopeError('integrations.register', `with kind \"${CHANNEL_KIND_PREFIX}…\"`, peer.grant)\n return kind\n}\n\nfunction stateOf(value: unknown): IntegrationState {\n if (!isIntegrationState(value))\n throw new InvalidParamsError(`state must be one of ${INTEGRATION_STATES.join(', ')}.`)\n return value\n}\n\nfunction detailOf(value: unknown): { detail?: string } {\n if (value === undefined)\n return {}\n if (typeof value !== 'string' || value.length > MAX_DETAIL_LENGTH)\n throw new InvalidParamsError(`detail must be a string of at most ${MAX_DETAIL_LENGTH} characters.`)\n return { detail: printable(value, 'detail') }\n}\n\nexport function createIntegrationHandlers({ broadcast, onClose, registry = createIntegrationRegistry() }: {\n broadcast: (signal: HostSignal) => void\n /** Registers the peer-close cleanup (`PeerRegistry.onClose`). */\n onClose: (cleanup: (peer: HostPeer) => void) => void\n registry?: IntegrationRegistry\n}): Handlers<'integrations.register' | 'integrations.update' | 'integrations.list'> {\n const changed = (didChange: boolean): void => {\n if (didChange)\n broadcast({ kind: 'integrations:changed', integrations: registry.list() })\n }\n onClose(peer => changed(registry.release(peer)))\n\n return {\n 'integrations.register': (p, peer) => {\n changed(registry.register(peer, {\n name: boundedString(p?.name, 'name', MAX_NAME_LENGTH),\n kind: kindFor(peer, boundedString(p?.kind, 'kind', MAX_NAME_LENGTH)),\n state: stateOf(p?.state),\n ...detailOf(p?.detail),\n }))\n },\n 'integrations.update': (p, peer) => {\n changed(registry.update(peer, {\n name: boundedString(p?.name, 'name', MAX_NAME_LENGTH),\n state: stateOf(p?.state),\n ...detailOf(p?.detail),\n }))\n },\n 'integrations.list': () => registry.list(),\n }\n}\n","/**\n * Who is connected: which sessions have windows attached, which one this\n * window watches, and the integrations (channels and other non-window\n * clients) that registered themselves.\n */\nimport type { DaemonEnvironment } from '../environment'\nimport type { PeerRegistry } from '../peers'\nimport type { Handlers } from './types'\nimport { createIntegrationHandlers } from './integrations'\n\nexport function createPresenceHandlers({ env, peers }: {\n env: DaemonEnvironment\n peers: Pick<PeerRegistry, 'computePresence' | 'broadcastPresence' | 'broadcast' | 'onClose'>\n}): Handlers<'presence.list' | 'presence.watch' | 'integrations.register' | 'integrations.update' | 'integrations.list'> {\n return {\n ...createIntegrationHandlers({ broadcast: peers.broadcast, onClose: peers.onClose }),\n 'presence.list': () => peers.computePresence(),\n 'presence.watch': (p, peer) => {\n peer.watching = p.sessionId\n peers.broadcastPresence()\n // Warm the per-cwd runtime config off the keystroke path: the first\n // suggest.resolve on a cold cwd would otherwise pay full extension\n // discovery inside the typist's wait (the 150ms provider deadline\n // starts only AFTER the registry exists). Fire-and-forget; the\n // 16-entry LRU keeps recently watched cwds hot.\n void env.store.load(p.sessionId).then((data) => {\n if (!data)\n return\n const meta = data.metadata ?? {}\n const cwd = typeof meta.cwd === 'string' ? meta.cwd : (data.projectRoot ?? '')\n return env.runtimeConfig(cwd)\n }).catch(() => undefined)\n },\n }\n}\n","/** The host-owned type-ahead queue every window shares. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostPeer } from '../peers'\nimport type { SendDedup } from '../send-requests'\nimport type { Handlers } from './types'\nimport { deduped } from '../send-requests'\nimport { promptFields } from './chat'\nimport { boundAttachments } from './drafts'\nimport { InvalidParamsError } from './params'\n\nexport function createQueueHandlers({ host, clearDraft, dedup }: {\n host: ChatHost\n clearDraft: (sessionId: string, origin: HostPeer | null) => void\n /** Answers a retried `requestId` with its first outcome (`../send-requests`). Absent: `requestId` is ignored. */\n dedup?: SendDedup\n}): Handlers<'queue.list' | 'queue.add' | 'queue.remove' | 'queue.update' | 'queue.attachments' | 'queue.pushNow'> {\n return {\n 'queue.list': p => host.queueList(p.sessionId),\n 'queue.add': async (p, peer) => {\n // Same cheap shape guards as `drafts.set` — a malformed peer payload\n // must not propagate a non-string into every window's queue box.\n const text = typeof p.text === 'string' ? p.text.slice(0, 64 * 1024) : ''\n const activatedSkills = Array.isArray(p.activatedSkills)\n ? p.activatedSkills.filter((name): name is string => typeof name === 'string')\n : undefined\n const attachments = Array.isArray(p.attachments)\n ? boundAttachments(p.attachments)\n : undefined\n const asCommand = typeof p.asCommand === 'string' ? p.asCommand.slice(0, 128) : undefined\n const fields = promptFields(p)\n const result = await deduped(dedup, 'queue.add', p, () => host.queueAdd(p.sessionId, text, activatedSkills, attachments, asCommand, fields))\n // Queuing/sending consumed the shared draft, same as a direct send\n // (not for a prompt sent from outside the composer).\n if (p.keepDraft !== true)\n clearDraft(p.sessionId, peer)\n return result\n },\n 'queue.remove': p => host.queueRemove(p.sessionId, p.id),\n 'queue.update': p => host.queueUpdate(\n p.sessionId,\n p.id,\n typeof p.text === 'string' ? p.text.slice(0, 64 * 1024) : '',\n updatedAttachments(p.attachments),\n ),\n 'queue.attachments': p => host.queueAttachments(p.sessionId, p.id),\n 'queue.pushNow': p => host.queuePushNow(p.sessionId, p.id),\n }\n}\n\n/**\n * The list `queue.update` stores in place of an entry's attachments. An entry\n * that is malformed or over the budget is refused, not dropped: the list\n * REPLACES what is stored, so a quietly shorter list would delete the rest.\n */\nfunction updatedAttachments(list: unknown): ReturnType<typeof boundAttachments> | undefined {\n if (!Array.isArray(list))\n return undefined\n const bounded = boundAttachments(list)\n if (bounded.length !== list.length)\n throw new InvalidParamsError('attachments: an entry is malformed, or the list is over 24 MiB.')\n return bounded\n}\n","/** Reattach without a reload: replay a session's numbered signals from the host's log (`../signal-log`). */\nimport type { SignalLog } from '../signal-log'\nimport type { Handlers } from './types'\n\nexport function createResumeHandlers({ log }: { log: Pick<SignalLog, 'epoch' | 'replay'> }): Handlers<'sessions.resume'> {\n return {\n 'sessions.resume': (p) => {\n if (p.epoch !== log.epoch)\n return { ok: false, reason: 'epoch' }\n const signals = typeof p.afterSeq === 'number' ? log.replay(p.sessionId, p.afterSeq) : null\n return signals ? { ok: true, signals } : { ok: false, reason: 'gap' }\n },\n }\n}\n","/**\n * A zidane-server's log, for a client's Settings › Logs: the records its\n * bounded buffer holds (`logs.list`) and each new one to the connections\n * following it (`logs.watch`, `logs:record`). Another host has no buffer\n * and refuses both.\n */\nimport type { LogRecord, RingBufferSink } from '../../../logger'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { createSharedWatches } from '../../../extensions/shared-watches'\n\nconst NO_LOGS = 'This host keeps no log for clients (a zidane-server does).'\n\n/** A value as it can cross the wire: an error by its message, anything JSON can't hold by its text. */\nfunction wireValue(value: unknown): unknown {\n if (value instanceof Error)\n return value.message\n try {\n return JSON.parse(JSON.stringify(value) ?? 'null') as unknown\n }\n catch {\n return String(value)\n }\n}\n\n/** A record with its attributes made wire-safe (an extension may log anything). */\nfunction wireRecord(record: LogRecord): LogRecord {\n return { ...record, attrs: Object.fromEntries(Object.entries(record.attrs).map(([key, value]) => [key, wireValue(value)])) }\n}\n\nexport function createLogHandlers({ logs, onClose }: {\n logs?: RingBufferSink\n onClose: (release: (peer: HostPeer) => void) => void\n}): Handlers<'logs.list' | 'logs.watch' | 'logs.unwatch'> {\n const buffer = (): RingBufferSink => {\n if (!logs)\n throw new Error(NO_LOGS)\n return logs\n }\n const followers = createSharedWatches<HostPeer>()\n onClose(peer => followers.release(peer))\n return {\n 'logs.list': () => ({ records: buffer().getRecords().map(wireRecord) }),\n 'logs.watch': (_p, peer) => {\n const sink = buffer()\n return followers.watch('log', peer, async () => sink.subscribe(() => {\n const last = sink.getRecords().at(-1)\n if (!last)\n return\n const record = wireRecord(last)\n for (const follower of followers.owners('log'))\n follower.send({ kind: 'logs:record', record })\n }))\n },\n 'logs.unwatch': (_p, peer) => {\n followers.unwatch('log', peer)\n },\n }\n}\n","/**\n * What only a zidane-server does: manage its tokens (`tokens.*`, and\n * `tokens:changed` to every window after a change), update itself\n * (`server.update.*`) and show its log (`logs.*`, `./logs`). Another host\n * answers them with a refusal.\n */\nimport type { RingBufferSink } from '../../../logger'\nimport type { HostSignal, ServerTokenInfo, ServerTokenScope, ServerUpdateStatus } from '../../protocol'\nimport type { ClientScope } from '../../scopes'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { isValidMachineName } from '../../../chat/machine-protocol'\nimport { isClientScope } from '../../scopes'\nimport { createLogHandlers } from './logs'\nimport { InvalidParamsError } from './params'\n\nexport interface ServerUpdateControl {\n status: () => ServerUpdateStatus\n configure: (enabled: boolean) => ServerUpdateStatus\n check: () => Promise<ServerUpdateStatus>\n installNow: () => Promise<ServerUpdateStatus>\n}\n\n/** A zidane-server's token store, as its clients reach it (`src/server/server.ts` audits each call). */\nexport interface ServerTokensControl {\n createMachineToken: (name: string, by: string | undefined) => { id: string, name: string, token: string }\n list: () => ServerTokenInfo[]\n create: (name: string, scope: ServerTokenScope, by: string | undefined) => ServerTokenInfo & { token: string }\n /** `null`: no live token has that id. */\n revoke: (id: string, by: string | undefined) => ServerTokenInfo[] | null\n /** A one-time pairing code (`src/server/pairing.ts`); throws past the live-code cap. */\n pair: (scope: ClientScope, ttlMs: number | undefined, name: string | undefined, by: string | undefined) => { code: string, expiresAt: number }\n /** A one-time machine join code (`src/ipc/machine/join.ts`); throws past the live-code cap or the server's longest lifetime. */\n machineInvite: (ttlMs: number | undefined, name: string | undefined, by: string | undefined) => { code: string, expiresAt: number }\n /** Calls `listener` after the tokens changed, whoever changed them (a client, a pairing, the CLI). Returns the unsubscribe. */\n onChange: (listener: () => void) => () => void\n}\n\n/** Bounds of `tokens.pair`'s `ttlMs` (`src/server/pairing.ts`). */\nconst PAIR_TTL_MIN_MS = 30_000\nconst PAIR_TTL_MAX_MS = 60 * 60_000\n\nconst NO_UPDATER = 'This host does not update itself (a zidane-server does).'\nconst NO_TOKENS = 'This host has no tokens (only a zidane-server does).'\n\nfunction validName(method: string, name: unknown): string {\n if (typeof name !== 'string' || name.trim() === '')\n throw new InvalidParamsError(`${method}: \"name\" must be a non-empty string.`)\n return name.trim().slice(0, 100)\n}\n\nexport function createServerHandlers({ tokens, update, logs, broadcast, onClose, onPeerClose }: {\n tokens?: ServerTokensControl\n update?: () => ServerUpdateControl | null\n logs?: RingBufferSink\n broadcast: (signal: HostSignal) => void\n /** Registers what to stop when the host shuts down. */\n onClose: (stop: () => void) => void\n /** Registers what to release when a connection drops (its log follow). */\n onPeerClose: (release: (peer: HostPeer) => void) => void\n}): Handlers<'tokens.createMachineToken' | 'tokens.list' | 'tokens.create' | 'tokens.revoke' | 'tokens.revokeSelf' | 'tokens.pair' | 'tokens.machineInvite' | 'server.update.status' | 'server.update.configure' | 'server.update.check' | 'server.update.install' | 'logs.list' | 'logs.watch' | 'logs.unwatch'> {\n const updater = (): ServerUpdateControl => {\n const control = update?.()\n if (!control)\n throw new Error(NO_UPDATER)\n return control\n }\n const store = (): ServerTokensControl => {\n if (!tokens)\n throw new Error(NO_TOKENS)\n return tokens\n }\n // A token created, revoked or paired, here or by the CLI: every window's token list re-reads.\n if (tokens)\n onClose(tokens.onChange(() => broadcast({ kind: 'tokens:changed' })))\n return {\n // Counted against, and audited with, the token that asks.\n 'tokens.createMachineToken': (p, peer) => store().createMachineToken(validName('tokens.createMachineToken', p.name), peer.principal),\n 'tokens.list': () => store().list(),\n 'tokens.create': (p, peer) => {\n const name = validName('tokens.create', p.name)\n if (p.scope !== 'machine' && !isClientScope(p.scope))\n throw new InvalidParamsError('tokens.create: \"scope\" must be \"chat\", \"approve\", \"admin\" or \"machine\".')\n return store().create(name, p.scope, peer.principal)\n },\n 'tokens.revoke': (p, peer) => {\n if (typeof p.id !== 'string' || p.id === '')\n throw new InvalidParamsError('tokens.revoke: \"id\" must be a token id.')\n const revoked = store().revoke(p.id, peer.principal)\n if (!revoked)\n throw new Error(`No live token has the id \"${p.id}\".`)\n return { revoked }\n },\n 'tokens.revokeSelf': (_p, peer) => {\n if (!peer.principal)\n throw new Error('This connection has no token to revoke.')\n const revoked = store().revoke(peer.principal, peer.principal)\n if (!revoked)\n throw new Error('This connection\\'s token is no longer live.')\n return { revoked }\n },\n 'tokens.pair': (p, peer) => {\n if (!isClientScope(p.scope))\n throw new InvalidParamsError('tokens.pair: \"scope\" must be \"chat\", \"approve\" or \"admin\".')\n if (p.ttlMs !== undefined && (!Number.isInteger(p.ttlMs) || p.ttlMs < PAIR_TTL_MIN_MS || p.ttlMs > PAIR_TTL_MAX_MS))\n throw new InvalidParamsError(`tokens.pair: \"ttlMs\" must be an integer from ${PAIR_TTL_MIN_MS} to ${PAIR_TTL_MAX_MS}.`)\n if (p.name !== undefined && typeof p.name !== 'string')\n throw new InvalidParamsError('tokens.pair: \"name\" must be a string.')\n return store().pair(p.scope, p.ttlMs, p.name?.trim() || undefined, peer.principal)\n },\n 'tokens.machineInvite': (p, peer) => {\n if (p.ttlMs !== undefined && (!Number.isInteger(p.ttlMs) || p.ttlMs < PAIR_TTL_MIN_MS || p.ttlMs > PAIR_TTL_MAX_MS))\n throw new InvalidParamsError(`tokens.machineInvite: \"ttlMs\" must be an integer from ${PAIR_TTL_MIN_MS} to ${PAIR_TTL_MAX_MS}.`)\n const name = typeof p.name === 'string' ? p.name.trim() : p.name\n if (name !== undefined && (typeof name !== 'string' || (name !== '' && !isValidMachineName(name))))\n throw new InvalidParamsError('tokens.machineInvite: \"name\" must be a machine name: up to 64 letters, digits, dots, dashes or underscores.')\n return store().machineInvite(p.ttlMs, name || undefined, peer.principal)\n },\n 'server.update.status': () => updater().status(),\n 'server.update.configure': (p) => {\n if (typeof p?.enabled !== 'boolean')\n throw new InvalidParamsError('server.update.configure: \"enabled\" must be true or false.')\n return updater().configure(p.enabled)\n },\n 'server.update.check': () => updater().check(),\n 'server.update.install': () => updater().installNow(),\n ...createLogHandlers({ ...(logs ? { logs } : {}), onClose: onPeerClose }),\n }\n}\n","/**\n * Session data a client reads (and the extension state it writes) instead of\n * its own store: the list rows, one row, the whole document (or it a page of\n * turns at a time), one tool result's text, how its title came about. A window on\n * another machine (zidane-server) has no other way to see the host's\n * sessions.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { Session, SessionData, SessionStore } from '../../../session/index'\nimport type { SessionTurn } from '../../../types'\nimport type { TranscriptReplayCache } from './transcript-cache'\nimport type { Handlers } from './types'\nimport { describeTitleStatus } from '../../../chat/auto-title'\nimport { exportFilename, renderSession } from '../../../chat/session-export'\nimport { getSessionHeader, getSessionMeta, headerFromData, lastContextSizeFromTurns, listSessionMeta, runProgress, sumRunCosts, toolResultText } from '../../../chat/store'\nimport { deleteExtensionSessionState, loadSession, setExtensionSessionState } from '../../../session/index'\nimport { SESSION_TURNS_MAX_PAGE, SESSION_TURNS_PAGE } from '../../protocol'\nimport { InvalidParamsError, nonNegativeInt, sessionIdOf } from './params'\n\ntype SessionReadMethod = 'sessions.listMeta' | 'sessions.getMeta' | 'sessions.get' | 'sessions.getTurns' | 'sessions.getToolResult' | 'sessions.getHeader' | 'sessions.titleStatus' | 'sessions.setExtensionState' | 'sessions.export'\n\nfunction pageBound(value: unknown, name: string, fallback: number, max: number): number {\n return Math.min(nonNegativeInt(value, name) ?? fallback, max)\n}\n\n/**\n * The live session's document without copying it (`toJSON()` deep-clones\n * every turn). Read-only: each transport serializes the reply before the\n * session can change under it.\n */\nfunction liveView(live: Session): SessionData {\n return {\n id: live.id,\n ...(live.agentId !== undefined ? { agentId: live.agentId } : {}),\n ...(live.projectRoot !== undefined ? { projectRoot: live.projectRoot } : {}),\n turns: live.turns,\n runs: live.runs,\n status: live.status,\n metadata: live.metadata,\n createdAt: live.createdAt,\n updatedAt: live.updatedAt,\n }\n}\n\nexport function createSessionReadHandlers({ host, store, snapshots }: { host: ChatHost, store: SessionStore, snapshots: Pick<TranscriptReplayCache, 'document'> }): Handlers<SessionReadMethod> {\n /** The document as the host holds it: the live copy (ahead of the store mid-run, and holding the todos), else the stored one. */\n const documentOf = async (sessionId: string): Promise<SessionData | null> => {\n const live = host.getLiveSession(sessionId)\n if (live)\n return live.toJSON()\n // A reader: a load-time pairing heal stays in memory, the host's own\n // agent persists the document.\n const loaded = await loadSession(store, sessionId, { persistHeal: false })\n return loaded ? loaded.toJSON() : null\n }\n return {\n 'sessions.listMeta': (p) => {\n const projectRoot = p?.projectRoot\n if (projectRoot !== undefined && projectRoot !== null && typeof projectRoot !== 'string')\n throw new InvalidParamsError('projectRoot must be a string or null.')\n return listSessionMeta(store, projectRoot !== undefined ? { projectRoot } : undefined)\n },\n 'sessions.getMeta': p => getSessionMeta(store, sessionIdOf(p)),\n 'sessions.export': async (p) => {\n const sessionId = sessionIdOf(p)\n if (p.format !== 'markdown' && p.format !== 'json')\n throw new InvalidParamsError('format must be \"markdown\" or \"json\".')\n const data = await documentOf(sessionId)\n if (!data)\n throw new Error(`Session \"${sessionId}\" not found.`)\n return { filename: exportFilename(sessionId, p.format), content: renderSession(data, p.format) }\n },\n 'sessions.get': async (p) => {\n const sessionId = sessionIdOf(p)\n if (p.turns !== false)\n return documentOf(sessionId)\n // `turns: false`: the rest of the document, its turns read a page at a time\n // (`sessions.getTurns`), from the same snapshot, named by its version.\n const snapshot = await snapshots.document(store, sessionId, host.getLiveSession(sessionId))\n return snapshot && { ...snapshot.data, turns: [], version: snapshot.version }\n },\n 'sessions.getTurns': async (p) => {\n // One snapshot per content version serves every page (not a load, heal and copy per page).\n const sessionId = sessionIdOf(p)\n const snapshot = await snapshots.document(store, sessionId, host.getLiveSession(sessionId))\n if (!snapshot)\n return null\n const from = pageBound(p.from, 'from', 0, Number.MAX_SAFE_INTEGER)\n const limit = Math.max(1, pageBound(p.limit, 'limit', SESSION_TURNS_PAGE, SESSION_TURNS_MAX_PAGE))\n const { turns } = snapshot.data\n return { turns: turns.slice(from, from + limit), total: turns.length, version: snapshot.version }\n },\n 'sessions.getToolResult': async (p) => {\n const sessionId = sessionIdOf(p)\n if (typeof p.callId !== 'string' || p.callId.length === 0)\n throw new InvalidParamsError('callId must be a non-empty string.')\n // Read in place: the live turns, else the cached snapshot (no load and copy per expand).\n const live = host.getLiveSession(sessionId)\n const turns = live ? live.turns : (await snapshots.document(store, sessionId, null))?.data.turns\n if (!turns)\n return null\n const resultIn = (turn: SessionTurn): string | undefined => {\n for (const block of turn.content) {\n if (block.type === 'tool_result' && block.callId === p.callId)\n return toolResultText(block.output)\n }\n return undefined\n }\n // The named turn first, then the rest (newest first: results sit near their call).\n if (typeof p.turnId === 'string') {\n for (const turn of turns) {\n const text = turn.id === p.turnId ? resultIn(turn) : undefined\n if (text !== undefined)\n return text\n }\n }\n for (let i = turns.length - 1; i >= 0; i--) {\n const text = resultIn(turns[i]!)\n if (text !== undefined)\n return text\n }\n return null\n },\n 'sessions.titleStatus': async (p) => {\n const sessionId = sessionIdOf(p)\n const live = host.getLiveSession(sessionId)\n const header = live ? headerFromData(liveView(live)) : await getSessionHeader(store, sessionId)\n if (!header)\n throw new Error(`Session \"${sessionId}\" not found.`)\n return describeTitleStatus(header.metadata)\n },\n 'sessions.getHeader': async (p) => {\n const sessionId = sessionIdOf(p)\n const live = host.getLiveSession(sessionId)\n if (p.usage !== true)\n return live ? headerFromData(liveView(live)) : getSessionHeader(store, sessionId)\n // The footer's numbers need the turns: read here, only the numbers go out.\n const data = live ? liveView(live) : await store.load(sessionId)\n if (!data)\n return null\n const header = live ? headerFromData(data) : (await getSessionHeader(store, sessionId)) ?? headerFromData({ ...data, id: sessionId })\n // Only a run this host is running: a stored `running` run can be a dead process's.\n const run = live && host.isSessionRunning(sessionId) ? runProgress(data) : undefined\n return {\n ...header,\n contextTokens: lastContextSizeFromTurns(data.turns, data.runs),\n costUsd: sumRunCosts(data.runs),\n ...(run ? { runStartedAt: run.startedAt, runOutputTokens: run.outputTokens } : {}),\n }\n },\n 'sessions.setExtensionState': async (p) => {\n const sessionId = sessionIdOf(p)\n if (typeof p.extension !== 'string' || typeof p.key !== 'string')\n throw new InvalidParamsError('extension and key must be strings.')\n // The live copy when an agent holds the session (its save is\n // header-only, safe mid-run), else the stored one.\n const session = host.getLiveSession(sessionId) ?? await loadSession(store, sessionId, { persistHeal: false })\n if (!session)\n throw new Error(`Session \"${sessionId}\" not found.`)\n // Key checks and size bounds are the shared helpers' own.\n if (p.value === undefined)\n await deleteExtensionSessionState(session, p.extension, p.key)\n else\n await setExtensionSessionState(session, p.extension, p.key, p.value)\n },\n }\n}\n","/** Host settings and the runtime registry: read, write (rebuilding what a change requires), reload, and the setup wizard's write. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostSettings, HostSignal } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { Handlers } from './types'\nimport { settingsToWire } from '../../../chat/host-scoped-settings'\nimport { mergeOnboardingState } from '../../../chat/onboarding/result'\nimport { InvalidParamsError } from './params'\n\nconst isObject = (value: unknown): value is object => typeof value === 'object' && value !== null && !Array.isArray(value)\n\n/**\n * Settings that choose what is discovered on disk (MCP servers, skills,\n * plugins and the configs they come from): a change also re-walks the plugin\n * catalog, so a plugin installed outside the catalog shows up. Which agents\n * rebuild is decided per agent, from what its build read (`applyAgentSettings`).\n */\nconst DISCOVERY_KEYS = ['enabledMcps', 'disabledMcpTools', 'enabledSkills', 'enabledPlugins', 'importForeignConfigs', 'importRulerConfigs'] as const\n\nexport function createSettingsHandlers({ host, env, broadcast, onClose }: {\n host: ChatHost\n env: DaemonEnvironment\n broadcast: (signal: HostSignal) => void\n /** Registers what to stop when the host shuts down: the watch on the settings file. */\n onClose?: (stop: () => void) => void\n}): Handlers<'settings.get' | 'settings.set' | 'runtime.reload' | 'onboarding.complete'> {\n /*\n * The settings this host last acted on. A write through `settings.set` and a\n * change another process made to the file (two daemons, or a daemon and a\n * window in local mode, share `state.json`) are both applied against them,\n * so neither is missed.\n */\n let applied = env.readSettings()\n\n /**\n * Act on a settings change: swap the extension registry when its keys\n * changed, answer the interactions on screen when they switched to skip,\n * rebuild every agent built from a value that changed (at run end when busy,\n * no run aborted), and converge every window's settings UI.\n */\n function apply(next: HostSettings) {\n const before = applied\n applied = next\n const changed = (key: keyof HostSettings): boolean =>\n JSON.stringify(before[key]) !== JSON.stringify(next[key])\n\n /*\n * Extension toggles swap the registry: forget the runtime config first so\n * every rebuild resolves a fresh one, and dispose the old registries only\n * once no agent runs on them (as `runtime.reload`).\n */\n if (changed('enabledExtensions') || changed('loadProjectExtensions')) {\n const disposeOld = env.forgetRuntime()\n void host.rebuildAllAgents({ rediscover: true }).then(disposeOld, disposeOld)\n }\n else if (DISCOVERY_KEYS.some(changed)) {\n // Best-effort, as the extension branch: a failed rebuild must not reject unobserved.\n void host.rebuildAllAgents({ rediscover: true }).catch(() => undefined)\n }\n\n // Flipping to skip answers the modals already on screen — otherwise an\n // interaction raised under `ask` waits forever for an answer the new mode\n // says nobody will give. Resolved host-side so every window converges.\n if (changed('interactionMode') && next.interactionMode === 'skip')\n host.interactions.resolveAutomatically()\n\n // Rebuild what the change makes stale; close terminals turned off.\n host.applyAgentSettings(before, next)\n\n const wire = settingsToWire(next)\n broadcast({ kind: 'settings:changed', settings: wire })\n return wire\n }\n\n // Runs from a file watcher's timer: a throw there would be uncaught and end the host.\n const stopWatching = env.watchSettings?.(() => {\n try {\n const next = env.readSettings()\n if (JSON.stringify(next) !== JSON.stringify(applied))\n apply(next)\n }\n catch (err) {\n console.error('[ipc-daemon] applying a settings change from disk failed:', err)\n }\n })\n if (stopWatching)\n onClose?.(stopWatching)\n\n return {\n 'runtime.reload': () => {\n // Forget first so every rebuild (now for idle sessions, at run end for\n // busy ones) resolves a fresh registry; dispose the old registries only\n // once no agent runs on them. Disposing up front would tear down hooks\n // and HUD writers a busy run is still using.\n const disposeOld = env.forgetRuntime()\n void host.rebuildAllAgents().then(disposeOld, disposeOld)\n },\n\n // Every settings payload carries the legacy `safeMode` for windows older than `approvalMode`.\n 'settings.get': () => settingsToWire(env.readSettings()),\n 'settings.set': (p) => {\n const patch: unknown = p?.patch\n if (typeof patch !== 'object' || patch === null || Array.isArray(patch))\n throw new InvalidParamsError('patch must be an object of settings.')\n return apply(env.writeSettings(p.patch))\n },\n 'onboarding.complete': (p) => {\n const { set, reset } = p?.settings ?? {}\n if (!isObject(set) || !Array.isArray(reset) || reset.some(key => typeof key !== 'string'))\n throw new InvalidParamsError('settings must hold `set` (an object of settings) and `reset` (an array of keys).')\n if (!isObject(p.records))\n throw new InvalidParamsError('records must be an object.')\n const next = apply(env.writeSettings(set, reset))\n const { stateStore } = env.config\n const state = stateStore.load()\n stateStore.save({ ...state, onboarding: mergeOnboardingState(state.onboarding, p.records) })\n return next\n },\n }\n}\n","/** Inline autocomplete, resolved daemon-side and fanned out to every window on the session. */\nimport type { HostSignal } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { createPathAutocompleteProvider, resolveInlineSuggestion } from '../../../chat/inline-autocomplete'\nimport { loadOrThrow } from './session-load'\n\nexport function createSuggestHandlers({ env, broadcastExcept }: {\n env: DaemonEnvironment\n broadcastExcept: (origin: HostPeer | null, signal: HostSignal) => void\n}): {\n methods: Handlers<'suggest.resolve'>\n /** The session was deleted: abort its in-flight compute and forget its sequence. */\n forget: (sessionId: string) => void\n} {\n /**\n * Shared inline-autocomplete state — per-session latest-wins\n * coalescing for `suggest.resolve`. `seq` is the newest sequence seen\n * (stale requests return without computing); `controller` aborts an\n * in-flight compute when a newer request supersedes it (the GUI's\n * controller-map pattern, daemon-side). Entries outlive their compute\n * (the seq high-water mark), so the map is an LRU of 256 sessions:\n * refusing new keys at the cap instead would switch suggestions off for\n * every session past the 256th until the daemon restarts.\n */\n const suggests = new Map<string, { seq: number, controller: AbortController | null }>()\n\n const methods: Handlers<'suggest.resolve'> = {\n 'suggest.resolve': async (p, peer) => {\n const sessionId = String(p.sessionId)\n const seq = typeof p.seq === 'number' ? p.seq : 0\n // Same cheap shape guards + 64 KiB text cap as `drafts.set`.\n const text = typeof p.text === 'string' ? p.text.slice(0, 64 * 1024) : ''\n const caret = typeof p.caret === 'number'\n ? Math.max(0, Math.min(Math.floor(p.caret), text.length))\n : text.length\n\n const prev = suggests.get(sessionId)\n // Latest-wins: a stale seq answers immediately without computing —\n // the requester's own NEWER request (already in flight or about to\n // land) carries the authoritative result.\n if (prev && seq < prev.seq)\n return { suggestion: null, seq }\n // Supersede: abort the in-flight compute for this session, if any.\n prev?.controller?.abort()\n\n const controller = new AbortController()\n const entry = { seq, controller: controller as AbortController | null }\n suggests.delete(sessionId)\n suggests.set(sessionId, entry)\n if (suggests.size > 256) {\n const [oldest, evicted] = suggests.entries().next().value!\n evicted.controller?.abort()\n suggests.delete(oldest)\n }\n\n try {\n // Session cwd from metadata (same derivation as `toRow`) — the\n // per-cwd runtime config is the SAME registry the GUI main uses\n // locally, resolved through the existing daemon environment.\n const data = await loadOrThrow(env.store, sessionId)\n const meta = data.metadata ?? {}\n const cwd = typeof meta.cwd === 'string' ? meta.cwd : (data.projectRoot ?? '')\n const config = await env.runtimeConfig(cwd)\n // Canonical provider assembly (built-in path provider first, then\n // extension providers) and canonical deadlines —\n // `resolveInlineSuggestion` races each provider against its own\n // budget exactly as the GUI main / TUI do.\n const providers = [\n createPathAutocompleteProvider({ cwd: () => cwd }),\n ...config.extensions.inlineAutocompleteProviders,\n ]\n const result = await resolveInlineSuggestion(providers, { text, cursor: caret, cwd, signal: controller.signal })\n // Superseded mid-compute — the newer request owns the fan-out.\n if (controller.signal.aborted || suggests.get(sessionId) !== entry)\n return { suggestion: null, seq }\n // Full ordered candidate list rides along (additive field) so\n // clients keep ↑/↓ rotation; `suggestion` stays candidates[0] for\n // older clients that only read the single field.\n const candidates = result ? [...result.suffixes] : []\n const suggestion = candidates[0] ?? null\n // Fan out to every OTHER window on the session — the requester\n // already has the result from this RPC reply (drafts'\n // broadcastExcept pattern).\n broadcastExcept(peer, { kind: 'suggest:changed', sessionId, seq, basis: text, caret, suggestion, ...(candidates.length > 0 ? { candidates } : {}) })\n return { suggestion, seq, ...(candidates.length > 0 ? { candidates } : {}) }\n }\n finally {\n // Keep the seq high-water mark for stale checks; drop only the\n // controller so a finished compute can't be \"aborted\" later.\n if (suggests.get(sessionId) === entry)\n entry.controller = null\n }\n },\n }\n\n return {\n methods,\n forget: (sessionId) => {\n suggests.get(sessionId)?.controller?.abort()\n suggests.delete(sessionId)\n },\n }\n}\n","import type { EnvironmentRegistry } from '../../chat/environment'\nimport type { EnvironmentSecrets } from '../../chat/environment-settings'\n/**\n * Applying one `sync.push` category on a zidane-server (`./handlers/sync`\n * owns the record, the source check and the audit): each writes through the\n * host's own setters or the user-scope files, skipping overrides (a field\n * whose value here no longer matches what sync wrote becomes one), and\n * reports every field as applied, unchanged or skipped (with why).\n */\nimport type { SyncCategory, SyncFile, SyncPayloads, SyncPushResult } from '../../chat/sync/types'\nimport type { McpServerConfig } from '../../types'\nimport type { DaemonEnvironment } from './environment'\nimport type { ProviderAuth } from './handlers/auth'\nimport type { SyncSetters } from './handlers/sync'\nimport type { HostPeer } from './peers'\nimport type { SyncFieldRecord, SyncRecord } from './sync-store'\nimport { Buffer } from 'node:buffer'\nimport { createHash } from 'node:crypto'\nimport { accessSync, constants, existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from 'node:fs'\nimport { basename, delimiter, dirname, isAbsolute, join, relative, resolve, sep } from 'node:path'\nimport process from 'node:process'\nimport { writeFileAtomic } from '../../atomic-write'\nimport { applyEnvironmentSettingsChange, readEnvironmentSettings } from '../../chat/environment-settings'\nimport { isWindowOnlySetting } from '../../chat/host-scoped-settings'\nimport { parseMcpsFile } from '../../chat/mcps-discovery'\nimport { isMcpServerName, mcpsWritePath } from '../../chat/mcps-write'\nimport { projectUserPaths } from '../../chat/project-user-paths'\nimport { readProjects, safelistProjectKey, writeProjects } from '../../chat/safe-mode'\nimport { DEFAULT_SETTINGS } from '../../chat/settings-defaults'\nimport { hashValue, isRecord } from '../../chat/sync/hash'\nimport { isSyncableSetting, settingsFromWire } from '../../chat/sync/settings-keys'\nimport { settingField, SYNCABLE_ENVIRONMENT_KINDS, SYSTEM_MD_FIELD } from '../../chat/sync/types'\nimport { userSystemMdPath } from '../../chat/system-md'\nimport { InvalidParamsError } from './handlers/params'\n\n/** What applying a push reads and writes through. */\nexport interface SyncApplyContext {\n env: DaemonEnvironment\n setters: SyncSetters\n auth: Pick<ProviderAuth, 'descriptorOf' | 'storedKeys'>\n /** The host's environment kinds and their secret store (`environments`). */\n environments: EnvironmentRegistry\n environmentSecrets: EnvironmentSecrets\n home: () => string\n prefix: () => string\n}\n\nconst MAX_SETTINGS_BYTES = 256 * 1024\n\nconst MAX_SYSTEM_MD_BYTES = 256 * 1024\n\nconst MAX_FILE_BYTES = 1024 * 1024\n\nconst MAX_SKILL_BYTES = 4 * 1024 * 1024\n\nconst MAX_FILES_BYTES = 16 * 1024 * 1024\n\nconst MAX_SKILL_FILES = 200\n\nconst MAX_SKILLS = 500\n\nconst MAX_PATH_DEPTH = 8\n\nconst MAX_SAFELIST_ENTRIES = 1000\n\nconst MAX_ENTRY_LENGTH = 1000\n\nconst NAME_RE = /^\\w[\\w@.-]{0,99}$/\n\nconst SEGMENT_RE = /^[^/\\\\\\0]{1,255}$/\n\n/** A skill file's relative path: plain segments, no `..`, bounded depth. */\nfunction checkRelativePath(path: unknown): string | null {\n if (typeof path !== 'string' || path === '' || isAbsolute(path) || path.includes('\\\\'))\n return null\n const segments = path.split('/')\n if (segments.length > MAX_PATH_DEPTH || segments.some(s => s === '.' || s === '..' || !SEGMENT_RE.test(s)))\n return null\n return segments.join('/')\n}\n\n/** Is `command` runnable here (an absolute path, or found on PATH)? Looks, never runs. */\nfunction commandAvailable(command: string): boolean {\n const executable = (path: string): boolean => {\n try {\n accessSync(path, constants.X_OK)\n return statSync(path).isFile()\n }\n catch {\n return false\n }\n }\n if (command.includes('/'))\n return isAbsolute(command) && executable(command)\n return (process.env.PATH ?? '').split(delimiter).filter(Boolean).some(dir => executable(join(dir, command)))\n}\n\n/** A folder's files, sorted, as one hash (symlinks hashed by target, never followed). Null when absent. */\nfunction hashDir(dir: string): string | null {\n let stat\n try {\n stat = lstatSync(dir)\n }\n catch {\n return null\n }\n if (!stat.isDirectory())\n return `not-a-folder:${stat.mode}`\n const hash = createHash('sha256')\n const walk = (at: string, depth: number): void => {\n if (depth > MAX_PATH_DEPTH + 1)\n return\n for (const name of readdirSync(at).sort()) {\n const path = join(at, name)\n const rel = relative(dir, path).split(sep).join('/')\n const s = lstatSync(path)\n if (s.isDirectory()) {\n walk(path, depth + 1)\n }\n else if (s.isFile()) {\n hash.update(`f:${rel}\\0`)\n hash.update(readFileSync(path))\n hash.update('\\0')\n }\n else {\n hash.update(`o:${rel}:${s.mode}\\0`)\n }\n }\n }\n walk(dir, 0)\n return hash.digest('hex')\n}\n\n/** The hash `hashDir` gives the folder these files make. */\nfunction hashFiles(files: readonly { path: string, bytes: Buffer }[]): string {\n const hash = createHash('sha256')\n // `hashDir` walks in sorted order level by level: replay that order.\n const sorted = [...files].sort((a, b) => compareWalkOrder(a.path, b.path))\n for (const file of sorted) {\n hash.update(`f:${file.path}\\0`)\n hash.update(file.bytes)\n hash.update('\\0')\n }\n return hash.digest('hex')\n}\n\n/** The order a sorted depth-first walk visits two relative paths. */\nfunction compareWalkOrder(a: string, b: string): number {\n const as = a.split('/')\n const bs = b.split('/')\n for (let i = 0; i < Math.min(as.length, bs.length); i++) {\n if (as[i] !== bs[i]) {\n // Same level: readdir order (code units), whether file or folder.\n return as[i]! < bs[i]! ? -1 : 1\n }\n }\n return as.length - bs.length\n}\n\nfunction userSkillsRoot(ctx: SyncApplyContext): string {\n const root = projectUserPaths({ subPath: 'skills', cwd: ctx.home(), home: ctx.home(), prefix: ctx.prefix() })\n .find(p => p.source === 'user' && p.path.includes(`.${ctx.prefix().replace(/^\\./, '')}`))\n return root!.path\n}\nfunction userMcpsPath(ctx: SyncApplyContext): string {\n return mcpsWritePath('user', { home: ctx.home(), cwd: ctx.home(), prefix: ctx.prefix() })\n}\nfunction userExtensionDirs(ctx: SyncApplyContext, name: string): string[] {\n return projectUserPaths({ subPath: 'extensions', cwd: ctx.home(), home: ctx.home(), prefix: ctx.prefix() }).filter(p => p.source === 'user').map(p => join(p.path, name))\n}\n\n/** Is `field` free to write? An override (now or found by a changed value) is not. */\nfunction writable(record: SyncRecord, field: string, currentHash: string | null, result: SyncPushResult): boolean {\n if (record.overrides[field]) {\n result.skipped.push({ field, reason: 'override' })\n return false\n }\n const known = record.fields[field]\n if (known?.hash !== undefined && known.hash !== (currentHash ?? 'absent')) {\n record.overrides[field] = { at: Date.now() }\n result.skipped.push({ field, reason: 'override' })\n return false\n }\n return true\n}\n\nfunction mark(record: SyncRecord, field: string, category: SyncCategory, fields: Omit<SyncFieldRecord, 'category' | 'syncedAt'>): void {\n record.fields[field] = { category, syncedAt: Date.now(), ...fields }\n}\n\n// ---- settings ----------------------------------------------------------\nexport function pushSettings(ctx: SyncApplyContext, record: SyncRecord, payload: SyncPayloads['settings'], result: SyncPushResult): void {\n if (!isRecord(payload?.values))\n throw new InvalidParamsError('settings: payload.values must be an object.')\n if (JSON.stringify(payload.values).length > MAX_SETTINGS_BYTES)\n throw new InvalidParamsError(`settings: larger than ${MAX_SETTINGS_BYTES} bytes.`)\n const settings = ctx.env.readSettings()\n const current = settings as unknown as Record<string, unknown>\n const patch: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(settingsFromWire(payload.values, settings.approvalMode))) {\n const field = settingField(key)\n if (!Object.hasOwn(DEFAULT_SETTINGS, key)) {\n result.skipped.push({ field, reason: 'not a setting' })\n continue\n }\n if (!isSyncableSetting(key)) {\n result.skipped.push({ field, reason: isWindowOnlySetting(key) ? 'window-only setting' : 'not synced' })\n continue\n }\n const currentHash = hashValue(current[key])\n if (!writable(record, field, currentHash, result))\n continue\n if (hashValue(value) === currentHash) {\n mark(record, field, 'settings', { hash: currentHash, sent: currentHash })\n result.unchanged.push(field)\n continue\n }\n patch[key] = value\n }\n if (Object.keys(patch).length === 0)\n return\n const next = ctx.setters.setSettings(patch)\n for (const key of Object.keys(patch)) {\n mark(record, settingField(key), 'settings', { hash: hashValue(next[key]), sent: hashValue(patch[key]) })\n result.applied.push(settingField(key))\n }\n}\n\n// ---- safe-mode allowlists ----------------------------------------------\n/** The project here a client's path names: the same folder inside a workspace root, else one folder of that name in a root. */\nfunction projectHere(ctx: SyncApplyContext, clientPath: string): string | null {\n const roots = (ctx.env.workspaceRoots ?? []).map((root) => {\n try {\n return realpathSync(root)\n }\n catch {\n return null\n }\n }).filter((r): r is string => r !== null)\n const inRoot = (path: string): boolean => roots.some(root => path === root || path.startsWith(root + sep))\n const isDir = (path: string): boolean => statSync(path, { throwIfNoEntry: false })?.isDirectory() === true\n if (isAbsolute(clientPath) && isDir(clientPath)) {\n const real = realpathSync(clientPath)\n if (inRoot(real))\n return safelistProjectKey(real)\n }\n const name = basename(clientPath)\n if (!name || name === '.' || name === '..')\n return null\n const found = [...new Set(roots.map(root => join(root, name)).filter(isDir).map(path => realpathSync(path)))]\n return found.length === 1 ? safelistProjectKey(found[0]!) : null\n}\n\nexport function pushSafelists(ctx: SyncApplyContext, record: SyncRecord, payload: SyncPayloads['safelists'], result: SyncPushResult): void {\n if (!isRecord(payload?.projects))\n throw new InvalidParamsError('safelists: payload.projects must map paths to entries.')\n const dataDir = ctx.env.userDataDir()\n const file = readProjects(dataDir)\n let dirty = false\n for (const [clientPath, entries] of Object.entries(payload.projects)) {\n const field = `safelist:${clientPath}`\n if (!Array.isArray(entries) || entries.length > MAX_SAFELIST_ENTRIES || !entries.every(e => typeof e === 'string' && e.length <= MAX_ENTRY_LENGTH)) {\n result.skipped.push({ field, reason: 'invalid entries' })\n continue\n }\n const target = projectHere(ctx, clientPath)\n if (!target) {\n result.skipped.push({ field, reason: 'no project of that path or name on this server' })\n continue\n }\n // The server's own entries stay; the ones this device put there and dropped since go.\n const previous = record.fields[field]?.target === target ? (record.fields[field]?.entries ?? []) : []\n const current = file[target]?.safelist ?? []\n const next = current.filter(entry => !previous.includes(entry) || entries.includes(entry))\n for (const entry of entries) {\n if (!next.includes(entry))\n next.push(entry)\n }\n mark(record, field, 'safelists', { target, entries: [...entries] })\n if (JSON.stringify(next) === JSON.stringify(current)) {\n result.unchanged.push(field)\n continue\n }\n file[target] = { ...file[target], safelist: next }\n dirty = true\n result.applied.push(field)\n }\n if (dirty)\n writeProjects(dataDir, file)\n}\n\n// ---- SYSTEM.md and skills ----------------------------------------------\n/** A skill as checked bytes, or why it is refused. */\nfunction checkSkill(skill: unknown): { name: string, files: { path: string, bytes: Buffer }[] } | { field: string, reason: string } {\n const name = isRecord(skill) && typeof skill.name === 'string' ? skill.name : ''\n const field = `skill:${name}`\n if (!NAME_RE.test(name))\n return { field, reason: 'not a plain skill name' }\n const files = isRecord(skill) && Array.isArray(skill.files) ? skill.files as SyncFile[] : null\n if (!files || files.length === 0 || files.length > MAX_SKILL_FILES)\n return { field, reason: `needs 1 to ${MAX_SKILL_FILES} files` }\n const out: { path: string, bytes: Buffer }[] = []\n let total = 0\n for (const file of files) {\n const path = checkRelativePath(isRecord(file) ? file.path : undefined)\n if (!path)\n return { field, reason: 'a file path is not a plain relative path' }\n if (typeof file.data !== 'string')\n return { field, reason: `${path}: no data` }\n const bytes = Buffer.from(file.data, 'base64')\n if (bytes.length > MAX_FILE_BYTES)\n return { field, reason: `${path} is larger than ${MAX_FILE_BYTES} bytes` }\n total += bytes.length\n if (out.some(f => f.path === path || f.path.startsWith(`${path}/`) || path.startsWith(`${f.path}/`)))\n return { field, reason: `${path} appears twice` }\n out.push({ path, bytes })\n }\n if (total > MAX_SKILL_BYTES)\n return { field, reason: `larger than ${MAX_SKILL_BYTES} bytes` }\n return { name, files: out }\n}\n\n/** Replace `dir` with exactly these files: staged next to it, then swapped in. */\nfunction writeSkillDir(root: string, name: string, files: readonly { path: string, bytes: Buffer }[]): void {\n mkdirSync(root, { recursive: true })\n const dir = join(root, name)\n const stage = join(root, `.${name}.sync-${process.pid}-${Date.now()}`)\n mkdirSync(stage)\n try {\n for (const file of files) {\n const target = resolve(stage, file.path)\n if (!target.startsWith(stage + sep))\n throw new Error(`${file.path} is outside the skill folder.`)\n mkdirSync(dirname(target), { recursive: true })\n writeFileSync(target, file.bytes)\n }\n const backup = existsSync(dir) ? `${stage}.old` : null\n if (backup)\n renameSync(dir, backup)\n renameSync(stage, dir)\n if (backup)\n rmSync(backup, { recursive: true, force: true })\n }\n finally {\n rmSync(stage, { recursive: true, force: true })\n }\n}\n\nexport function pushFiles(ctx: SyncApplyContext, record: SyncRecord, payload: SyncPayloads['files'], result: SyncPushResult): boolean {\n if (!isRecord(payload) || !Array.isArray(payload.skills) || payload.skills.length > MAX_SKILLS || (payload.systemMd !== null && typeof payload.systemMd !== 'string'))\n throw new InvalidParamsError('files: payload must be { systemMd: string | null, skills: [...] }.')\n let touched = false\n let total = 0\n\n // SYSTEM.md (user scope).\n const mdPath = userSystemMdPath({ home: ctx.home(), prefix: ctx.prefix() })\n const currentMd = existsSync(mdPath) ? readFileSync(mdPath, 'utf8') : null\n const currentMdHash = currentMd === null ? null : hashValue(currentMd)\n if (payload.systemMd !== null && Buffer.byteLength(payload.systemMd) > MAX_SYSTEM_MD_BYTES) {\n result.skipped.push({ field: SYSTEM_MD_FIELD, reason: `larger than ${MAX_SYSTEM_MD_BYTES} bytes` })\n }\n else if (payload.systemMd !== null || record.fields[SYSTEM_MD_FIELD]) {\n if (writable(record, SYSTEM_MD_FIELD, currentMdHash, result)) {\n if (payload.systemMd === null) {\n // This computer has none any more: drop the one sync wrote.\n rmSync(mdPath, { force: true })\n delete record.fields[SYSTEM_MD_FIELD]\n result.applied.push(SYSTEM_MD_FIELD)\n touched = true\n }\n else if (hashValue(payload.systemMd) === currentMdHash) {\n mark(record, SYSTEM_MD_FIELD, 'files', { hash: currentMdHash })\n result.unchanged.push(SYSTEM_MD_FIELD)\n }\n else {\n total += Buffer.byteLength(payload.systemMd)\n writeFileAtomic(mdPath, payload.systemMd, { ensureDir: true })\n mark(record, SYSTEM_MD_FIELD, 'files', { hash: hashValue(payload.systemMd) })\n result.applied.push(SYSTEM_MD_FIELD)\n touched = true\n }\n }\n }\n\n // Skills (user scope, `~/.<prefix>/skills/<name>`).\n const root = userSkillsRoot(ctx)\n const sent = new Set<string>()\n for (const raw of payload.skills) {\n const skill = checkSkill(raw)\n if ('reason' in skill) {\n result.skipped.push(skill)\n continue\n }\n const field = `skill:${skill.name}`\n sent.add(field)\n const bytes = skill.files.reduce((n, f) => n + f.bytes.length, 0)\n if (total + bytes > MAX_FILES_BYTES) {\n result.skipped.push({ field, reason: `over the ${MAX_FILES_BYTES}-byte bound of one push` })\n continue\n }\n const dir = join(root, skill.name)\n if (existsSync(dir) && lstatSync(dir).isSymbolicLink()) {\n result.skipped.push({ field, reason: 'a link on this server, left alone' })\n continue\n }\n const currentHash = hashDir(dir)\n if (!writable(record, field, currentHash, result))\n continue\n const wanted = hashFiles(skill.files)\n if (wanted === currentHash) {\n mark(record, field, 'files', { hash: wanted })\n result.unchanged.push(field)\n continue\n }\n total += bytes\n writeSkillDir(root, skill.name, skill.files)\n mark(record, field, 'files', { hash: hashDir(dir) ?? wanted })\n result.applied.push(field)\n touched = true\n }\n // Skills this device synced and no longer has.\n for (const [field, known] of Object.entries(record.fields)) {\n if (known.category !== 'files' || !field.startsWith('skill:') || sent.has(field))\n continue\n const dir = join(root, field.slice('skill:'.length))\n if (!writable(record, field, hashDir(dir), result))\n continue\n rmSync(dir, { recursive: true, force: true })\n delete record.fields[field]\n result.applied.push(field)\n touched = true\n }\n return touched\n}\n\n// ---- MCP servers ---------------------------------------------------------\nfunction readUserMcps(ctx: SyncApplyContext): McpServerConfig[] {\n const path = userMcpsPath(ctx)\n if (!existsSync(path))\n return []\n try {\n return parseMcpsFile(readFileSync(path, 'utf8'))\n }\n catch {\n return []\n }\n}\n\nexport async function pushMcps(ctx: SyncApplyContext, record: SyncRecord, payload: SyncPayloads['mcps'], peer: HostPeer, result: SyncPushResult): Promise<void> {\n if (!isRecord(payload) || !Array.isArray(payload.servers))\n throw new InvalidParamsError('mcps: payload.servers must be a list.')\n const hashOf = (name: string): string | null => {\n const found = readUserMcps(ctx).find(s => s.name === name)\n return found ? hashValue(found) : null\n }\n const sent = new Set<string>()\n for (const config of payload.servers) {\n const name = isRecord(config) && typeof config.name === 'string' ? config.name : ''\n const field = `mcp:${name}`\n if (!isMcpServerName(name)) {\n result.skipped.push({ field, reason: 'not a plain server name' })\n continue\n }\n sent.add(field)\n const currentHash = hashOf(name)\n if (!writable(record, field, currentHash, result))\n continue\n const wanted = hashValue(config)\n if (record.fields[field]?.sent === wanted && currentHash !== null) {\n result.unchanged.push(field)\n continue\n }\n try {\n await ctx.setters.mcpUpsert({ config: config as unknown as McpServerConfig }, peer)\n }\n catch (err) {\n result.skipped.push({ field, reason: err instanceof Error ? err.message : String(err) })\n continue\n }\n mark(record, field, 'mcps', { hash: hashOf(name) ?? wanted, sent: wanted })\n result.applied.push(field)\n if (typeof config.command === 'string' && config.command.trim() !== '' && !commandAvailable(config.command.trim()))\n result.warnings.push({ field, message: `\"${config.command}\" is not on this server's PATH: the server may not run there.` })\n }\n for (const [field, known] of Object.entries(record.fields)) {\n if (known.category !== 'mcps' || sent.has(field))\n continue\n const name = field.slice('mcp:'.length)\n if (!writable(record, field, hashOf(name), result))\n continue\n try {\n await ctx.setters.mcpRemove({ name }, peer)\n }\n catch (err) {\n result.skipped.push({ field, reason: err instanceof Error ? err.message : String(err) })\n continue\n }\n delete record.fields[field]\n result.applied.push(field)\n }\n}\n\n// ---- extensions ----------------------------------------------------------\nexport async function pushExtensions(ctx: SyncApplyContext, record: SyncRecord, payload: SyncPayloads['extensions'], peer: HostPeer, result: SyncPushResult): Promise<void> {\n if (!isRecord(payload) || !Array.isArray(payload.extensions))\n throw new InvalidParamsError('extensions: payload.extensions must be a list.')\n for (const entry of payload.extensions) {\n const name = isRecord(entry) && typeof entry.name === 'string' ? entry.name : ''\n const field = `extension:${name}`\n if (!NAME_RE.test(name) || typeof entry.spec !== 'string') {\n result.skipped.push({ field, reason: 'needs a plain name and a source spec' })\n continue\n }\n if (record.overrides[field]) {\n result.skipped.push({ field, reason: 'override' })\n continue\n }\n // Installed already (by sync or by hand): left as it is, never updated or removed by sync.\n if (userExtensionDirs(ctx, name).some(dir => existsSync(dir))) {\n if (!record.fields[field])\n mark(record, field, 'extensions', {})\n result.unchanged.push(field)\n continue\n }\n try {\n await ctx.setters.install({ kind: 'extension', spec: entry.spec, scope: 'user', ...(typeof entry.extension === 'string' ? { extension: entry.extension } : {}) }, peer)\n }\n catch (err) {\n result.skipped.push({ field, reason: err instanceof Error ? err.message : String(err) })\n continue\n }\n mark(record, field, 'extensions', {})\n result.applied.push(field)\n }\n}\n\n// ---- provider API keys ---------------------------------------------------\n// ---- environments ------------------------------------------------------\n/**\n * Cloud sandbox kinds (`SYNCABLE_ENVIRONMENT_KINDS`): each as the server's\n * own `environments.update` writes it, so its registry checks every option.\n * A kind the server doesn't have, or the device sent outside the list, is\n * skipped. An edit made on the server since is an override (compared by the\n * hash of its options and on/off state; keys are not read back).\n */\nexport function pushEnvironments(ctx: SyncApplyContext, record: SyncRecord, payload: SyncPayloads['environments'], result: SyncPushResult): void {\n if (!isRecord(payload) || !Array.isArray(payload.kinds))\n throw new InvalidParamsError('environments: payload.kinds must be a list.')\n const currentHash = (kind: string): string => {\n const settings = readEnvironmentSettings(ctx.env.readSettings())\n return hashValue({ config: settings.config[kind] ?? {}, enabled: settings.enabled.includes(kind), disabled: settings.disabled.includes(kind) })\n }\n for (const entry of payload.kinds) {\n const kind = isRecord(entry) && typeof entry.kind === 'string' ? entry.kind : ''\n const field = `environment:${kind}`\n if (!SYNCABLE_ENVIRONMENT_KINDS.includes(kind)) {\n result.skipped.push({ field, reason: 'not a cloud sandbox' })\n continue\n }\n if (!writable(record, field, currentHash(kind), result))\n continue\n const wanted = hashValue(entry)\n if (record.fields[field]?.sent === wanted) {\n result.unchanged.push(field)\n continue\n }\n const values = isRecord(entry.values) ? entry.values : {}\n const secrets = isRecord(entry.secrets) ? entry.secrets : {}\n try {\n const write = applyEnvironmentSettingsChange(ctx.environments, ctx.env.readSettings(), {\n kind,\n ...(typeof entry.enabled === 'boolean' ? { enabled: entry.enabled } : {}),\n values: { ...values, ...secrets } as Record<string, string | number | boolean>,\n })\n for (const secret of write.secrets)\n ctx.environmentSecrets.set(kind, secret.key, secret.value)\n ctx.setters.setSettings(write.settingsPatch)\n }\n catch (err) {\n result.skipped.push({ field, reason: err instanceof Error ? err.message : String(err) })\n continue\n }\n mark(record, field, 'environments', { hash: currentHash(kind), sent: wanted })\n result.applied.push(field)\n }\n}\n\nexport function pushKeys(ctx: SyncApplyContext, record: SyncRecord, payload: SyncPayloads['keys'], result: SyncPushResult): void {\n if (!isRecord(payload) || !Array.isArray(payload.keys))\n throw new InvalidParamsError('keys: payload.keys must be a list.')\n for (const entry of payload.keys) {\n const provider = isRecord(entry) && typeof entry.provider === 'string' ? entry.provider : ''\n const field = `key:${provider}`\n if (!record.keys.includes(provider)) {\n result.skipped.push({ field, reason: 'not opted in for this key' })\n continue\n }\n if (record.overrides[field]) {\n result.skipped.push({ field, reason: 'override' })\n continue\n }\n try {\n if (typeof entry.key !== 'string' || entry.key.trim() === '')\n throw new Error('empty key')\n if (ctx.auth.storedKeys(ctx.auth.descriptorOf(provider)).includes(entry.key.trim())) {\n if (!record.fields[field])\n mark(record, field, 'keys', {})\n result.unchanged.push(field)\n continue\n }\n ctx.setters.setApiKey({ provider, key: entry.key })\n }\n catch (err) {\n result.skipped.push({ field, reason: err instanceof Error ? err.message : String(err) })\n continue\n }\n mark(record, field, 'keys', {})\n result.applied.push(field)\n }\n}\n","/**\n * A zidane-server's settings-sync record (`<dataDir>/sync.json`, 0600,\n * written atomically): the source device, the categories and API keys it\n * opted in, the fields it set (with a hash of what the server held after\n * each write, to tell a server-side edit) and the fields edited here since\n * (overrides). No secret is stored: an API key field has no hash.\n */\nimport type { SyncCategory, SyncSource, SyncStatus } from '../../chat/sync/types'\nimport { existsSync, readFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { OWNER_ONLY, writeJsonFileAtomic } from '../../atomic-write'\nimport { isRecord } from '../../chat/sync/hash'\nimport { settingField, SYNC_CATEGORIES } from '../../chat/sync/types'\n\nexport interface SyncFieldRecord {\n category: SyncCategory\n syncedAt: number\n /** Hash of the server's value right after the last write: anything else there now is an edit made here. */\n hash?: string\n /** Hash of the value the source sent last: the same again is `unchanged`. */\n sent?: string\n /** A safelist: the project key it maps to here, and the entries the source put there. */\n target?: string\n entries?: string[]\n}\n\nexport interface SyncRecord {\n version: 1\n source: SyncSource | null\n categories: SyncCategory[]\n keys: string[]\n fields: Record<string, SyncFieldRecord>\n overrides: Record<string, { at: number }>\n lastPushAt?: number\n}\n\nexport const SYNC_FILE = 'sync.json'\n\nexport function emptySyncRecord(): SyncRecord {\n return { version: 1, source: null, categories: [], keys: [], fields: {}, overrides: {} }\n}\n\nconst SAFE_MODE_FIELD = settingField('safeMode')\nconst APPROVAL_MODE_FIELD = settingField('approvalMode')\n\n/**\n * `approvalMode` replaced the synced `safeMode`. An override of it still\n * guards the server's mode, so it moves over; its field hash (of a boolean)\n * matches no mode, so it goes and the next push syncs the field afresh.\n */\nfunction withoutSafeModeField(record: SyncRecord): SyncRecord {\n const { [SAFE_MODE_FIELD]: override, ...overrides } = record.overrides\n const { [SAFE_MODE_FIELD]: _field, ...fields } = record.fields\n if (override && !overrides[APPROVAL_MODE_FIELD])\n overrides[APPROVAL_MODE_FIELD] = override\n return { ...record, fields, overrides }\n}\n\nexport interface SyncStore {\n file: string\n read: () => SyncRecord\n write: (record: SyncRecord) => void\n}\n\nexport function createSyncStore(dataDir: string): SyncStore {\n const file = join(dataDir, SYNC_FILE)\n return {\n file,\n read: () => {\n if (!existsSync(file))\n return emptySyncRecord()\n try {\n const raw: unknown = JSON.parse(readFileSync(file, 'utf8'))\n if (!isRecord(raw))\n return emptySyncRecord()\n const source = isRecord(raw.source) && typeof raw.source.deviceId === 'string' && typeof raw.source.deviceName === 'string'\n ? raw.source as unknown as SyncSource\n : null\n return withoutSafeModeField({\n version: 1,\n source,\n categories: Array.isArray(raw.categories) ? raw.categories.filter((c): c is SyncCategory => SYNC_CATEGORIES.includes(c as SyncCategory)) : [],\n keys: Array.isArray(raw.keys) ? raw.keys.filter((k): k is string => typeof k === 'string') : [],\n fields: isRecord(raw.fields) ? raw.fields as Record<string, SyncFieldRecord> : {},\n overrides: isRecord(raw.overrides) ? raw.overrides as Record<string, { at: number }> : {},\n ...(typeof raw.lastPushAt === 'number' ? { lastPushAt: raw.lastPushAt } : {}),\n })\n }\n catch {\n // Unreadable: start over (the next write replaces it).\n return emptySyncRecord()\n }\n },\n write: record => writeJsonFileAtomic(file, record, OWNER_ONLY),\n }\n}\n\n/** What `sync.status` says: the record without hashes or safelist entries. */\nexport function syncStatusOf(record: SyncRecord): SyncStatus {\n return {\n source: record.source,\n categories: [...record.categories],\n keys: [...record.keys],\n fields: Object.fromEntries(Object.entries(record.fields).map(([field, f]) => [field, { category: f.category, syncedAt: f.syncedAt }])),\n overrides: { ...record.overrides },\n ...(record.lastPushAt !== undefined ? { lastPushAt: record.lastPushAt } : {}),\n }\n}\n","/**\n * Settings sync from a client's computer (`sync.*`, `docs/SERVER.md`\n * § Settings sync): a zidane-server takes one device's settings, files,\n * MCP servers, extensions and opted-in API keys, through the same setters a\n * window uses (`settings.set`, `mcp.upsert` / `remove`, `catalog.install`,\n * `auth.setApiKey`, the user-scope files), and keeps a record of what came\n * from where (`../sync-store`).\n *\n * - One source per server: `sync.claim` by another device is refused unless\n * it takes over (which drops the previous source's marks, not its values).\n * The source is the device AND the token it claimed with: a device id is a\n * client's word, so the same id from another token is another source\n * (coordination between a user's devices, bound to who authenticated).\n * - A field edited on the server since it was synced (through a window, or\n * on disk: its value no longer matches what sync wrote) is an override:\n * pushes skip it until `sync.reset`.\n * - Window-only settings never apply; skills are written by plain names and\n * relative paths inside the skills folder, size-bounded; extensions and\n * MCP servers go through the install gate (`allowRemoteInstalls`) and its\n * audit; API keys only for providers the source opted in.\n * - Every call is audited with the connection's token; no value is logged.\n */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { SyncCategory, SyncPayloads, SyncPushResult, SyncStatus } from '../../../chat/sync/types'\nimport type { HostSignal, IpcParams } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { HostPeer } from '../peers'\nimport type { SyncApplyContext } from '../sync-apply'\nimport type { SyncRecord } from '../sync-store'\nimport type { ProviderAuth } from './auth'\nimport type { Handlers } from './types'\nimport { homedir } from 'node:os'\nimport { isRecord } from '../../../chat/sync/hash'\nimport { settingField, SYNC_CATEGORIES } from '../../../chat/sync/types'\nimport { pushEnvironments, pushExtensions, pushFiles, pushKeys, pushMcps, pushSafelists, pushSettings } from '../sync-apply'\nimport { createSyncStore, syncStatusOf } from '../sync-store'\nimport { InvalidParamsError } from './params'\n\nexport interface SyncOptions {\n /** One audit line per call (the server adds the connection's token). */\n audit?: (peer: HostPeer, entry: Record<string, unknown>) => void\n}\n\ntype SyncMethod = 'sync.status' | 'sync.claim' | 'sync.push' | 'sync.reset' | 'sync.release'\n\n/** The host's own setters, as a window calls them (installs gated and audited there). */\nexport interface SyncSetters {\n setSettings: (patch: Record<string, unknown>) => Record<string, unknown>\n install: (params: IpcParams<'catalog.install'>, peer: HostPeer) => Promise<unknown> | unknown\n mcpUpsert: (params: IpcParams<'mcp.upsert'>, peer: HostPeer) => Promise<unknown> | unknown\n mcpRemove: (params: IpcParams<'mcp.remove'>, peer: HostPeer) => Promise<unknown> | unknown\n setApiKey: (params: IpcParams<'auth.setApiKey'>) => unknown\n}\n\nconst MAX_DEVICE_FIELD = 200\n\nconst NOT_A_SERVER = 'This host takes no settings sync (a zidane-server does).'\n\nfunction checkDevice(p: { deviceId?: unknown, deviceName?: unknown }, withName: boolean): { deviceId: string, deviceName: string } {\n if (typeof p.deviceId !== 'string' || p.deviceId.trim() === '' || p.deviceId.length > MAX_DEVICE_FIELD)\n throw new InvalidParamsError('deviceId must be a non-empty string.')\n if (withName && (typeof p.deviceName !== 'string' || p.deviceName.trim() === '' || p.deviceName.length > MAX_DEVICE_FIELD))\n throw new InvalidParamsError('deviceName must be a non-empty string.')\n return { deviceId: p.deviceId, deviceName: typeof p.deviceName === 'string' ? p.deviceName.trim() : '' }\n}\n\nfunction checkCategories(value: unknown): SyncCategory[] | undefined {\n if (value === undefined)\n return undefined\n if (!Array.isArray(value) || !value.every(c => SYNC_CATEGORIES.includes(c as SyncCategory)))\n throw new InvalidParamsError(`categories must be some of: ${SYNC_CATEGORIES.join(', ')}.`)\n return SYNC_CATEGORIES.filter(c => value.includes(c))\n}\n\nexport function createSyncHandlers({ host, env, broadcast, setters, auth, options }: {\n host: Pick<ChatHost, 'rebuildAllAgents' | 'environments' | 'environmentSecrets'>\n env: DaemonEnvironment\n broadcast: (signal: HostSignal) => void\n setters: SyncSetters\n auth: Pick<ProviderAuth, 'descriptorOf' | 'storedKeys'>\n options?: SyncOptions\n}): Handlers<SyncMethod> & { markOverrides: (fields: readonly string[]) => Promise<void> } {\n const store = createSyncStore(env.userDataDir())\n const ctx: SyncApplyContext = { env, setters, auth, environments: host.environments, environmentSecrets: host.environmentSecrets, home: () => homedir(), prefix: () => env.config.prefix }\n\n /** Sync calls (and override marks) one at a time: each reads the record, works, writes it. */\n let queue: Promise<unknown> = Promise.resolve()\n const exclusive = <T>(work: () => Promise<T> | T): Promise<T> => {\n const next = queue.then(work, work)\n queue = next.catch(() => undefined)\n return next\n }\n\n const changed = (): void => broadcast({ kind: 'sync:changed' })\n const audit = (peer: HostPeer, entry: Record<string, unknown>): void => options?.audit?.(peer, entry)\n\n function requireOptions(): void {\n if (!options)\n throw new Error(NOT_A_SERVER)\n }\n\n /** Mark fields the source set as edited here; nothing for fields nobody synced. */\n const markOverrides = (fields: readonly string[]): Promise<void> => {\n if (!options || fields.length === 0)\n return Promise.resolve()\n return exclusive(() => {\n const record = store.read()\n const marked = fields.filter(field => record.fields[field] && !record.overrides[field])\n if (marked.length === 0)\n return\n const at = Date.now()\n for (const field of marked)\n record.overrides[field] = { at }\n store.write(record)\n changed()\n })\n }\n\n /** Whether `deviceId` over `peer`'s token is the recorded source. */\n const isSource = (record: SyncRecord, deviceId: string, peer: HostPeer): boolean =>\n record.source !== null && record.source.deviceId === deviceId && record.source.tokenId === peer.principal\n\n /** The source's own call, or a refusal naming the device that syncs. */\n function requireSource(record: SyncRecord, deviceId: string, peer: HostPeer): void {\n if (!record.source)\n throw new Error('No device syncs to this server: claim it first (sync.claim).')\n if (!isSource(record, deviceId, peer))\n throw new Error(`This server is synced from ${record.source.deviceName}${record.source.deviceId === deviceId ? ' with another token' : ''}: take over from that device first.`)\n }\n\n const rebuild = (): void => {\n void host.rebuildAllAgents({ rediscover: true }).catch(() => undefined)\n }\n\n return {\n markOverrides,\n\n 'sync.status': (): SyncStatus => {\n requireOptions()\n return syncStatusOf(store.read())\n },\n\n 'sync.claim': (p, peer) => exclusive(() => {\n requireOptions()\n const { deviceId, deviceName } = checkDevice(p, true)\n const categories = checkCategories(p.categories)\n if (p.keys !== undefined && (!Array.isArray(p.keys) || !p.keys.every(k => typeof k === 'string')))\n throw new InvalidParamsError('keys must be provider names.')\n const takeover = p.takeover === true\n const record = store.read()\n const other = record.source !== null && !isSource(record, deviceId, peer)\n if (other && !takeover) {\n audit(peer, { event: 'sync.claim', deviceId, deviceName, takeover, claimed: false, ok: true })\n return { claimed: false, status: syncStatusOf(record) }\n }\n const next: SyncRecord = other\n ? { version: 1, source: null, categories: [], keys: [], fields: {}, overrides: {} }\n : record\n next.source = {\n deviceId,\n deviceName,\n claimedAt: other || !record.source ? Date.now() : record.source.claimedAt,\n ...(peer.principal ? { tokenId: peer.principal } : {}),\n }\n if (categories)\n next.categories = categories\n if (p.keys !== undefined)\n next.keys = [...new Set(p.keys)]\n store.write(next)\n changed()\n audit(peer, { event: 'sync.claim', deviceId, deviceName, takeover, claimed: true, categories: next.categories, keys: next.keys, ok: true })\n return { claimed: true, status: syncStatusOf(next) }\n }),\n\n 'sync.push': (p, peer) => exclusive(async () => {\n requireOptions()\n const { deviceId } = checkDevice(p, false)\n const category = p.category\n const fields = { event: 'sync.push', category, deviceId }\n try {\n if (!SYNC_CATEGORIES.includes(category))\n throw new InvalidParamsError(`category must be one of: ${SYNC_CATEGORIES.join(', ')}.`)\n const record = store.read()\n requireSource(record, deviceId, peer)\n if (!record.categories.includes(category))\n throw new Error(`\"${category}\" is not synced to this server (claim it with that category).`)\n const result: SyncPushResult = { applied: [], unchanged: [], skipped: [], warnings: [] }\n const payload = p.payload as unknown\n if (category === 'settings') {\n pushSettings(ctx, record, payload as SyncPayloads['settings'], result)\n }\n else if (category === 'safelists') {\n pushSafelists(ctx, record, payload as SyncPayloads['safelists'], result)\n }\n else if (category === 'files') {\n if (pushFiles(ctx, record, payload as SyncPayloads['files'], result)) {\n rebuild()\n broadcast({ kind: 'catalog:changed', catalog: 'skills' })\n }\n }\n else if (category === 'mcps') {\n await pushMcps(ctx, record, payload as SyncPayloads['mcps'], peer, result)\n }\n else if (category === 'extensions') {\n await pushExtensions(ctx, record, payload as SyncPayloads['extensions'], peer, result)\n }\n else if (category === 'environments') {\n pushEnvironments(ctx, record, payload as SyncPayloads['environments'], result)\n }\n else {\n pushKeys(ctx, record, payload as SyncPayloads['keys'], result)\n }\n record.lastPushAt = Date.now()\n store.write(record)\n changed()\n audit(peer, { ...fields, applied: result.applied.length, unchanged: result.unchanged.length, skipped: result.skipped.length, ok: true })\n return result\n }\n catch (err) {\n audit(peer, { ...fields, ok: false, error: err instanceof Error ? err.message : String(err) })\n throw err\n }\n }),\n\n 'sync.reset': (p, peer) => exclusive(() => {\n requireOptions()\n if (typeof p.field !== 'string' || p.field === '')\n throw new InvalidParamsError('field must be a sync field name.')\n const record = store.read()\n const reset = Boolean(record.overrides[p.field])\n if (reset) {\n delete record.overrides[p.field]\n // Forget the server value it was compared against: the next push writes over it.\n const known = record.fields[p.field]\n if (known) {\n delete known.hash\n delete known.sent\n }\n store.write(record)\n changed()\n }\n audit(peer, { event: 'sync.reset', field: p.field, reset, ok: true })\n return { reset }\n }),\n\n 'sync.release': (p, peer) => exclusive(() => {\n requireOptions()\n const { deviceId } = checkDevice(p, false)\n const record = store.read()\n if (!record.source)\n return { released: false }\n requireSource(record, deviceId, peer)\n // What it set stays; the marks go.\n store.write({ version: 1, source: null, categories: [], keys: [], fields: {}, overrides: {} })\n changed()\n audit(peer, { event: 'sync.release', deviceId, ok: true })\n return { released: true }\n }),\n }\n}\n\ntype OverrideWrapped = 'settings.set' | 'mcp.upsert' | 'mcp.remove' | 'catalog.remove' | 'catalog.update' | 'auth.setApiKey' | 'auth.configure' | 'auth.remove' | 'auth.setPreferred'\n\n/**\n * The window-facing setters, marking what they change as an override when\n * the field came from sync (the sync handlers call the unwrapped ones).\n */\nexport function withSyncOverrides(\n handlers: Handlers<OverrideWrapped>,\n { readSettings, markOverrides }: { readSettings: () => object, markOverrides: (fields: readonly string[]) => Promise<void> },\n): Handlers<OverrideWrapped> {\n const after = async <T>(work: () => Promise<T> | T, fields: (result: T) => string[]): Promise<T> => {\n const result = await work()\n await markOverrides(fields(result))\n return result\n }\n return {\n 'settings.set': async (p, peer) => {\n const before = readSettings() as Record<string, unknown>\n return after(() => handlers['settings.set'](p, peer), next => Object.keys(isRecord(p?.patch) ? p.patch : {})\n .filter(key => JSON.stringify(before[key]) !== JSON.stringify((next as unknown as Record<string, unknown>)[key]))\n .map(settingField))\n },\n 'mcp.upsert': (p, peer) => after(() => handlers['mcp.upsert'](p, peer), r => (p.scope === 'project' ? [] : [`mcp:${r.name}`])),\n 'mcp.remove': (p, peer) => after(() => handlers['mcp.remove'](p, peer), r => (r.removed ? [`mcp:${p.name}`] : [])),\n 'catalog.remove': (p, peer) => after(() => handlers['catalog.remove'](p, peer), () => [`${p.kind}:${p.name}`]),\n 'catalog.update': (p, peer) => after(() => handlers['catalog.update'](p, peer), () => [`${p.kind}:${p.name}`]),\n 'auth.setApiKey': (p, peer) => after(() => handlers['auth.setApiKey'](p, peer), () => [`key:${p.provider}`]),\n 'auth.configure': (p, peer) => after(() => handlers['auth.configure'](p, peer), () => [`key:${p.provider}`]),\n 'auth.remove': (p, peer) => after(() => handlers['auth.remove'](p, peer), r => (r.removed ? [`key:${p.provider}`] : [])),\n 'auth.setPreferred': (p, peer) => after(() => handlers['auth.setPreferred'](p, peer), () => [`key:${p.provider}`]),\n }\n}\n","/** Shared terminals: lifecycle, I/O, and the views and viewers each client attaches. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { nonNegativeInt } from './params'\n\ntype TerminalMethod\n = | 'terminal.state' | 'terminal.open' | 'terminal.attach' | 'terminal.detach' | 'terminal.write'\n | 'terminal.resize' | 'terminal.ack' | 'terminal.restart' | 'terminal.close' | 'terminal.setHidden'\n | 'terminal.registerViewer' | 'terminal.unregisterViewer'\n | 'terminal.projectState' | 'terminal.openInProject' | 'terminal.adopt' | 'terminal.releaseDraft'\n\nexport function createTerminalHandlers({ host, isConnected }: {\n host: ChatHost\n isConnected: (peer: HostPeer) => boolean\n}): {\n methods: Handlers<TerminalMethod>\n /** The peer dropped: release its drafts and viewers, then detach its views. */\n releasePeer: (peer: HostPeer) => void\n} {\n return {\n methods: {\n 'terminal.state': p => host.terminals.state(p.sessionId),\n 'terminal.open': p => host.terminals.open(p),\n 'terminal.attach': async (p, peer) => {\n // Optional: older clients omit it, and 0 means no cap.\n const maxLines = nonNegativeInt(p.maxLines, 'maxLines') || undefined\n const result = await host.terminals.attach(p.terminalId, p.clientId, { maxLines })\n // The peer dropped during the attach (a remote reconnect can take seconds):\n // its cleanup already ran, so a client left behind would never ack and stall every view.\n if (!isConnected(peer)) {\n host.terminals.detach(p.terminalId, p.clientId)\n return result\n }\n const views = (peer.terminalViews ??= new Map())\n views.set(p.terminalId, (views.get(p.terminalId) ?? new Set()).add(p.clientId))\n return result\n },\n 'terminal.detach': (p, peer) => {\n const views = peer.terminalViews?.get(p.terminalId)\n views?.delete(p.clientId)\n if (views?.size === 0)\n peer.terminalViews?.delete(p.terminalId)\n host.terminals.detach(p.terminalId, p.clientId)\n },\n 'terminal.write': p => host.terminals.write(p.terminalId, p.data, p.clientId ? { clientId: p.clientId, ...(p.response ? { response: true } : {}) } : undefined),\n 'terminal.resize': p => host.terminals.resize(p.terminalId, p.clientId, p.cols, p.rows, p.claim),\n 'terminal.ack': p => host.terminals.ack(p.terminalId, p.clientId, p.offset),\n 'terminal.restart': p => host.terminals.restart(p.terminalId),\n 'terminal.close': p => host.terminals.close(p.terminalId),\n 'terminal.setHidden': p => host.terminals.setHidden(p.terminalId, p.hidden),\n 'terminal.projectState': p => host.terminals.projectState(p),\n 'terminal.openInProject': async (p, peer) => {\n if (p.draftId)\n (peer.terminalDrafts ??= new Set()).add(p.draftId)\n const result = await host.terminals.openInProject(p)\n // The peer dropped during the open: its cleanup already ran, so nothing would release this draft.\n if (p.draftId && !isConnected(peer))\n host.terminals.releaseDraft(p.draftId)\n return result\n },\n 'terminal.adopt': async (p, peer) => {\n const result = await host.terminals.adopt(p)\n peer.terminalDrafts?.delete(p.draftId)\n return result\n },\n 'terminal.releaseDraft': (p, peer) => {\n peer.terminalDrafts?.delete(p.draftId)\n host.terminals.releaseDraft(p.draftId)\n },\n 'terminal.registerViewer': (p, peer) => {\n ;(peer.terminalViewers ??= new Set()).add(p.viewerId)\n host.terminals.registerViewer(p.viewerId)\n return { ok: true }\n },\n 'terminal.unregisterViewer': (p, peer) => {\n peer.terminalViewers?.delete(p.viewerId)\n host.terminals.unregisterViewer(p.viewerId)\n return { ok: true }\n },\n },\n releasePeer(peer) {\n // A client that crashed or quit never releases its drafts: give their terminals back to the project.\n for (const draftId of peer.terminalDrafts ?? [])\n host.terminals.releaseDraft(draftId)\n for (const viewerId of peer.terminalViewers ?? [])\n host.terminals.unregisterViewer(viewerId)\n for (const [terminalId, clients] of peer.terminalViews ?? []) {\n for (const clientId of clients)\n host.terminals.detach(terminalId, clientId)\n }\n },\n }\n}\n","/** `sessions.generateTitle`: the host titles a session with its own providers and credentials (`ChatHost.generateSessionTitle`). */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HostSignal } from '../../protocol'\nimport type { Handlers } from './types'\nimport { optionalString, sessionIdOf } from './params'\n\nexport function createTitleHandlers({ host, broadcast }: {\n host: ChatHost\n broadcast: (signal: HostSignal) => void\n}): Handlers<'sessions.generateTitle'> {\n return {\n 'sessions.generateTitle': async (p) => {\n const sessionId = sessionIdOf(p)\n const providerKey = optionalString(p.providerKey, 'providerKey')\n const model = optionalString(p.model, 'model')\n const title = await host.generateSessionTitle(sessionId, {\n ...(providerKey !== undefined ? { providerKey } : {}),\n ...(model !== undefined ? { model } : {}),\n })\n // As `sessions.setTitle`: every window told.\n broadcast({ kind: 'sessions:changed', op: 'update', sessionId })\n return { title }\n },\n }\n}\n","/** A session's todo list. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { TodoItem } from '../../../chat/todos'\nimport type { SessionStore } from '../../../session/index'\nimport type { TodosSnapshot } from '../../protocol'\nimport type { Handlers } from './types'\nimport { toTodosSnapshot } from '../../../chat/host/signals'\nimport { selectActiveTodos, setTodosForRun } from '../../../chat/todos'\nimport { loadSession } from '../../../session/index'\n\nexport function createTodoHandlers({ host, store }: { host: ChatHost, store: SessionStore }): Handlers<'todos.get' | 'todos.set'> {\n return {\n 'todos.get': (p): TodosSnapshot | null => {\n const state = host.getTodosSnapshot(p.sessionId)\n return state ? toTodosSnapshot(state) : null\n },\n\n /*\n * The host fans the resulting `todos:snapshot` out to every window,\n * including this caller — the returned snapshot is a confirmation, so the\n * sender can tell \"applied\" from \"no live agent\" (null) rather than\n * assuming success. `persistIdle` turns \"no live agent\" into a write to\n * the stored session (nothing else is writing it), for a client that has\n * no store of its own.\n */\n 'todos.set': async (p): Promise<TodosSnapshot | null> => {\n const state = await host.setTodos(p.sessionId, p.items)\n if (state)\n return toTodosSnapshot(state)\n if (p.persistIdle !== true || host.getLiveSession(p.sessionId))\n return null\n return persistIdleTodos(store, p.sessionId, Array.isArray(p.items) ? p.items : [])\n },\n }\n}\n\n/** The idle-session todo edit, as a window applied it to its own copy: the active run's list, archive cleared. */\nasync function persistIdleTodos(store: SessionStore, sessionId: string, items: readonly TodoItem[]): Promise<TodosSnapshot | null> {\n const session = await loadSession(store, sessionId, { persistHeal: false })\n if (!session)\n return null\n // `null` before the first run: the session slot that run will read.\n setTodosForRun(session, selectActiveTodos(session).runId, items, { clearArchive: true })\n await session.save()\n return toTodosSnapshot(selectActiveTodos(session))\n}\n","/** A session's turns: replay, fork, edits, out-of-band appends, and compaction. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { StreamEvent } from '../../../chat/index'\nimport type { SessionStore } from '../../../session/index'\nimport type { HostTranscriptPager } from '../../history/index'\nimport type { HostSignal, LoadEventsPaging } from '../../protocol'\nimport type { Handlers } from './types'\nimport { describeForkFailure } from '../../../chat/session-factory'\nimport { eventsFromTurns } from '../../../chat/store'\nimport { loadOrThrow } from './session-load'\nimport { isPagedLoad } from './transcript-page'\n\ntype TranscriptMethod\n = | 'sessions.loadEvents' | 'sessions.getTurn' | 'sessions.touch' | 'sessions.fork' | 'sessions.deleteTurn'\n | 'sessions.editTurnText' | 'sessions.rewind' | 'sessions.appendTurns' | 'sessions.appendNote' | 'sessions.compact'\n\nexport function createTranscriptHandlers({ host, store, broadcast, pages }: {\n host: ChatHost\n store: SessionStore\n broadcast: (signal: HostSignal) => void\n /** Pages, sliced from the session's whole replay (one replay per scroll-back, not per page), off this thread when it can. */\n pages: Pick<HostTranscriptPager, 'page'>\n}): Handlers<TranscriptMethod> {\n return {\n 'sessions.loadEvents': async (p) => {\n const paging = p as typeof p & LoadEventsPaging\n if (isPagedLoad(paging)) {\n // A slice of the whole replay: pages concatenate to exactly one whole load.\n // The paged shape (`loadEventsPage`); the method is typed by its unpaged call.\n return await pages.page(store, p.sessionId, paging) as unknown as StreamEvent[]\n }\n const data = await loadOrThrow(store, p.sessionId)\n // Pass `runs` so replay reconstructs subagent depth / ancestry /\n // spawn rendering — matching the GUI + TUI local replay paths.\n return eventsFromTurns(data.turns, data.runs)\n },\n 'sessions.getTurn': async (p) => {\n const data = await store.load(p.sessionId)\n return data?.turns.find(t => t.id === p.turnId) ?? null\n },\n // Out-of-band transcript append (local command / bash output) — tell\n // every window to re-converge on the store's canonical replay.\n 'sessions.touch': (p) => {\n broadcast({ kind: 'sessions:changed', op: 'update', sessionId: p.sessionId })\n },\n 'sessions.fork': async (p) => {\n const result = await host.forkSession({\n source: p.sessionId,\n turnId: p.turnId,\n ...(typeof p.title === 'string' && p.title ? { title: p.title.slice(0, 256) } : {}),\n })\n if (!result.ok)\n throw new Error(describeForkFailure(result.reason, p.sessionId, p.turnId))\n broadcast({ kind: 'sessions:changed', op: 'create', sessionId: result.id })\n return { id: result.id }\n },\n 'sessions.deleteTurn': p => host.deleteTurn(p.sessionId, p.turnId),\n // Same 64 KiB text cap as the composer paths.\n 'sessions.editTurnText': p => host.editTurnText(p.sessionId, p.turnId, typeof p.text === 'string' ? p.text.slice(0, 64 * 1024) : ''),\n 'sessions.rewind': p => host.rewindSession(p.sessionId, p.turnId, { inclusive: p.inclusive === true }),\n 'sessions.appendTurns': p => host.appendTurns(p.sessionId, Array.isArray(p.turns) ? p.turns : [], { whenIdle: p.whenIdle === true }),\n 'sessions.appendNote': p => host.appendNote(\n p.sessionId,\n Array.isArray(p.blocks) ? p.blocks.filter(block => typeof block?.text === 'string') : [],\n ),\n 'sessions.compact': p => host.compactSessionNow(p.sessionId),\n }\n}\n","/**\n * `usage.summary`: the welcome screen's usage summary over the host's\n * sessions database, as the desktop app reduces its own\n * (`../../../chat/usage-summary.ts`). The scan reads every turn, so its day\n * buckets are kept a minute and every range is cut from them; concurrent\n * calls share one scan. Days are the host's local days. The greeting's name\n * is left out: the host's user is not the person reading.\n *\n * `usage.providers`: each provider's plan windows, probed with the host's\n * credentials (`../../../chat/provider-usage.ts`, which caches them), and\n * `usage.github`: GitHub's API limits as the host's GitHub client sees them.\n */\nimport type { ProviderDescriptor } from '../../../chat/providers'\nimport type { UsageRange } from '../../../chat/usage-summary'\nimport type { SessionStore } from '../../../session/index'\nimport type { UsageBuckets } from '../../../session/sqlite-usage'\nimport type { Handlers } from './types'\nimport { fetchGithubUsage } from '../../../chat/github-usage'\nimport { fetchAllProviderUsage } from '../../../chat/provider-usage'\nimport { summarizeUsage, USAGE_RANGES } from '../../../chat/usage-summary'\nimport { InvalidParamsError } from './params'\n\n/** How long one scan's buckets serve. */\nconst BUCKETS_TTL_MS = 60_000\n\nexport function createUsageHandlers({ store, scan, dataDir, providers }: {\n store: SessionStore\n /** The store's day buckets (`HostTranscriptPager.usage`); `null`: the store keeps no usage. */\n scan: (store: SessionStore) => Promise<UsageBuckets | null>\n /** Where the credentials are. */\n dataDir: () => string\n /** The host's providers. */\n providers: () => Readonly<Record<string, ProviderDescriptor>>\n}): Handlers<'usage.summary' | 'usage.providers' | 'usage.github'> {\n let cached: { buckets: UsageBuckets, at: number } | null = null\n let pending: Promise<UsageBuckets> | null = null\n const buckets = (now: number): Promise<UsageBuckets> => {\n if (cached && now - cached.at < BUCKETS_TTL_MS)\n return Promise.resolve(cached.buckets)\n pending ??= scan(store).then((scanned) => {\n if (!scanned)\n throw new Error('This host\\'s session store keeps no usage history.')\n cached = { buckets: scanned, at: Date.now() }\n return scanned\n }).finally(() => {\n pending = null\n })\n return pending\n }\n return {\n 'usage.summary': async (p) => {\n if (!USAGE_RANGES.includes(p.range as UsageRange))\n throw new InvalidParamsError(`range must be one of ${USAGE_RANGES.join(', ')}.`)\n const now = new Date()\n return summarizeUsage(await buckets(now.getTime()), p.range, { now })\n },\n 'usage.providers': p => fetchAllProviderUsage(dataDir(), providers(), { refresh: p?.refresh === true }),\n 'usage.github': p => fetchGithubUsage({ probe: p?.probe === true }),\n }\n}\n","/** Commands and file access inside a session's workspace (its execution environment). */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { Handlers } from './types'\nimport { Buffer } from 'node:buffer'\n\ntype WorkspaceMethod\n = | 'sessions.workspaceExec' | 'sessions.workspaceReadFile' | 'sessions.workspaceWriteFile'\n | 'sessions.workspaceListFiles' | 'sessions.workspaceFileSize'\n | 'sessions.workspaceCreate' | 'sessions.workspaceMove' | 'sessions.workspaceCopy' | 'sessions.workspaceRemove'\n | 'sessions.workspaceEmptyDirs'\n\n/** A path param of an entry call: a string, else refused like any invalid name (the rules check the rest). */\nconst pathParam = (value: unknown): string => (typeof value === 'string' ? value : '\\0')\n\nexport function createWorkspaceHandlers({ host }: { host: ChatHost }): Handlers<WorkspaceMethod> {\n return {\n 'sessions.workspaceExec': p => host.workspaceExec(p.sessionId, p.command, {\n ...(p.cwd !== undefined ? { cwd: p.cwd } : {}),\n ...(p.env !== undefined ? { env: p.env } : {}),\n ...(p.timeoutSeconds !== undefined ? { timeoutSeconds: p.timeoutSeconds } : {}),\n }),\n 'sessions.workspaceReadFile': p => host.workspaceReadFile(p.sessionId, p.path),\n 'sessions.workspaceWriteFile': p => host.workspaceWriteFile(p.sessionId, p.path, p.content),\n 'sessions.workspaceListFiles': p => host.workspaceListFiles(p.sessionId, p.path, p.options),\n 'sessions.workspaceFileSize': p => host.workspaceFileSize(p.sessionId, p.path),\n 'sessions.workspaceCreate': (p) => {\n if (p.kind !== 'file' && p.kind !== 'dir')\n throw new Error('kind must be \"file\" or \"dir\".')\n if (p.content !== undefined && typeof p.content !== 'string')\n throw new Error('content must be base64 text.')\n return host.workspaceCreate(p.sessionId, pathParam(p.path), p.kind, {\n ...(p.content !== undefined ? { content: new Uint8Array(Buffer.from(p.content, 'base64')) } : {}),\n ...(p.freeName === true ? { freeName: true } : {}),\n })\n },\n 'sessions.workspaceMove': p => host.workspaceMove(p.sessionId, pathParam(p.from), pathParam(p.to)),\n 'sessions.workspaceCopy': p => host.workspaceCopy(p.sessionId, pathParam(p.from), pathParam(p.toDir)),\n 'sessions.workspaceRemove': p => host.workspaceRemove(p.sessionId, pathParam(p.path)),\n 'sessions.workspaceEmptyDirs': p => host.workspaceEmptyDirs(p.sessionId),\n }\n}\n","import type { ChatHost } from '../../../chat/host/engine'\n/**\n * Streamed workspace commands (`sessions.workspaceExecStream` /\n * `sessions.workspaceExecCancel`): `!` on a remote host, live. The process\n * is the session context's `execStream` (a machine's too); its output goes\n * to the connection that started it only, as `workspace:exec:data` signals,\n * then one `workspace:exec:exit`. Bounded per connection: concurrent\n * commands, chunk size, total output (past it the process group is stopped\n * and the exit says `truncated`). Cancel and a dropped connection kill the\n * process group. A context that can't stream runs the buffered exec and\n * reports it the same way (its cancel stops reporting, not the command).\n */\nimport type { StreamHandle } from '../../../contexts/types'\nimport type { HostSignal } from '../../protocol'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\nimport { Buffer } from 'node:buffer'\nimport { randomUUID } from 'node:crypto'\nimport { InvalidParamsError } from './params'\n\nexport const WORKSPACE_EXEC_STREAM_LIMITS = {\n /** Streamed commands one connection may run at once. */\n maxConcurrent: 4,\n /** Largest `chunk` of one data signal, in bytes. */\n chunkBytes: 64 * 1024,\n /** Output past this (stdout + stderr, bytes) stops the process: the same ceiling as a local `!`. */\n maxOutputBytes: 1024 * 1024,\n /** Longest command text. */\n maxCommandLength: 64 * 1024,\n /** The buffered fallback's bound (seconds), as the buffered `!` had. */\n fallbackTimeoutSeconds: 600,\n}\n\ntype ExitSignal = Extract<HostSignal, { kind: 'workspace:exec:exit' }>\n\ninterface RunningExec {\n peer: HostPeer\n /** Ends the process group (the fallback: stops reporting). */\n kill: () => void\n cancelled: boolean\n /** A kill was sent before the process's exit was known: the exit is the kill's. */\n killedLive?: boolean\n}\n\n/** Cut `text` into pieces of at most `max` UTF-8 bytes, never inside a code point. */\nfunction utf8Pieces(text: string, max: number): string[] {\n if (Buffer.byteLength(text) <= max)\n return [text]\n const pieces: string[] = []\n let current = ''\n let bytes = 0\n for (const char of text) {\n const size = Buffer.byteLength(char)\n if (bytes + size > max) {\n pieces.push(current)\n current = ''\n bytes = 0\n }\n current += char\n bytes += size\n }\n if (current)\n pieces.push(current)\n return pieces\n}\n\n/** The longest prefix of `text` within `max` UTF-8 bytes. */\nfunction utf8Prefix(text: string, max: number): string {\n let bytes = 0\n let end = 0\n for (const char of text) {\n const size = Buffer.byteLength(char)\n if (bytes + size > max)\n break\n bytes += size\n end += char.length\n }\n return text.slice(0, end)\n}\n\nexport function createWorkspaceExecStreamHandlers({ host, isConnected, limits = WORKSPACE_EXEC_STREAM_LIMITS }: {\n host: Pick<ChatHost, 'workspaceExecStream' | 'workspaceExec'>\n isConnected: (peer: HostPeer) => boolean\n limits?: typeof WORKSPACE_EXEC_STREAM_LIMITS\n}): {\n methods: Handlers<'sessions.workspaceExecStream' | 'sessions.workspaceExecCancel'>\n /** The peer dropped: kill what it started. */\n releasePeer: (peer: HostPeer) => void\n} {\n const running = new Map<string, RunningExec>()\n const perPeer = new WeakMap<HostPeer, Set<string>>()\n\n const send = (peer: HostPeer, signal: HostSignal): void => {\n if (isConnected(peer))\n peer.send(signal)\n }\n\n /** Output accounting for one exec: emits what fits, reports when the cap is reached. */\n function outputSink(execId: string, peer: HostPeer, onCap: () => void) {\n let total = 0\n let capped = false\n return {\n capped: () => capped,\n emit(stream: 'stdout' | 'stderr', text: string): void {\n if (capped || text === '')\n return\n let piece = text\n if (total + Buffer.byteLength(piece) > limits.maxOutputBytes) {\n piece = utf8Prefix(piece, limits.maxOutputBytes - total)\n capped = true\n }\n total += Buffer.byteLength(piece)\n for (const chunk of piece ? utf8Pieces(piece, limits.chunkBytes) : [])\n send(peer, { kind: 'workspace:exec:data', execId, stream, chunk })\n if (capped)\n onCap()\n },\n }\n }\n\n async function pump(execId: string, peer: HostPeer, stream: StreamHandle, entry: RunningExec): Promise<void> {\n const sink = outputSink(execId, peer, () => entry.kill())\n const drain = async (source: AsyncIterable<Uint8Array> | undefined, name: 'stdout' | 'stderr'): Promise<void> => {\n if (!source)\n return\n const decoder = new TextDecoder()\n try {\n for await (const bytes of source)\n sink.emit(name, decoder.decode(bytes, { stream: true }))\n sink.emit(name, decoder.decode())\n }\n catch {\n // The stream ended badly (a dropped machine link): the exit says how.\n }\n }\n const [code] = await Promise.all([stream.exited, drain(stream.stdout, 'stdout'), drain(stream.stderr, 'stderr')])\n // A cancel or cap that landed after the process exited on its own leaves its real exit.\n const killed = entry.killedLive === true\n const exit: ExitSignal = {\n kind: 'workspace:exec:exit',\n execId,\n code: killed ? null : code,\n signal: killed ? 'SIGTERM' : null,\n ...(sink.capped() ? { truncated: true as const } : {}),\n ...(entry.cancelled && killed ? { cancelled: true as const } : {}),\n }\n send(peer, exit)\n }\n\n /** A context without `execStream`: the buffered exec, reported as one stdout and one stderr chunk. */\n async function buffered(execId: string, peer: HostPeer, entry: RunningExec, run: () => Promise<{ stdout: string, stderr: string, exitCode: number }>): Promise<void> {\n let stopped = false\n entry.kill = () => {\n stopped = true\n }\n const sink = outputSink(execId, peer, () => undefined)\n try {\n const result = await run()\n if (!stopped) {\n sink.emit('stdout', result.stdout)\n sink.emit('stderr', result.stderr)\n }\n send(peer, {\n kind: 'workspace:exec:exit',\n execId,\n code: stopped ? null : result.exitCode,\n signal: stopped ? 'SIGTERM' : null,\n ...(sink.capped() ? { truncated: true as const } : {}),\n ...(entry.cancelled ? { cancelled: true as const } : {}),\n })\n }\n catch (err) {\n sink.emit('stderr', err instanceof Error ? err.message : String(err))\n send(peer, { kind: 'workspace:exec:exit', execId, code: null, signal: null, ...(entry.cancelled ? { cancelled: true as const } : {}) })\n }\n }\n\n return {\n methods: {\n 'sessions.workspaceExecStream': async (p, peer) => {\n if (typeof p.sessionId !== 'string' || p.sessionId === '')\n throw new InvalidParamsError('sessionId must be a non-empty string.')\n if (typeof p.command !== 'string' || p.command.trim() === '')\n throw new InvalidParamsError('command must be a non-empty string.')\n if (p.command.length > limits.maxCommandLength)\n throw new InvalidParamsError(`command is longer than ${limits.maxCommandLength} characters.`)\n if (p.cwd !== undefined && typeof p.cwd !== 'string')\n throw new InvalidParamsError('cwd must be a string.')\n const own = perPeer.get(peer) ?? new Set<string>()\n perPeer.set(peer, own)\n if (own.size >= limits.maxConcurrent)\n throw new Error(`This connection already runs ${own.size} shell commands (at most ${limits.maxConcurrent}): stop one first.`)\n const execId = randomUUID()\n // Reserved before the await: concurrent requests count against the bound too.\n own.add(execId)\n const entry: RunningExec = { peer, kill: () => undefined, cancelled: false }\n running.set(execId, entry)\n const done = (): void => {\n own.delete(execId)\n running.delete(execId)\n }\n const options = p.cwd !== undefined ? { cwd: p.cwd } : {}\n let stream: StreamHandle | null\n try {\n stream = await host.workspaceExecStream(p.sessionId, p.command, options)\n }\n catch (err) {\n done()\n throw err\n }\n if (stream) {\n const live = stream\n let exited = false\n void live.exited.then(() => {\n exited = true\n }, () => {\n exited = true\n })\n entry.kill = () => {\n if (!exited)\n entry.killedLive = true\n void live.kill()\n }\n // Dropped while it started: nobody will read it.\n if (!isConnected(peer))\n entry.kill()\n void pump(execId, peer, live, entry).finally(done)\n }\n else {\n void buffered(execId, peer, entry, () => host.workspaceExec(p.sessionId, p.command, { ...options, timeoutSeconds: limits.fallbackTimeoutSeconds })).finally(done)\n }\n return { execId }\n },\n 'sessions.workspaceExecCancel': (p, peer) => {\n const entry = typeof p.execId === 'string' ? running.get(p.execId) : undefined\n if (!entry || entry.peer !== peer)\n return { cancelled: false }\n entry.cancelled = true\n entry.kill()\n return { cancelled: true }\n },\n },\n releasePeer(peer) {\n for (const execId of perPeer.get(peer) ?? []) {\n const entry = running.get(execId)\n if (entry) {\n entry.cancelled = true\n entry.kill()\n }\n }\n },\n }\n}\n","/**\n * `ipc.hello` verdict: can this client attach to this host process?\n *\n * Pure (no I/O, no state) so every transport applies the same three fences:\n * protocol version, build fingerprint, release. Kept apart from the\n * dispatcher because the rules are subtle and the direction of each fence\n * (only a strictly NEWER client retires the host) matters more than the code.\n *\n * A network server (`hostKind: 'server'`) keeps only the protocol fence: it\n * outlives any one client's upgrade and no client may retire it, so a newer\n * release or build attaches and degrades like an older one does.\n */\nimport type { HelloParams, HostKind } from '../protocol'\nimport { compareVersions } from '../../version'\nimport { IPC_MIN_PROTOCOL_VERSION, IPC_PROTOCOL_VERSION } from '../protocol'\n\nexport type HelloVerdict\n /**\n * `retire`: attach, but the host must exit at its first idle point. `protocolVersion`: what\n * the connection speaks (a server and a client in each other's range speak the lower one).\n */\n = | { accept: true, retire: boolean, protocolVersion: number }\n | { accept: false, message: string }\n\nexport interface HelloContext {\n /** This host's build fingerprint (`IPC_BUILD_ID`; `'unknown'` in compiled binaries). */\n buildId: string\n /** This host's release (`ZIDANE_VERSION`). */\n codeVersion: string\n /** Runs, queues or interactions in flight that a drain would abort. */\n hasActiveWork: boolean\n /** What this host is. Default: a local daemon's fences. */\n hostKind?: HostKind\n}\n\n/**\n * A server accepts a client whose version range overlaps its own\n * ({@link IPC_MIN_PROTOCOL_VERSION}…{@link IPC_PROTOCOL_VERSION}); they speak the lower version.\n */\nfunction evaluateServerHello(params: Partial<HelloParams>): HelloVerdict {\n const client = typeof params.protocolVersion === 'number' ? params.protocolVersion : undefined\n const clientMin = typeof params.minProtocolVersion === 'number' ? Math.min(params.minProtocolVersion, client ?? Infinity) : client\n if (client !== undefined && clientMin !== undefined && clientMin <= IPC_PROTOCOL_VERSION && client >= IPC_MIN_PROTOCOL_VERSION)\n return { accept: true, retire: false, protocolVersion: Math.min(client, IPC_PROTOCOL_VERSION) }\n const upgrade = client !== undefined && client > IPC_PROTOCOL_VERSION ? 'server' : 'client'\n const speaks = IPC_MIN_PROTOCOL_VERSION === IPC_PROTOCOL_VERSION ? `v${IPC_PROTOCOL_VERSION}` : `v${IPC_MIN_PROTOCOL_VERSION} to v${IPC_PROTOCOL_VERSION}`\n return {\n accept: false,\n message: `Protocol version mismatch: the server speaks ${speaks}, the client v${client ?? '?'}. Upgrade the ${upgrade}.`,\n }\n}\n\nexport function evaluateHello(params: Partial<HelloParams>, ctx: HelloContext): HelloVerdict {\n if (ctx.hostKind === 'server')\n return evaluateServerHello(params)\n /*\n * Build-fingerprint drain is DIRECTIONAL: only a strictly NEWER\n * client retires this (older) daemon. An older client accepts a\n * newer daemon — its unknown methods degrade via `optional()`.\n * Without the direction check, two concurrently-running clients\n * from different builds would each reject the other's daemon and\n * drain-respawn in a loop, aborting live runs each cycle.\n */\n const clientBuild = Number(params.buildId)\n const daemonBuild = Number(ctx.buildId)\n const staleBuild\n = params.buildId !== undefined\n && params.buildId !== 'unknown'\n && ctx.buildId !== 'unknown'\n && Number.isFinite(clientBuild)\n && Number.isFinite(daemonBuild)\n && clientBuild > daemonBuild\n /*\n * Release fence: the same protocol version can span several\n * releases, and a daemon outlives the upgrade that replaced its\n * binary — a client running strictly NEWER code must not execute on\n * the old process. Same direction rule as the build fence: only a\n * newer client retires the daemon; older clients attach and degrade.\n */\n const staleRelease\n = typeof params.codeVersion === 'string'\n && compareVersions(params.codeVersion, ctx.codeVersion) > 0\n /*\n * Same protocol, older code, live work: attach instead of asking\n * for a drain that would abort it. The client can speak to this\n * daemon; it only must not stay on it, so the daemon retires at\n * its first idle point and the client's reconnect lands on a\n * fresh one. A protocol mismatch can't attach and stays refused.\n */\n const protocolMatches = params.protocolVersion === IPC_PROTOCOL_VERSION\n if (protocolMatches && (staleBuild || staleRelease) && ctx.hasActiveWork)\n return { accept: true, retire: true, protocolVersion: IPC_PROTOCOL_VERSION }\n if (!protocolMatches || staleBuild || staleRelease) {\n return {\n accept: false,\n message: staleRelease\n ? `Stale daemon: it runs zidane ${ctx.codeVersion} but the client runs ${params.codeVersion}. Draining for respawn.`\n : staleBuild\n ? `Build mismatch: the daemon was started from an older build (daemon ${ctx.buildId}, client ${params.buildId}). Draining for respawn.`\n : `Protocol version mismatch: daemon speaks v${IPC_PROTOCOL_VERSION}, client sent v${params.protocolVersion ?? '?'}.`,\n }\n }\n return { accept: true, retire: false, protocolVersion: IPC_PROTOCOL_VERSION }\n}\n","/**\n * Host identity: which host a client is talking to, stable across restarts.\n *\n * The id is a UUID written once to `<dataDir>/host-id` and read back on every\n * start. The data dir is the host's `userDataDir` (the user's zidane dir), so\n * the local daemon and a window's in-process host share one id: they serve\n * the same store on the same computer. A remote `zidane-server` has its own\n * data dir, hence its own id.\n */\nimport type { HostKind } from '../protocol'\nimport { hostname } from 'node:os'\nimport { join } from 'node:path'\nimport { readOrCreateHostIdFile } from '../../host-id'\n\nexport interface HostIdentityOptions {\n kind: HostKind\n /** Display name. Default: the machine's hostname. */\n name?: string\n}\n\nexport interface HostIdentity {\n /** `undefined` when the data dir can't hold the id: the host still serves, without identity. */\n id: string | undefined\n kind: HostKind\n name: string\n}\n\nconst FILE = 'host-id'\n\nexport function resolveHostIdentity(dataDir: string, options: HostIdentityOptions): HostIdentity {\n return {\n id: readOrCreateHostIdFile(join(dataDir, FILE)),\n kind: options.kind,\n name: options.name ?? hostname(),\n }\n}\n","/**\n * Connected peers: the set, signal fan-out, live presence, and the cleanup a\n * dropped peer triggers. Presence piggybacks on fan-out, so the two live\n * together.\n *\n * Streaming deltas are coalesced here, once per event-loop turn: a run of\n * consecutive deltas with the same owner (`deltaKey`) goes out as one signal\n * with their texts joined, one number, one log entry. Anything else that is\n * fanned out (any other signal, terminal output, an origin-excluded one) and\n * a peer joining or leaving sends the held delta first, and so does\n * {@link PeerRegistry.flush}, which the dispatcher calls around every\n * request, so a reply never overtakes a delta emitted before it.\n */\nimport type { ChatHost } from '../../chat/host/engine'\nimport type { HostSignal, SessionPresence } from '../protocol'\nimport type { ClientScope } from '../scopes'\n\n/**\n * A signal serialized once for every peer of one fan-out. `json` is the\n * signal's JSON, computed on first use (`undefined`: it cannot be encoded,\n * so no peer can receive it). `frame` is where the wire transports memoize\n * the notification text they all send (`../transports/peer-rpc`).\n */\nexport interface EncodedSignal {\n json: () => string | undefined\n frame?: string\n}\n\nexport function encodeSignal(signal: HostSignal): EncodedSignal {\n let json: string | undefined\n let done = false\n return {\n json: () => {\n if (!done) {\n done = true\n try {\n json = JSON.stringify(signal)\n }\n catch {\n json = undefined\n }\n }\n return json\n },\n }\n}\n\n/** One connected client, as the dispatcher sees it. The transport creates it and supplies `send`. */\nexport interface HostPeer {\n /**\n * Delivers one host signal to this client, with its number in its session\n * when it has one (`./signal-log`; the wire carries it as\n * `SIGNAL_SEQ_FIELD`). `encoded` is the same signal already serialized\n * for every peer of the fan-out (absent: serialize it yourself). Must\n * never throw.\n */\n send: (signal: HostSignal, seq?: number, encoded?: EncodedSignal) => void\n /** Set once `ipc.hello` succeeded; only ready peers receive signals. */\n ready: boolean\n /** Session this peer's window is attached to (`presence.watch`). */\n watching: string | null\n /** Browser hosts this peer registered (`browser.registerHost`), released when it drops. */\n browserHosts?: Set<string>\n /** Terminal views attached through this peer: terminal id → client ids. Detached when it drops. */\n terminalViews?: Map<string, Set<string>>\n /** Terminal viewers this peer registered (`terminal.registerViewer`), released when it drops. */\n terminalViewers?: Set<string>\n /** Drafts this peer opened terminals in (`terminal.openInProject`), released to their project when it drops. */\n terminalDrafts?: Set<string>\n /** What authenticated the connection (a zidane-server's token id), for its audit lines. */\n principal?: string\n /**\n * The client scope its token grants (`../scopes`): a call above it is refused. Absent: the\n * connection reaches every method (a local window, the daemon's socket).\n */\n grant?: ClientScope\n /**\n * The protocol version this connection speaks, set by `ipc.hello` (the lower of the client's\n * and the host's, `../daemon/handshake`). A handler that changed shape across versions reads it.\n */\n protocolVersion?: number\n}\n\nexport interface PeerRegistry {\n add: (peer: HostPeer) => void\n /** Whether the peer is still connected (a handler may outlive its peer across an await). */\n has: (peer: HostPeer) => boolean\n /** The peer's connection ended: run every `onClose` cleanup in registration order, then refresh presence. */\n remove: (peer: HostPeer) => void\n /** Release what a peer registered when it drops; runs in registration order. */\n onClose: (cleanup: (peer: HostPeer) => void) => void\n /** Forget every peer WITHOUT per-peer cleanup (the host is shutting down). */\n clear: () => void\n /** Run `stop` once on {@link clear}, when the host shuts down. */\n onClear: (stop: () => void) => void\n size: () => number\n /** Fan a host signal out to every ready peer (terminal output only to its viewers), refreshing presence on the signals that change it. A streaming delta may be held for the rest of this event-loop turn (see the module header). */\n broadcast: (signal: HostSignal) => void\n /** Send the held streaming delta now, if any. */\n flush: () => void\n /**\n * Fan out to every handshaken peer except `origin`. Draft signals use\n * this so a window's own keystrokes never bounce back and fight its\n * cursor — echo-safety by construction, no client-side dedupe.\n */\n broadcastExcept: (origin: HostPeer | null, signal: HostSignal) => void\n computePresence: () => SessionPresence[]\n broadcastPresence: () => void\n /**\n * Late-bound: the broadcast sink exists before the host (the environment\n * the host is built on needs it), and presence reads the host only once a\n * signal arrives.\n */\n bindHost: (host: PresenceSource) => void\n}\n\ntype PresenceSource = Pick<ChatHost, 'approvals' | 'interactions' | 'listLiveSessions'>\n\nexport interface PeerRegistryOptions {\n /** Numbers a signal on its way to every peer (`SignalLog.record`); `json` serializes it (once, shared with the peers). */\n sequence?: (signal: HostSignal, json: () => string | undefined) => number | undefined\n}\n\n/** The fields a delta event may carry and still be coalesced. */\nconst DELTA_FIELDS: ReadonlySet<string> = new Set(['kind', 'text', 'streaming', 'turnId', 'childId', 'depth'])\n\ntype DeltaSignal = Extract<HostSignal, { kind: 'event' }>\n\n/**\n * What a streaming delta coalesces under (session, kind, owner, depth,\n * turn), or `null` when the signal is not a plain delta. Two consecutive\n * deltas with the same key give the client reducers (`appendMarkdownDelta`,\n * `appendThinkingLines` in `src/chat/streaming-pure.ts`) the same rows as\n * one delta with both texts: markdown appends the text, thinking splits it\n * on `\\n` into the owner's last row and new rows after it.\n */\nfunction deltaKey(signal: HostSignal): string | null {\n if (signal.kind !== 'event')\n return null\n const event = signal.event as { kind: string, text?: unknown, streaming?: unknown, turnId?: unknown, childId?: unknown, depth?: unknown }\n if (event.kind === 'markdown' ? event.streaming !== true : event.kind !== 'thinking')\n return null\n if (typeof event.text !== 'string')\n return null\n for (const key in signal) {\n if (key !== 'kind' && key !== 'sessionId' && key !== 'event')\n return null\n }\n for (const key in event) {\n if (!DELTA_FIELDS.has(key))\n return null\n }\n return JSON.stringify([signal.sessionId, event.kind, event.streaming ?? null, event.childId ?? null, event.depth ?? null, event.turnId ?? null])\n}\n\nexport function createPeerRegistry(options: PeerRegistryOptions = {}): PeerRegistry {\n const peers = new Set<HostPeer>()\n let boundHost: PresenceSource | null = null\n const closeCleanups: Array<(peer: HostPeer) => void> = []\n const clearListeners: Array<() => void> = []\n\n /** Sessions with a run in flight, tracked from the run signals themselves. */\n const runningSessions = new Set<string>()\n\n /** The held delta: one slot, so deltas of different owners never change order. */\n let held: { key: string, signal: DeltaSignal, copied: boolean } | null = null\n let flushArmed = false\n\n const flush = (): void => {\n const pending = held\n if (!pending)\n return\n held = null\n emit(pending.signal)\n }\n\n const broadcast = (signal: HostSignal): void => {\n const key = deltaKey(signal)\n if (key !== null && held?.key === key) {\n const delta = signal as DeltaSignal\n if (!held.copied) {\n // The caller's object stays as it was.\n held.signal = { ...held.signal, event: { ...held.signal.event } }\n held.copied = true\n }\n const event = held.signal.event as { text: string }\n event.text += (delta.event as { text: string }).text\n return\n }\n flush()\n if (key === null) {\n emit(signal)\n return\n }\n held = { key, signal: signal as DeltaSignal, copied: false }\n if (!flushArmed) {\n flushArmed = true\n setImmediate(() => {\n flushArmed = false\n flush()\n })\n }\n }\n\n function emit(signal: HostSignal): void {\n // Terminal output only goes where the terminal is shown.\n if (signal.kind === 'terminal:output' || signal.kind === 'terminal:reset') {\n const encoded = encodeSignal(signal)\n for (const peer of peers) {\n if (peer.ready && peer.terminalViews?.has(signal.terminalId))\n peer.send(signal, undefined, encoded)\n }\n return\n }\n // Numbered only here: what every peer gets is what a reattaching one can be replayed.\n fanOut(null, signal, true)\n /*\n * Presence piggybacks on the signals that change it — run state and\n * HITL queues — so the snapshot stays fresh without instrumenting the\n * host. `presence:changed` itself is emitted via `broadcastExcept`\n * directly, so this cannot recurse.\n */\n switch (signal.kind) {\n case 'run:start':\n // Signal-tracked rather than read off `agent.isRunning`: the host\n // broadcasts `run:start` BEFORE invoking `agent.run()`, so the\n // flag lags the signal by a tick.\n runningSessions.add(signal.sessionId)\n broadcastPresence()\n break\n case 'run:end':\n runningSessions.delete(signal.sessionId)\n broadcastPresence()\n break\n case 'approval:request':\n case 'approval:resolved':\n case 'interaction:request':\n case 'interaction:resolved':\n broadcastPresence()\n break\n default:\n break\n }\n }\n\n /** Serialized once here, for the log and every peer. */\n function fanOut(origin: HostPeer | null, signal: HostSignal, numbered: boolean): void {\n const encoded = encodeSignal(signal)\n const seq = numbered ? options.sequence?.(signal, encoded.json) : undefined\n for (const peer of peers) {\n if (!peer.ready || peer === origin)\n continue\n peer.send(signal, seq, encoded)\n }\n }\n\n function broadcastExcept(origin: HostPeer | null, signal: HostSignal): void {\n flush()\n fanOut(origin, signal, false)\n }\n\n /**\n * Live presence: which sessions have attached windows, and their\n * run / awaiting-input state. Union of watched, live-agent, and\n * pending-HITL sessions — small by construction.\n */\n function computePresence(): SessionPresence[] {\n const host = boundHost\n if (!host)\n throw new Error('Presence read before the host was bound.')\n const windowCounts = new Map<string, number>()\n for (const peer of peers) {\n if (peer.ready && peer.watching)\n windowCounts.set(peer.watching, (windowCounts.get(peer.watching) ?? 0) + 1)\n }\n\n const attention = new Set<string>()\n for (const request of host.approvals.listPending())\n attention.add(request.sessionId)\n for (const pending of host.interactions.list())\n attention.add(pending.sessionId)\n\n // Union of signal-tracked runs (fresh) and the agent flag (covers a\n // window attaching to a daemon whose run started before it connected).\n const live = new Map(host.listLiveSessions().map(entry => [entry.sessionId, entry.running]))\n\n const ids = new Set<string>([...windowCounts.keys(), ...attention, ...live.keys(), ...runningSessions])\n return [...ids].map(sessionId => ({\n sessionId,\n windows: windowCounts.get(sessionId) ?? 0,\n running: runningSessions.has(sessionId) || live.get(sessionId) === true,\n attention: attention.has(sessionId),\n }))\n }\n\n function broadcastPresence(): void {\n broadcastExcept(null, { kind: 'presence:changed', sessions: computePresence() })\n }\n\n return {\n add(peer) {\n flush()\n peers.add(peer)\n },\n has: peer => peers.has(peer),\n remove(peer) {\n flush()\n if (!peers.delete(peer))\n return\n for (const cleanup of closeCleanups)\n cleanup(peer)\n // The window detached: its session may have left the \"active\" set.\n if (peer.watching)\n broadcastPresence()\n },\n onClose(cleanup) {\n closeCleanups.push(cleanup)\n },\n clear() {\n flush()\n peers.clear()\n for (const stop of clearListeners.splice(0))\n stop()\n },\n onClear(stop) {\n clearListeners.push(stop)\n },\n size: () => peers.size,\n broadcast,\n flush,\n broadcastExcept,\n computePresence,\n broadcastPresence,\n bindHost(host) {\n boundHost = host\n },\n }\n}\n","/**\n * What each authenticated principal (a zidane-server token id) set going on\n * this host: the sessions it drove (prompts, queued and steered messages,\n * orchestration) and the terminals it opened. Revoking the token stops them\n * (`stop`): a leaked token's agent runs and shells must not outlive its\n * revocation. A process they left running in the background (`nohup`, a\n * daemonized server) is out of reach: only a restart of the host ends it.\n *\n * A driven session is claimed before its method runs (`claim`), so a\n * revocation landing mid-call (a `chat.send` still provisioning) finds it;\n * the rest is recorded after a method succeeded, from its params or result.\n * Work a revoked principal's call left behind once it resolves is stopped\n * there and then. Stopping is per session, not per run: a session another\n * token also drives has its run in flight interrupted and its whole queue\n * dropped, whichever token started that run or queued those messages (the\n * host does not say who started a run, and a leaked token's run must not\n * survive because another device steered it). Peers without a principal (the unix socket, an auth-less\n * loopback server) record nothing. A deleted session's id stays until its\n * token is revoked or the host restarts: nothing runs there, so `stop`\n * passes over it.\n */\nimport type { ChatHost } from '../../chat/host/engine'\nimport type { HostPeer } from './peers'\n\n/** Methods that drive a session's agent: `params.sessionId` names the session. */\nconst DRIVING: ReadonlySet<string> = new Set([\n 'chat.send',\n 'chat.pushQueued',\n 'chat.steer',\n 'chat.followUp',\n 'queue.add',\n 'queue.pushNow',\n 'orchestration.send',\n 'orchestration.steer',\n])\n\n/** What `stop` ended: sessions whose run or background work it stopped, terminals it closed. */\nexport interface StoppedWork {\n runs: number\n terminals: number\n}\n\nexport interface PrincipalWork {\n /** Run `peer`'s call of `method`, noting the session it drives (before the call) or the terminal it opened (after). Returns the call's result. */\n track: (method: string, params: unknown, peer: HostPeer, call: () => unknown) => Promise<unknown>\n /** Drop the queued messages, interrupt the runs, cancel the background work and close the terminals `principal` started, then forget it. */\n stop: (principal: string) => Promise<StoppedWork>\n}\n\ntype WorkHost = Pick<ChatHost, 'isSessionRunning' | 'interrupt' | 'listRunningWork' | 'cancelRunningWork' | 'queueList' | 'queueRemove' | 'terminals'>\n\nexport function createPrincipalWork(host: WorkHost): PrincipalWork {\n const sessions = new Map<string, Set<string>>()\n const terminals = new Map<string, Set<string>>()\n /** Principals already stopped: a call of theirs still in flight is stopped when it resolves. */\n const revoked = new Set<string>()\n\n const add = (map: Map<string, Set<string>>, principal: string, id: string): void => {\n let ids = map.get(principal)\n if (!ids)\n map.set(principal, ids = new Set())\n ids.add(id)\n }\n\n const forgetTerminal = (terminalId: string): void => {\n for (const ids of terminals.values())\n ids.delete(terminalId)\n }\n\n /**\n * Drop the session's queue first: an interrupted run's end drains it, and\n * the next entry would start a fresh run. The whole queue goes, whoever\n * queued each entry: the wire does not say which entries a principal added.\n * Likewise the run in flight is interrupted whoever started it.\n * Returns whether a run, queued messages or background work were stopped.\n */\n const stopSession = async (sessionId: string): Promise<boolean> => {\n const queued = host.queueList(sessionId)\n for (const item of queued)\n host.queueRemove(sessionId, item.id)\n const running = host.isSessionRunning(sessionId)\n const background = host.listRunningWork(sessionId).length > 0\n if (running)\n host.interrupt(sessionId)\n if (background)\n await host.cancelRunningWork(sessionId, 'all', 'The token that started it was revoked.').catch(() => false)\n return running || background || queued.length > 0\n }\n\n const closeTerminal = async (terminalId: string): Promise<boolean> => {\n try {\n await host.terminals.close(terminalId)\n return true\n }\n catch {\n // Already gone, or its shell would not die: the others still close.\n return false\n }\n }\n\n /** Before the call: a revocation landing while it runs (a `chat.send` still provisioning) finds the session. */\n const claim = (method: string, params: unknown, peer: HostPeer): void => {\n const principal = peer.principal\n const sessionId = (params as { sessionId?: unknown } | null)?.sessionId\n if (principal !== undefined && !revoked.has(principal) && DRIVING.has(method) && typeof sessionId === 'string')\n add(sessions, principal, sessionId)\n }\n\n /** After the call succeeded; a principal revoked meanwhile has what it left behind stopped now. */\n const record = (method: string, params: unknown, result: unknown, peer: HostPeer): void => {\n const principal = peer.principal\n if (principal === undefined)\n return\n const p = (params ?? {}) as { sessionId?: unknown, terminalId?: unknown }\n const opened = (result as { id?: unknown } | null)?.id\n const late = revoked.has(principal)\n if (DRIVING.has(method) && typeof p.sessionId === 'string') {\n if (late)\n void stopSession(p.sessionId).catch(() => false)\n else\n add(sessions, principal, p.sessionId)\n }\n else if (method === 'orchestration.createWorker' && typeof result === 'string') {\n if (late)\n void stopSession(result).catch(() => false)\n else\n add(sessions, principal, result)\n }\n else if (method === 'terminal.open' && typeof opened === 'string') {\n if (late)\n void closeTerminal(opened)\n else\n add(terminals, principal, opened)\n }\n else if (method === 'terminal.close' && typeof p.terminalId === 'string') {\n forgetTerminal(p.terminalId)\n }\n }\n\n return {\n async track(method, params, peer, call) {\n claim(method, params, peer)\n const result = await call()\n record(method, params, result, peer)\n return result\n },\n\n async stop(principal) {\n revoked.add(principal)\n const driven = sessions.get(principal) ?? new Set<string>()\n const opened = terminals.get(principal) ?? new Set<string>()\n sessions.delete(principal)\n terminals.delete(principal)\n let runs = 0\n for (const sessionId of driven) {\n if (await stopSession(sessionId))\n runs++\n }\n let closed = 0\n for (const terminalId of opened) {\n if (await closeTerminal(terminalId))\n closed++\n }\n return { runs, terminals: closed }\n },\n }\n}\n","/**\n * Per-session signal numbering and the bounded replay log behind\n * `sessions.resume`.\n *\n * Every session-scoped signal the host fans out to all peers gets the next\n * number of its session (from 1), and the last ones are kept as JSON, so a\n * client that dropped and reattached can be sent exactly what it missed\n * instead of reloading the whole transcript. Signals with no session, and\n * the origin-excluded or viewer-only ones that never go through the full\n * fan-out (drafts, search, suggestions, terminal output), are not numbered.\n *\n * Bounds: per session the last `maxSignals` signals and at most `maxBytes`\n * of them; across sessions `maxTotalBytes`, past which the least recently\n * written session loses its log. Sizes are UTF-8 bytes of the JSON plus\n * {@link ENTRY_OVERHEAD_BYTES} per entry. The bytes are the real bound: a\n * streamed reply is many small signals, and a count bound low enough to bind\n * first would cover less than the time a client needs to notice a dropped\n * connection and come back (`maxSignals` is only a backstop). A\n * position the log no longer covers (or that is not a non-negative integer)\n * is a gap: the client falls back to `sessions.loadEvents`.\n *\n * Numbering survives eviction and `forget`, so a stale position can never\n * pass for a fresh one. A forgotten session keeps only its next number, in\n * a map bounded by `maxForgotten` (least recently forgotten go first); an\n * evicted counter raises a floor every new log starts from, so a number is\n * never given out twice in one epoch, at the cost of new sessions'\n * numbering not starting at 1 once that happened.\n *\n * `epoch` names this log: numbers mean nothing to another host process.\n */\nimport type { HostSignal, SequencedSignal } from '../protocol'\nimport { Buffer } from 'node:buffer'\nimport { randomUUID } from 'node:crypto'\n\n/** What one kept entry costs beyond its JSON (the entry object, its slot), counted against the byte bounds. */\nexport const ENTRY_OVERHEAD_BYTES = 64\n\nexport interface SignalLogOptions {\n /** Default 100 000: past the byte bounds for any realistic signal size. */\n maxSignals?: number\n /** Default 4 MiB. */\n maxBytes?: number\n /** Default 32 MiB. */\n maxTotalBytes?: number\n /** Forgotten sessions whose counters are kept. Default 10 000. */\n maxForgotten?: number\n}\n\nexport interface SignalLog {\n readonly epoch: string\n /**\n * The signal's number in its session, or `undefined` when it is not\n * session-scoped. `serialize` gives its JSON (`undefined`: it cannot be\n * encoded), so a caller that encodes it anyway does it once; default\n * `JSON.stringify`.\n */\n record: (signal: HostSignal, serialize?: () => string | undefined) => number | undefined\n /** Every signal of `sessionId` after `afterSeq`, in order; `null` when the log does not cover them all. */\n replay: (sessionId: string, afterSeq: number) => SequencedSignal[] | null\n /** The session is gone: drop its log (its numbering stays). */\n forget: (sessionId: string) => void\n /** Sessions tracked (live logs and forgotten counters): bounded by `maxForgotten` plus live sessions. */\n sessionCount: () => number\n}\n\ninterface Entry {\n seq: number\n json: string\n bytes: number\n}\n\ninterface SessionLog {\n /** Number the next signal gets. */\n next: number\n entries: Entry[]\n /** Index of the oldest kept entry. */\n head: number\n bytes: number\n}\n\nfunction stringify(signal: HostSignal): string | undefined {\n try {\n return JSON.stringify(signal)\n }\n catch {\n return undefined\n }\n}\n\nfunction sessionOf(signal: HostSignal): string | undefined {\n const id = (signal as { sessionId?: unknown }).sessionId\n return typeof id === 'string' ? id : undefined\n}\n\nexport function createSignalLog(options: SignalLogOptions = {}): SignalLog {\n const maxSignals = options.maxSignals ?? 100_000\n const maxBytes = options.maxBytes ?? 4 * 1024 * 1024\n const maxTotalBytes = options.maxTotalBytes ?? 32 * 1024 * 1024\n const maxForgotten = options.maxForgotten ?? 10_000\n const epoch = randomUUID()\n /** Insertion order = least recently written first. */\n const logs = new Map<string, SessionLog>()\n /** Next number of forgotten sessions; insertion order = least recently forgotten first. */\n const forgotten = new Map<string, number>()\n /** Every number below this may have been given out by a session whose counter is gone. */\n let floor = 1\n let totalBytes = 0\n\n const dropOldest = (log: SessionLog): void => {\n totalBytes -= log.entries[log.head]!.bytes\n log.bytes -= log.entries[log.head]!.bytes\n log.head++\n if (log.head > 1024 && log.head * 2 > log.entries.length) {\n log.entries = log.entries.slice(log.head)\n log.head = 0\n }\n }\n\n const clear = (log: SessionLog): void => {\n totalBytes -= log.bytes\n log.entries = []\n log.head = 0\n log.bytes = 0\n }\n\n return {\n epoch,\n record(signal, serialize = () => stringify(signal)) {\n const sessionId = sessionOf(signal)\n if (sessionId === undefined)\n return undefined\n let log = logs.get(sessionId)\n if (log) {\n logs.delete(sessionId)\n }\n else {\n log = { next: forgotten.get(sessionId) ?? floor, entries: [], head: 0, bytes: 0 }\n forgotten.delete(sessionId)\n }\n logs.set(sessionId, log)\n\n const seq = log.next++\n const json = serialize()\n if (json === undefined) {\n // Not JSON-able, so no peer can receive it either: a hole the log cannot replay.\n clear(log)\n return seq\n }\n const bytes = Buffer.byteLength(json) + ENTRY_OVERHEAD_BYTES\n log.entries.push({ seq, json, bytes })\n log.bytes += bytes\n totalBytes += bytes\n while (log.entries.length - log.head > maxSignals || (log.bytes > maxBytes && log.entries.length - log.head > 0))\n dropOldest(log)\n for (const [id, other] of logs) {\n if (totalBytes <= maxTotalBytes || id === sessionId)\n break\n clear(other)\n }\n return seq\n },\n replay(sessionId, afterSeq) {\n const log = logs.get(sessionId)\n if (!log || !Number.isSafeInteger(afterSeq) || afterSeq < 0)\n return null\n const last = log.next - 1\n if (afterSeq > last || afterSeq < 0)\n return null\n if (afterSeq === last)\n return []\n const first = log.entries[log.head]?.seq\n if (first === undefined || first > afterSeq + 1)\n return null\n const out: SequencedSignal[] = []\n for (let i = log.head; i < log.entries.length; i++) {\n const entry = log.entries[i]!\n if (entry.seq > afterSeq)\n out.push({ seq: entry.seq, signal: JSON.parse(entry.json) as HostSignal })\n }\n return out\n },\n forget(sessionId) {\n const log = logs.get(sessionId)\n if (!log)\n return\n clear(log)\n logs.delete(sessionId)\n forgotten.set(sessionId, log.next)\n while (forgotten.size > maxForgotten) {\n const [oldest, next] = forgotten.entries().next().value!\n forgotten.delete(oldest)\n floor = Math.max(floor, next)\n }\n },\n sessionCount: () => logs.size + forgotten.size,\n }\n}\n","import type { WorkspaceConfinement } from '../../chat/workspace-confinement'\nimport type { FsDirEntry, FsDirListing, FsDirSearch, FsRoots } from '../protocol'\n/**\n * The folders a host lets sessions use, as `fs.*` lists them: the host's own\n * confinement (`ChatHost.workspace`, `src/chat/workspace-confinement.ts`,\n * which the host enforces at its entry points), plus the folder listing,\n * folder creation and folder search, each kept inside the roots. A\n * server is confined to its workspace roots; a local host is not, and its\n * listing root is the user's home, like the window's own folder picker.\n */\nimport { existsSync, mkdirSync, readdirSync, realpathSync, statSync } from 'node:fs'\nimport { readdir } from 'node:fs/promises'\nimport { dirname, join } from 'node:path'\nimport { isInside } from '../../chat/workspace-confinement'\n\n/** Most folders one listing returns. */\nconst MAX_DIR_ENTRIES = 2000\n\n/** How deep a folder search goes below where it starts. */\nexport const SEARCH_MAX_DEPTH = 4\n/** Most folders one search returns. */\nexport const SEARCH_MAX_RESULTS = 200\n/** Most folders one search reads, so a huge tree answers in bounded time. */\nconst SEARCH_MAX_READS = 5000\n/** Folders a search never enters: dependency trees, not projects. */\nconst SEARCH_SKIP = new Set(['node_modules'])\n\n/** A folder name a client may create: one path segment, not hidden, no control characters. */\nfunction checkFolderName(name: string): string {\n const trimmed = name.trim()\n if (!trimmed)\n throw new Error('A folder name is required.')\n if (trimmed.length > 255)\n throw new Error('That folder name is too long.')\n // eslint-disable-next-line no-control-regex -- refusing control characters is the point\n if (/[/\\\\\\u0000-\\u001F]/.test(trimmed))\n throw new Error('A folder name cannot hold \"/\", \"\\\\\" or control characters.')\n if (trimmed.startsWith('.'))\n throw new Error('A folder name cannot start with a dot.')\n return trimmed\n}\n\n/** Exact name first, then a name that starts with the query, then the rest; shallow before deep. */\nfunction searchRank(entry: FsDirEntry, query: string, depth: number): number {\n const name = entry.name.toLowerCase()\n const kind = name === query ? 0 : name.startsWith(query) ? 1 : 2\n return kind * 100 + depth\n}\n\nexport interface WorkspaceRoots {\n describe: () => FsRoots\n /** The real path of `path` when it is a folder inside the roots; throws otherwise. */\n resolveFolder: (path: string) => string\n /** A new session's folder: `cwd` checked when confined, the first root when confined and empty. */\n sessionFolder: (cwd: string) => string\n /** A folder a running session moves to (`setFolder`, launch override): checked when confined; `''` passes. */\n checkFolder: (cwd: string) => string\n list: (path?: string) => FsDirListing\n /** Creates folder `name` in `parent` (inside the roots); throws when it exists or the name is not one plain segment. */\n mkdir: (parent: string, name: string) => FsDirEntry\n /** The folders whose name holds `query`, in `path` (default: every root) and below, within the search bounds. */\n search: (query: string, path?: string) => Promise<FsDirSearch>\n}\n\nexport function createWorkspaceRoots(confinement: WorkspaceConfinement): WorkspaceRoots {\n const { confined, roots, resolveFolder } = confinement\n return {\n describe: () => ({ roots: [...roots], confined }),\n resolveFolder,\n checkFolder: confinement.checkFolder,\n sessionFolder: confinement.sessionFolder,\n list(path) {\n const dir = resolveFolder(path ?? roots[0]!)\n const entries: FsDirEntry[] = []\n let truncated = false\n const names = readdirSync(dir, { withFileTypes: true })\n .filter(e => !e.name.startsWith('.') && (e.isDirectory() || e.isSymbolicLink()))\n .map(e => e.name)\n .sort((a, b) => a.localeCompare(b))\n for (const name of names) {\n let real: string\n try {\n // Canonical, as the confinement's roots are (`../../chat/workspace-confinement`).\n real = realpathSync.native(join(dir, name))\n if (!statSync(real).isDirectory())\n continue\n }\n catch {\n continue\n }\n // A symlink out of the roots is not offered (it would be refused anyway).\n if (!roots.some(root => isInside(root, real)))\n continue\n if (entries.length >= MAX_DIR_ENTRIES) {\n truncated = true\n break\n }\n entries.push({ name, path: real, isGitRepo: existsSync(join(real, '.git')) })\n }\n const atRoot = roots.includes(dir)\n return { roots: [...roots], path: dir, parent: atRoot ? null : dirname(dir), entries, ...(truncated ? { truncated } : {}) }\n },\n mkdir(parent, name) {\n const dir = resolveFolder(parent)\n const folder = checkFolderName(name)\n const target = join(dir, folder)\n try {\n mkdirSync(target)\n }\n catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'EEXIST')\n throw new Error(`${folder} already exists in ${dir}.`)\n throw err\n }\n return { name: folder, path: realpathSync.native(target), isGitRepo: false }\n },\n async search(query, path) {\n const needle = query.trim().toLowerCase()\n if (!needle)\n return { results: [] }\n const starts = path === undefined ? [...roots] : [resolveFolder(path)]\n const found: { entry: FsDirEntry, depth: number }[] = []\n const seen = new Set<string>()\n let reads = 0\n let truncated = false\n // Breadth first: a shallow match is found before the bounds cut a deep one.\n let level = starts.map(dir => ({ dir, depth: 0 }))\n while (level.length > 0) {\n const next: typeof level = []\n for (const { dir, depth } of level) {\n if (reads >= SEARCH_MAX_READS) {\n truncated = true\n break\n }\n reads++\n let dirents\n try {\n dirents = await readdir(dir, { withFileTypes: true })\n }\n catch {\n continue\n }\n // Symlinks are not followed: no loops, no way out of the roots.\n for (const dirent of dirents) {\n if (!dirent.isDirectory() || dirent.name.startsWith('.') || SEARCH_SKIP.has(dirent.name))\n continue\n const child = join(dir, dirent.name)\n if (seen.has(child))\n continue\n seen.add(child)\n if (dirent.name.toLowerCase().includes(needle))\n found.push({ entry: { name: dirent.name, path: child, isGitRepo: existsSync(join(child, '.git')) }, depth })\n if (depth + 1 < SEARCH_MAX_DEPTH)\n next.push({ dir: child, depth: depth + 1 })\n }\n }\n if (reads >= SEARCH_MAX_READS) {\n if (next.length > 0)\n truncated = true\n break\n }\n level = next\n }\n found.sort((a, b) => searchRank(a.entry, needle, a.depth) - searchRank(b.entry, needle, b.depth) || a.entry.path.localeCompare(b.entry.path))\n if (found.length > SEARCH_MAX_RESULTS)\n truncated = true\n const results = found.slice(0, SEARCH_MAX_RESULTS).map(f => f.entry)\n return { results, ...(truncated ? { truncated } : {}) }\n },\n }\n}\n","/**\n * Transport-free JSON-RPC dispatch around a `ChatHost`.\n *\n * Owns everything a host connection needs that is NOT the wire: the typed\n * method table, per-peer state (presence, terminal views, browser hosts,\n * terminal viewers), signal fan-out, the shared draft / search / suggest\n * state, and the `ipc.hello` handshake. A transport (the unix-socket server\n * in `server.ts`, the WebSocket server in `../transports/ws-server.ts`, the\n * in-memory one in `../memory.ts`) only frames messages and hands each\n * connection over as a {@link HostPeer} whose `send` delivers signals.\n *\n * Lifecycle that belongs to the process (draining, retiring once idle) stays\n * with the transport and reaches in through {@link DispatcherLifecycle}.\n *\n * This module is the composition root: peers and fan-out live in\n * `./peers`, each feature's methods (and the per-session or per-peer state\n * only they touch) in `./handlers/<feature>`.\n */\nimport type { ChatHost } from '../../chat/host/engine'\nimport type { RingBufferSink } from '../../logger'\nimport type { HelloParams, HelloResult, HostKind, HostSignal, IpcMethodName } from '../protocol'\nimport type { ClientScope } from '../scopes'\nimport type { DaemonEnvironment } from './environment'\nimport type { RemoteInstallsOptions } from './handlers/catalog-install'\nimport type { MediaTicketRegistry } from './handlers/files'\nimport type { MachineLinksHandlerOptions } from './handlers/machine-links'\nimport type { MachineServeOptions } from './handlers/machine-serve'\nimport type { ServerTokensControl, ServerUpdateControl } from './handlers/server'\nimport type { SyncOptions } from './handlers/sync'\nimport type { MethodTable } from './handlers/types'\nimport type { HostIdentityOptions } from './identity'\nimport type { HostPeer } from './peers'\nimport type { StoppedWork } from './principal-work'\nimport type { SignalLogOptions } from './signal-log'\nimport { dirname } from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { AcpErrorCode } from '../../acp/types'\nimport { createChatHost } from '../../chat/host/engine'\nimport { createFileMcpCredentialStore } from '../../chat/mcp-credentials'\nimport { createMcpStatusTracker } from '../../chat/mcp-status'\nimport { SYNC_CATEGORIES } from '../../chat/sync/types'\nimport { ZIDANE_VERSION } from '../../version'\nimport { createHostTranscriptPager } from '../history/index'\nimport { IPC_MIN_PROTOCOL_VERSION, IPC_PROTOCOL_VERSION, IpcErrorCode, MachineErrorCode, PING_METHOD } from '../protocol'\nimport { METHOD_SCOPES, methodScope, scopeAllows } from '../scopes'\nimport { createDaemonEnvironment } from './environment'\nimport { createArtifactHandlers } from './handlers/artifacts'\nimport { createAuthHandlers, createProviderAuth } from './handlers/auth'\nimport { createBrowserHandlers } from './handlers/browser'\nimport { createCatalogInstallHandlers, remoteInstallsAllowed } from './handlers/catalog-install'\nimport { createCatalogHandlers } from './handlers/catalogs'\nimport { createChatHandlers } from './handlers/chat'\nimport { createClientStateHandlers } from './handlers/client-state'\nimport { createContextHandlers } from './handlers/context'\nimport { createDaemonHandlers } from './handlers/daemon'\nimport { createDraftHandlers } from './handlers/drafts'\nimport { createEnvironmentHandlers } from './handlers/environments'\nimport { createExtensionUiHandlers } from './handlers/extension-ui'\nimport { createExtensionHandlers } from './handlers/extensions'\nimport { createFilesHandlers } from './handlers/files'\nimport { createFsHandlers } from './handlers/fs'\nimport { createGitHandlers } from './handlers/git'\nimport { createHistoryHandlers } from './handlers/history'\nimport { createHitlHandlers } from './handlers/hitl'\nimport { createLaunchOverrideHandlers } from './handlers/launch-overrides'\nimport { createMachineLinkHandlers } from './handlers/machine-links'\nimport { createMachineServeHandlers } from './handlers/machine-serve'\nimport { createMachineHandlers } from './handlers/machines'\nimport { createOAuthFlowHandlers } from './handlers/oauth-flows'\nimport { createOnboardingHandlers } from './handlers/onboarding'\nimport { createOrchestrationHandlers } from './handlers/orchestration'\nimport { createPanelHandlers } from './handlers/panels'\nimport { checkParams, InvalidParamsError } from './handlers/params'\nimport { createPerfHandlers, lazyHostPerf } from './handlers/perf'\nimport { createPresenceHandlers } from './handlers/presence'\nimport { createQueueHandlers } from './handlers/queue'\nimport { createResumeHandlers } from './handlers/resume'\nimport { createServerHandlers } from './handlers/server'\nimport { createSessionReadHandlers } from './handlers/session-reads'\nimport { createSessionHandlers } from './handlers/sessions'\nimport { createSettingsHandlers } from './handlers/settings'\nimport { createSuggestHandlers } from './handlers/suggest'\nimport { createSyncHandlers, withSyncOverrides } from './handlers/sync'\nimport { createTerminalHandlers } from './handlers/terminal'\nimport { createTitleHandlers } from './handlers/titles'\nimport { createTodoHandlers } from './handlers/todos'\nimport { createTranscriptHandlers } from './handlers/transcript'\nimport { createUsageHandlers } from './handlers/usage'\nimport { createWorkspaceHandlers } from './handlers/workspace'\nimport { createWorkspaceExecStreamHandlers } from './handlers/workspace-exec-stream'\nimport { evaluateHello } from './handshake'\nimport { resolveHostIdentity } from './identity'\nimport { IPC_BUILD_ID } from './lifecycle'\nimport { createPeerRegistry } from './peers'\nimport { createPrincipalWork } from './principal-work'\nimport { sendDedupFor } from './send-requests'\nimport { createSignalLog } from './signal-log'\nimport { createWorkspaceRoots } from './workspace-roots'\n\n/** Codes a machine error keeps over the wire (`MachineErrorCode`). */\nconst MACHINE_ERROR_CODES: ReadonlySet<number> = new Set(Object.values(MachineErrorCode))\n/** Terminals without a session: only hosts that advertise `HelloResult.projectTerminals` answer them. */\nconst PROJECT_TERMINAL_METHODS: ReadonlySet<string> = new Set(['terminal.projectState', 'terminal.openInProject', 'terminal.adopt', 'terminal.releaseDraft'])\n\nexport type { HostPeer } from './peers'\n\n/** Process lifecycle the transport owns; the dispatcher only asks for it. */\nexport interface DispatcherLifecycle {\n /** `daemon.shutdown`: drain and exit once the reply is out. */\n shutdown: () => void\n /** A newer client found this host mid-work: keep serving, exit at the first idle point. */\n retireWhenIdle: () => void\n isRetiring: () => boolean\n}\n\nexport interface HostDispatcherOptions {\n /**\n * Environment factory: the production daemon uses the disk-backed\n * `createDaemonEnvironment`; tests inject an in-memory one. Receives the\n * broadcast sink wired to peer fan-out.\n */\n createEnvironment?: (broadcast: (signal: HostSignal) => void) => DaemonEnvironment | Promise<DaemonEnvironment>\n appVersion: string\n startedAt: number\n lifecycle: DispatcherLifecycle\n /**\n * What this host reports itself as in `ipc.hello` / `daemon.info`; the id\n * comes from the environment's data dir. Default: a `daemon` named after\n * the machine.\n */\n identity?: HostIdentityOptions\n /** Bounds of the per-session replay log `sessions.resume` reads (`./signal-log`). */\n replay?: SignalLogOptions\n /**\n * Lend this host as a machine to its clients' hosts (`machine.attach`,\n * `docs/MACHINES.md` § Reverse direction). A zidane-server's\n * `allowAsMachine`; absent: refused.\n */\n machineServe?: MachineServeOptions\n /** Its token store, for clients (`tokens.*`): a zidane-server's. Absent: refused. */\n tokens?: ServerTokensControl\n /** The tickets its media are served under (`files.mediaTicket`): a zidane-server's. Absent: refused. */\n media?: MediaTicketRegistry\n /** A zidane-server's self-update (`server.update.*`); read per call, set once it started. */\n update?: () => ServerUpdateControl | null\n /** Pacing of this host's machine links (tests shrink it). */\n machineLinks?: MachineLinksHandlerOptions['pacing']\n /** How long an `auth.oauth.*` sign-in waits for its code. Default 10 minutes. */\n oauthFlowTtlMs?: number\n /** It serves `SERVER_OAUTH_CALLBACK_PATH` (a zidane-server, `deliverOAuthCallback`): a browser client's MCP sign-in may come back there. */\n oauthCallback?: boolean\n /** Its log buffer, for clients (`logs.*`): a zidane-server's. Absent: refused. */\n logs?: RingBufferSink\n /**\n * Installs and removals from clients (`catalog.install` / `remove` /\n * `update`, `mcp.upsert` / `remove`): a zidane-server's `allowRemoteInstalls`\n * and its audit log. Absent: refused.\n */\n remoteInstalls?: RemoteInstallsOptions\n /**\n * Settings sync from a client's computer (`sync.*`): a zidane-server's\n * sync record and audit. Absent: refused.\n */\n sync?: SyncOptions\n /**\n * Workspace writes from clients: cloning (`git.clone`) and creating\n * folders (`fs.mkdir`) in the workspace roots. A zidane-server's\n * `allowClone` and `allowCreateFolders`. Absent: both allowed (the user's\n * own computer).\n */\n workspaceWrites?: WorkspaceWritesOptions\n /**\n * A call refused because the connection's token doesn't reach the method\n * (`../scopes`): a zidane-server writes it to its audit log.\n */\n onForbidden?: (peer: HostPeer, method: string, required: ClientScope) => void\n /**\n * Leave resuming the runs a dead process left to {@link HostDispatcher.resumeAfterRestart}:\n * a host that starts channels calls it once they are connected, so a\n * resumed run's events reach their conversation. Absent: resumed at once.\n */\n deferResume?: boolean\n}\n\n/** Which workspace writes a host takes from its clients, read per call. */\nexport interface WorkspaceWritesOptions {\n /** `git.clone`. */\n clone: () => boolean\n /** `fs.mkdir`. */\n createFolders: () => boolean\n}\n\n/** The workspace writes a host takes, read per call; both allowed without options (the user's own computer). */\nfunction workspaceWritesOf(options: WorkspaceWritesOptions | undefined) {\n const clone = (): boolean => options?.clone() ?? true\n const createFolders = (): boolean => options?.createFolders() ?? true\n return { clone, createFolders, flags: () => ({ clone: clone(), createFolders: createFolders() }) }\n}\n\n/** What the hello says this host offers its clients. */\nfunction hostOffers(options: HostDispatcherOptions, machineServe: boolean, writes: { clone: boolean, createFolders: boolean }): Partial<HelloResult> {\n return {\n ...(machineServe ? { machineServe: true } : {}),\n ...(remoteInstallsAllowed(options.remoteInstalls) ? { remoteInstalls: true } : {}),\n ...writes,\n ...(options.sync ? { sync: true, syncCategories: [...SYNC_CATEGORIES] } : {}),\n }\n}\n\n/** A request's outcome, ready for the transport to frame as a JSON-RPC response. */\nexport type DispatchOutcome\n = | { ok: true, result: unknown }\n | { ok: false, code: number, message: string, data?: unknown }\n\nexport interface HostDispatcher {\n host: ChatHost\n addPeer: (peer: HostPeer) => void\n /** The peer's connection ended: release what it registered and refresh presence. */\n removePeer: (peer: HostPeer) => void\n /** Forget every peer WITHOUT per-peer cleanup, and stop watching the settings file (the host is shutting down). */\n detachAll: () => void\n peerCount: () => number\n handleRequest: (method: string, params: unknown, peer: HostPeer) => Promise<DispatchOutcome>\n /** Resume the runs a dead process left (a host serving every window); see `HostDispatcherOptions.deferResume`. Only the first call does anything. */\n resumeAfterRestart: () => void\n /** Fire-and-forget: no response, errors swallowed, ignored before the handshake. */\n handleNotification: (method: string, params: unknown, peer: HostPeer) => Promise<void>\n /**\n * A principal's credential was revoked (a zidane-server token): interrupt\n * the runs, cancel the background work and close the terminals its peers\n * started (`./principal-work`).\n */\n stopPrincipalWork: (principal: string) => Promise<StoppedWork>\n /** The browser came back to the server's OAuth callback with this query: the MCP server it signs in to, `undefined` when no sign-in waits for it. */\n deliverOAuthCallback: (query: URLSearchParams) => string | undefined\n}\n\n/**\n * The refusal of a call the peer's token doesn't reach (`../scopes`), reported to `onForbidden`;\n * `undefined` when it may call. A peer without a grant (a local window) reaches everything; a\n * method outside the protocol's scope table needs `admin` (never wider than the table says).\n */\nfunction forbiddenCall(method: string, peer: HostPeer, onForbidden: HostDispatcherOptions['onForbidden']): DispatchOutcome | undefined {\n if (!peer.grant)\n return undefined\n const required = methodScope(method) ?? 'admin'\n if (scopeAllows(peer.grant, required))\n return undefined\n onForbidden?.(peer, method, required)\n return {\n ok: false,\n code: IpcErrorCode.Forbidden,\n message: `\"${method}\" needs ${required === 'chat' ? 'a' : 'an'} ${required} token; this connection's token is ${peer.grant}.`,\n data: { required, granted: peer.grant },\n }\n}\n\n/**\n * A connection's terms, set on the peer and reported by `ipc.hello`: the protocol version it\n * speaks, its token's scope (absent for a local window) and the methods this host handles\n * within it.\n */\nfunction connectionTerms(peer: HostPeer, negotiated: number, handled: (method: string) => boolean): Pick<HelloResult, 'minProtocolVersion' | 'negotiatedProtocolVersion' | 'scope' | 'methods'> {\n peer.protocolVersion = negotiated\n const methods = (Object.keys(METHOD_SCOPES) as IpcMethodName[])\n .filter(method => handled(method) && (!peer.grant || scopeAllows(peer.grant, METHOD_SCOPES[method])))\n return { minProtocolVersion: IPC_MIN_PROTOCOL_VERSION, negotiatedProtocolVersion: negotiated, ...(peer.grant ? { scope: peer.grant } : {}), methods }\n}\n\n/** Where this module (and, bundled, its sibling chunks) lives. */\nconst OWN_DIR = dirname(fileURLToPath(import.meta.url))\n\n/**\n * A lazy import of this process's own code failed: the files it was started\n * from were replaced on disk (a rebuild, an upgrade) while it ran.\n */\nexport function isReplacedBuildError(err: unknown): boolean {\n const message = err instanceof Error ? err.message : ''\n const missing = /^Cannot find module '([^']+)'/.exec(message)?.[1]\n // A relative chunk (Bun) or a file next to this one (Node resolves the path); a package an extension lacks is not ours.\n return missing !== undefined && (/^\\.{1,2}\\//.test(missing) || missing.startsWith(`${OWN_DIR}/`))\n}\n\nexport const REPLACED_BUILD_MESSAGE = 'zidane was rebuilt or upgraded while its background service ran. The service restarts once no run is active. To restart it now, quit zidane everywhere and reopen it.'\n\n/** A handler's throw, as the outcome its caller gets. */\nfunction failureOutcome(err: unknown, lifecycle: DispatcherLifecycle): DispatchOutcome {\n // Its own code is gone from disk: say so, and hand over to a fresh process at the first idle point.\n if (isReplacedBuildError(err)) {\n lifecycle.retireWhenIdle()\n return { ok: false, code: IpcErrorCode.HandlerFailed, message: REPLACED_BUILD_MESSAGE }\n }\n if (err instanceof InvalidParamsError)\n return { ok: false, code: AcpErrorCode.InvalidParams, message: err.message }\n // A machine error keeps its code: a client tells \"busy, retry\" from \"refused\" by it.\n const code = (err as { code?: unknown } | null)?.code\n if (typeof code === 'number' && MACHINE_ERROR_CODES.has(code))\n return { ok: false, code, message: (err as Error).message }\n // A handler's own scope refusal (`PolicyScopeError`) answers like the dispatcher's: Forbidden, with what it needs.\n if (code === IpcErrorCode.Forbidden) {\n const data = (err as { data?: unknown }).data\n return { ok: false, code, message: (err as Error).message, ...(data !== undefined ? { data } : {}) }\n }\n return { ok: false, code: IpcErrorCode.HandlerFailed, message: err instanceof Error ? err.message : String(err) }\n}\n\n/**\n * What a previous process left pending: approvals, and (for a host serving\n * every window) every session's durable runs a dead process left. An\n * in-process host resumes those per session, when a window opens it.\n */\nfunction recoverAfterRestart(host: ChatHost, kind: HostKind, deferResume: boolean): () => void {\n host.approvals.rehydrate()\n let resumed = kind === 'in-process'\n const resume = (): void => {\n if (resumed)\n return\n resumed = true\n void host.resumePending().catch(() => undefined)\n }\n if (!deferResume)\n resume()\n return resume\n}\n\nexport async function createHostDispatcher(options: HostDispatcherOptions): Promise<HostDispatcher> {\n const { appVersion, startedAt, lifecycle } = options\n\n const signalLog = createSignalLog(options.replay)\n // Paged transcripts, off this thread when the store is a SQLite file (the worker ends with the host).\n const transcripts = createHostTranscriptPager()\n // Every numbered signal passes here: the ones following a session change drop its cached replay.\n const peers = createPeerRegistry({ sequence: (signal, json) => {\n transcripts.observe(signal)\n return signalLog.record(signal, json)\n } })\n peers.onClear(transcripts.close)\n const { broadcast, broadcastExcept } = peers\n\n const env = await (options.createEnvironment\n ? options.createEnvironment(broadcast)\n : createDaemonEnvironment({ broadcast }))\n const host = createChatHost(env)\n peers.bindHost(host)\n\n const store = env.store\n const identity = resolveHostIdentity(env.userDataDir(), options.identity ?? { kind: 'daemon' })\n const identityFields = { ...(identity.id ? { hostId: identity.id } : {}), hostKind: identity.kind, hostName: identity.name }\n\n // The host's own confinement (it checks it at its entry points); `fs.*` lists with it.\n const workspace = createWorkspaceRoots(host.workspace)\n const drafts = createDraftHandlers({ broadcastExcept })\n const suggest = createSuggestHandlers({ env, broadcastExcept })\n const launchOverrides = createLaunchOverrideHandlers({ host })\n const browser = createBrowserHandlers({ host })\n const terminal = createTerminalHandlers({ host, isConnected: peers.has })\n // Terminals without a session are This computer's (v1): a server answers their methods \"unknown\".\n const projectTerminals = identity.kind !== 'server'\n const execStreams = createWorkspaceExecStreamHandlers({ host, isConnected: peers.has })\n const auth = createProviderAuth({ host, env })\n const mcpStatus = createMcpStatusTracker({ dataDir: () => env.userDataDir(), store: () => env.mcpCredentialStore?.() ?? createFileMcpCredentialStore(env.userDataDir()), onChange: () => broadcast({ kind: 'catalog:changed', catalog: 'mcps' }), onCredentialsChanged: name => host.mcpServers.retire(name) })\n const oauth = createOAuthFlowHandlers({ host, env, auth, mcpStatus, isConnected: peers.has, serverCallback: options.oauthCallback === true, ...(options.oauthFlowTtlMs !== undefined ? { ttlMs: options.oauthFlowTtlMs } : {}) })\n const settings = createSettingsHandlers({ host, env, broadcast, onClose: peers.onClear })\n const installs = createCatalogInstallHandlers({ host, env, broadcast, setSettings: patch => settings['settings.set']({ patch }, null as unknown as HostPeer), ...(options.remoteInstalls ? { options: options.remoteInstalls } : {}) })\n const authHandlers = createAuthHandlers({ auth })\n const sync = createSyncHandlers({\n host,\n env,\n broadcast,\n auth,\n setters: {\n setSettings: patch => settings['settings.set']({ patch }, null as unknown as HostPeer) as unknown as Record<string, unknown>,\n install: (p, peer) => installs['catalog.install'](p, peer),\n mcpUpsert: (p, peer) => installs['mcp.upsert'](p, peer),\n mcpRemove: (p, peer) => installs['mcp.remove'](p, peer),\n setApiKey: p => authHandlers['auth.setApiKey'](p, null as unknown as HostPeer),\n },\n ...(options.sync ? { options: options.sync } : {}),\n })\n const { markOverrides, ...syncMethods } = sync\n const principalWork = createPrincipalWork(host)\n const writes = workspaceWritesOf(options.workspaceWrites)\n const machineServe = createMachineServeHandlers({ host, dataDir: () => env.userDataDir(), hostName: identity.name, settings: () => env.readSettings(), isConnected: peers.has, ...(options.machineServe ? { options: options.machineServe } : {}) })\n\n // Peer-close cleanup, in this order: browser hosts, terminal viewers and views, launch overrides, a lent machine.\n for (const release of [browser.releasePeer, terminal.releasePeer, launchOverrides.releasePeer, machineServe.releasePeer, execStreams.releasePeer, oauth.releasePeer])\n peers.onClose(release)\n\n const forgetSession = (sessionId: string): void => {\n drafts.forget(sessionId)\n launchOverrides.forget(sessionId)\n suggest.forget(sessionId)\n signalLog.forget(sessionId)\n transcripts.forget(sessionId)\n }\n\n /*\n * Exhaustive by `satisfies`: every `IpcMethodName` MUST have a handler\n * (compile error otherwise), each pinned to its `IpcMethods` signature\n * by the slice it comes from (see `./handlers/types`).\n */\n const methods = {\n ...createChatHandlers({ host, clearDraft: drafts.clearDraft, dedup: sendDedupFor(store) }),\n ...createQueueHandlers({ host, clearDraft: drafts.clearDraft, dedup: sendDedupFor(store) }),\n ...drafts.methods,\n ...suggest.methods,\n ...createExtensionHandlers({ env, broadcastExcept }),\n ...launchOverrides.methods,\n ...createSessionHandlers({ host, store, broadcast, forgetSession, hostId: identity.id, workspace }),\n ...createTitleHandlers({ host, broadcast }),\n ...createSessionReadHandlers({ host, store, snapshots: transcripts.replays }),\n ...createTranscriptHandlers({ host, store, broadcast, pages: transcripts }),\n ...createResumeHandlers({ log: signalLog }),\n ...createContextHandlers({ host }),\n ...createEnvironmentHandlers({ host, env, setSettings: settings['settings.set'] }),\n ...createWorkspaceHandlers({ host }),\n ...execStreams.methods,\n ...createGitHandlers({ host, store, workspace, isConnected: peers.has, onClose: peers.onClose, clone: writes.clone }),\n ...createFilesHandlers({ workspace, onClose: peers.onClose, ...(options.media ? { media: options.media } : {}) }),\n ...createFsHandlers({ workspace, environments: () => Promise.resolve(host.listEnvironments('')), createFolders: writes.createFolders, allows: () => ({ remoteInstalls: remoteInstallsAllowed(options.remoteInstalls), asMachine: machineServe.allowed(), sync: Boolean(options.sync), ...writes.flags() }) }),\n ...authHandlers,\n ...oauth.methods,\n ...installs,\n ...createCatalogHandlers({ env, host, mcpStatus }),\n ...createClientStateHandlers({ env }),\n ...createExtensionUiHandlers({ host, env }),\n ...createPanelHandlers({ host, env, store, onClose: peers.onClose }),\n ...createOnboardingHandlers({ host, env, broadcast, ...(options.remoteInstalls ? { installs: options.remoteInstalls } : {}) }),\n ...createArtifactHandlers({ store, broadcast, env, host }),\n ...createUsageHandlers({ store, scan: transcripts.usage, dataDir: () => env.userDataDir(), providers: () => env.config.providers }),\n ...createHistoryHandlers({ host, store }),\n ...createTodoHandlers({ host, store }),\n ...createOrchestrationHandlers({ host }),\n ...createHitlHandlers({ host, store, userDataDir: () => env.userDataDir() }),\n ...browser.methods,\n ...terminal.methods,\n ...settings,\n ...createPresenceHandlers({ env, peers }),\n ...createMachineHandlers({ host, broadcast }),\n ...machineServe.methods,\n ...createMachineLinkHandlers({ host, env, broadcast, hostId: identity.id, server: identity.kind === 'server', appVersion, ...(options.machineLinks ? { pacing: options.machineLinks } : {}) }),\n ...createPerfHandlers({ perf: lazyHostPerf({ kind: identity.kind, host, store }), onPeerClose: peers.onClose, onShutdown: peers.onClear }),\n ...createServerHandlers({ broadcast, onClose: peers.onClear, onPeerClose: peers.onClose, ...(options.logs ? { logs: options.logs } : {}), ...(options.tokens ? { tokens: options.tokens } : {}), ...(options.update ? { update: options.update } : {}) }),\n ...createDaemonHandlers({ host, appVersion, startedAt, lifecycle, identity: identityFields }),\n ...syncMethods,\n // A window's edit of a field the sync source set makes it a server override.\n ...(options.sync\n ? withSyncOverrides({\n 'settings.set': settings['settings.set'],\n 'mcp.upsert': installs['mcp.upsert'],\n 'mcp.remove': installs['mcp.remove'],\n 'catalog.remove': installs['catalog.remove'],\n 'catalog.update': installs['catalog.update'],\n ...authHandlers,\n }, { readSettings: () => env.readSettings(), markOverrides })\n : {}),\n } satisfies MethodTable\n\n /**\n * Widened view for the string-keyed lookup: the table is typed exhaustively\n * above; unknown wire methods fall out here. Own keys only: a wire method\n * named `constructor` / `__proto__` / `toString` is unknown, not a call into\n * `Object.prototype`.\n */\n const handlerFor = (method: string): ((params: unknown, peer: HostPeer) => unknown) | undefined =>\n Object.hasOwn(methods, method) && (projectTerminals || !PROJECT_TERMINAL_METHODS.has(method))\n ? (methods as Partial<Record<string, (params: unknown, peer: HostPeer) => unknown>>)[method]\n : undefined\n\n function hello(params: Partial<HelloParams>, peer: HostPeer): DispatchOutcome {\n const verdict = evaluateHello(params, { buildId: IPC_BUILD_ID, codeVersion: ZIDANE_VERSION, hasActiveWork: host.hasActiveWork(), hostKind: identity.kind })\n if (!verdict.accept) {\n return {\n ok: false,\n code: IpcErrorCode.VersionMismatch,\n message: verdict.message,\n data: { daemon: { protocolVersion: IPC_PROTOCOL_VERSION, appVersion, pid: process.pid, startedAt, buildId: IPC_BUILD_ID, codeVersion: ZIDANE_VERSION, ...identityFields } },\n }\n }\n if (verdict.retire)\n lifecycle.retireWhenIdle()\n peer.ready = true\n const result: HelloResult = {\n protocolVersion: IPC_PROTOCOL_VERSION,\n ...connectionTerms(peer, verdict.protocolVersion, method => handlerFor(method) !== undefined),\n appVersion,\n pid: process.pid,\n startedAt,\n buildId: IPC_BUILD_ID,\n codeVersion: ZIDANE_VERSION,\n ...identityFields,\n signalEpoch: signalLog.epoch,\n ...(lifecycle.isRetiring() ? { retiring: true } : {}),\n ...hostOffers(options, machineServe.allowed(), writes.flags()),\n ...(projectTerminals ? { projectTerminals: true } : {}),\n }\n return { ok: true, result }\n }\n\n async function route(method: string, params: unknown, peer: HostPeer): Promise<DispatchOutcome> {\n // Transport liveness (`../transports/client-core` heartbeat): answered by any host, handshake or not.\n if (method === PING_METHOD)\n return { ok: true, result: {} }\n if (method === 'ipc.hello')\n return hello((params ?? {}) as Partial<HelloParams>, peer)\n\n /*\n * `daemon.shutdown` / `daemon.info` are allowed pre-handshake: a\n * client that just got a VERSION_MISMATCH on `ipc.hello` (so it\n * never became `ready`) still needs to drain this stale daemon\n * before respawning a matching one.\n */\n if (!peer.ready && method !== 'daemon.shutdown' && method !== 'daemon.info')\n return { ok: false, code: IpcErrorCode.NotHandshaken, message: 'Handshake required: send ipc.hello first.' }\n\n const forbidden = forbiddenCall(method, peer, options.onForbidden)\n if (forbidden)\n return forbidden\n\n const handler = handlerFor(method)\n if (!handler && method.startsWith('machine.'))\n return { ok: false, code: MachineErrorCode.MethodNotAllowed, message: `\"${method}\" needs a machine connection (a machine-scoped token); this is a client connection.` }\n if (!handler)\n return { ok: false, code: AcpErrorCode.MethodNotFound, message: `Unknown method \"${method}\".` }\n\n try {\n checkParams(params)\n return { ok: true, result: (await principalWork.track(method, params, peer, () => handler(params, peer))) ?? null }\n }\n catch (err) {\n return failureOutcome(err, lifecycle)\n }\n }\n\n return {\n host,\n addPeer: peers.add,\n removePeer: peers.remove,\n detachAll: peers.clear,\n peerCount: peers.size,\n // What the previous process left (synchronous: nothing above awaited since the host was built).\n resumeAfterRestart: recoverAfterRestart(host, identity.kind, options.deferResume === true),\n\n handleRequest(method, params, peer) {\n // The stream so far goes out first: a handler reads (and a reply follows) every delta emitted before it.\n peers.flush()\n return route(method, params, peer).finally(peers.flush)\n },\n\n /*\n * Notification fast path: fire-and-forget writes with no response\n * bookkeeping. Used for per-keystroke draft sync, where a\n * request/response round-trip per key would be pure overhead.\n * Routed through the SAME handler table as requests; errors are\n * swallowed (there is nowhere to send them) and pre-handshake\n * notifications are ignored.\n */\n async handleNotification(method, params, peer) {\n if (!peer.ready)\n return\n if (forbiddenCall(method, peer, options.onForbidden))\n return\n const handler = handlerFor(method)\n if (!handler)\n return\n try {\n checkParams(params)\n await principalWork.track(method, params, peer, () => handler(params, peer))\n }\n catch {\n // fire-and-forget by contract\n }\n },\n stopPrincipalWork: principalWork.stop,\n deliverOAuthCallback: oauth.deliverCallback,\n }\n}\n","/**\n * Restart the daemon once it is idle after a newer zidane landed on disk.\n *\n * The daemon outlives upgrades: windows restart onto the new build, the\n * daemon keeps running the old one. It watches its own package the same way\n * windows do (`watchInstalledVersion`: the applied marker every install\n * writes, plus a slow poll). Once a newer version is installed it marks\n * itself retiring (`ipc.hello` / `daemon.info` say so) and exits at the\n * first point where it is fully idle: no run, compaction, command or\n * background task, no live terminal, no pending approval or question. Two\n * idle polls in a row, since a queue drain is scheduled just after a\n * dispatch releases and one poll could land in that gap. Windows reconnect\n * on their own and spawn a daemon from the new build.\n *\n * Loop guard: before it exits it records `{ from, to }` in the cache dir. A\n * daemon that starts on `from` again while `to` is still the installed\n * version (the client that respawned it runs an older binary than the one on\n * PATH) does not retire for `to` a second time.\n */\nimport type { CompanionSpec } from '../../chat/auto-update-companion'\nimport type { InstalledVersionState, InstalledVersionWatcher, WatchInstalledVersionOptions } from '../../chat/auto-update-restart'\nimport type { ChatHost } from '../../chat/host/engine'\nimport { mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { watchInstalledVersion } from '../../chat/auto-update-restart'\n\n/** File name of the loop guard inside the cache directory. */\nexport const DAEMON_UPDATE_RESTART_FILE = 'daemon-update-restart.json'\n\n/** The last restart the daemon made for an update. */\nexport interface DaemonUpdateRestartRecord {\n /** Version the daemon ran when it exited. */\n from: string\n /** Installed version it exited for. */\n to: string\n /** ms since epoch. */\n at: number\n}\n\n/** Options for {@link watchDaemonUpdate}. */\nexport interface WatchDaemonUpdateOptions {\n /** The daemon's package, e.g. `{ packageName: 'zidane-tui', binName: 'zidane' }`. */\n spec: CompanionSpec\n /** Version the daemon runs. An empty string turns the watch off. */\n currentVersion: string\n /** Where the applied marker and the loop guard live. */\n cacheDir: string\n /** No runs, compactions, commands, background tasks, live terminals or pending prompts. */\n isIdle: () => boolean\n /** A newer version is installed: the daemon now waits for idle. Called once. */\n onPending?: (version: string) => void\n /** Fully idle with a newer version installed: exit now. Called once. */\n retire: () => void\n /** One diagnostic line per event. */\n log?: (line: string) => void\n /** Idle poll interval. Default 1 s. */\n idlePollMs?: number\n /** Installed-version poll interval, passed to the watcher. Default 5 min. */\n pollMs?: number\n /** Injected for tests. Defaults to {@link watchInstalledVersion}. */\n watch?: (options: WatchInstalledVersionOptions) => InstalledVersionWatcher\n /** Injected for tests. Defaults to `Date.now`. */\n now?: () => number\n}\n\n/** Handle returned by {@link watchDaemonUpdate}. */\nexport interface DaemonUpdateWatch {\n /** The installed version the daemon waits to restart for, or `null`. */\n pending: () => string | null\n /** Stops watching and waiting. */\n close: () => void\n}\n\n/**\n * Nothing a restart would cut short: no run, compaction, command or\n * background task, no live terminal (`hasActiveWork`), and no approval or\n * question waiting for an answer.\n *\n * @param host - The daemon's chat host.\n */\nexport function daemonFullyIdle(host: Pick<ChatHost, 'hasActiveWork' | 'interactions'>): boolean {\n return !host.hasActiveWork() && host.interactions.list().length === 0\n}\n\n/**\n * Reads the loop guard. `null` when there is none or it does not parse.\n *\n * @param cacheDir - Directory that holds the record.\n */\nexport function readDaemonUpdateRestart(cacheDir: string): DaemonUpdateRestartRecord | null {\n try {\n const raw = JSON.parse(readFileSync(join(cacheDir, DAEMON_UPDATE_RESTART_FILE), 'utf8')) as Partial<DaemonUpdateRestartRecord>\n if (typeof raw.from === 'string' && typeof raw.to === 'string' && typeof raw.at === 'number')\n return { from: raw.from, to: raw.to, at: raw.at }\n return null\n }\n catch {\n return null\n }\n}\n\nfunction writeDaemonUpdateRestart(cacheDir: string, record: DaemonUpdateRestartRecord): void {\n try {\n mkdirSync(cacheDir, { recursive: true })\n writeFileSync(join(cacheDir, DAEMON_UPDATE_RESTART_FILE), `${JSON.stringify(record)}\\n`)\n }\n catch {\n // Without the guard a respawn on the old build may retire once more; never worse.\n }\n}\n\n/**\n * Watches for a newer install of the daemon's own package and calls `retire`\n * at the first fully idle point after one lands.\n *\n * @param options - Package, running version, idle probe and callbacks.\n */\nexport function watchDaemonUpdate(options: WatchDaemonUpdateOptions): DaemonUpdateWatch {\n const log = options.log ?? (() => undefined)\n const now = options.now ?? Date.now\n let pending: string | null = null\n let idleTimer: ReturnType<typeof setInterval> | undefined\n let closed = false\n\n const onState = (state: InstalledVersionState): void => {\n if (closed || pending || !state.restartRequired || !state.installed)\n return\n const guard = readDaemonUpdateRestart(options.cacheDir)\n if (guard && guard.from === options.currentVersion && guard.to === state.installed) {\n log(`[ipc-daemon] zidane ${state.installed} is installed, but a restart for it came back on ${options.currentVersion}; staying up`)\n return\n }\n pending = state.installed\n log(`[ipc-daemon] zidane ${pending} is installed; restarting once idle`)\n options.onPending?.(pending)\n let idlePolls = 0\n idleTimer = setInterval(() => {\n if (!options.isIdle()) {\n idlePolls = 0\n return\n }\n idlePolls += 1\n if (idlePolls < 2)\n return\n clearInterval(idleTimer)\n idleTimer = undefined\n writeDaemonUpdateRestart(options.cacheDir, { from: options.currentVersion, to: pending!, at: now() })\n log(`[ipc-daemon] idle; restarting for zidane ${pending}`)\n options.retire()\n }, options.idlePollMs ?? 1000)\n // Never keep the process alive for this.\n if (typeof idleTimer === 'object' && 'unref' in idleTimer)\n idleTimer.unref()\n }\n\n const watcher = (options.watch ?? watchInstalledVersion)({\n spec: options.spec,\n currentVersion: options.currentVersion,\n cacheDir: options.cacheDir,\n ...(options.pollMs !== undefined ? { pollMs: options.pollMs } : {}),\n onChange: onState,\n })\n onState(watcher.current())\n\n return {\n pending: () => pending,\n close: () => {\n closed = true\n clearInterval(idleTimer)\n watcher.close()\n },\n }\n}\n","/**\n * Unix-socket JSON-RPC server around a `ChatHost`.\n *\n * One `net.Server`, one JSON-RPC connection per peer (NDJSON framing: a\n * `net.Socket` is both the Readable and the Writable). The method table,\n * per-peer state, signal fan-out and the `ipc.hello` handshake live in the\n * transport-free dispatcher (`./dispatcher`); this module owns only what is\n * specific to the socket and the process: framing, the socket file and its\n * permissions, idle exit, retiring, and draining. Write backpressure (the\n * slow-consumer bound, the reply size) is shared with the WebSocket server\n * (`../transports/send-budget`).\n *\n * Handshake: a peer's first request MUST be `ipc.hello` carrying its\n * protocol version. Mismatched peers get a structured error (code\n * `IpcErrorCode.VersionMismatch`) and can ask the daemon to drain via `daemon.shutdown`\n * before respawning a fresh one.\n */\nimport type { Server, Socket } from 'node:net'\nimport type { JsonRpcConnection } from '../../acp/json-rpc'\nimport type { ChatHost } from '../../chat/host/engine'\nimport type { HostSignal } from '../protocol'\nimport type { HostDispatcher } from './dispatcher'\nimport type { DaemonEnvironment } from './environment'\nimport type { WatchDaemonUpdateOptions } from './update-retire'\nimport { chmodSync, existsSync, mkdirSync, unlinkSync } from 'node:fs'\nimport { createServer } from 'node:net'\nimport { basename, dirname } from 'node:path'\nimport { createJsonRpcConnection } from '../../acp/json-rpc'\nimport { connectIpcClient } from '../client'\nimport { createPacedWriter } from '../transports/paced-writer'\nimport { createRpcPeer, dispatcherHandlers, PEER_WRITE_HIGH_WATERMARK } from '../transports/peer-rpc'\nimport { createPeerSend } from '../transports/send-budget'\nimport { createHostDispatcher } from './dispatcher'\nimport { legacySocketPath, probeSocket } from './lifecycle'\nimport { daemonFullyIdle, watchDaemonUpdate } from './update-retire'\n\n// Canonical home is the protocol module (clients import the codes without\n// pulling the server's module graph); re-exported here for compatibility.\nexport { IpcErrorCode } from '../protocol'\n\n/** Options for {@link startIpcDaemon}. */\nexport interface IpcDaemonOptions {\n /** Path of the unix socket to listen on. Its directory is created with mode 0700 and the socket gets mode 0600. */\n socketPath: string\n /**\n * Environment factory — the production daemon uses the disk-backed\n * `createDaemonEnvironment`; tests inject an in-memory one. Receives the\n * broadcast sink wired to peer fan-out.\n */\n createEnvironment?: (broadcast: (signal: HostSignal) => void) => DaemonEnvironment | Promise<DaemonEnvironment>\n /**\n * zidane version reported in the handshake.\n * @default 'dev'\n */\n appVersion?: string\n /**\n * Milliseconds the daemon may have zero peers and no running session before\n * it calls `onIdle`. Unset or 0: never. Ignored with a shared `dispatcher`.\n */\n idleShutdownMs?: number\n /** Called when the daemon has had no peers for `idleShutdownMs` and no session is active, or when it retires after a newer client attached mid-work. The CLI exits the process; embedded servers ignore it. */\n onIdle?: () => void\n /** Receives one diagnostic line per event, such as peers connecting. */\n onLog?: (line: string) => void\n /**\n * Serve this already-built host instead of creating one: another front-end\n * (zidane-server's WebSocket) serves it too. Its owner drains it and owns\n * its lifecycle, so `createEnvironment`, `appVersion` and the idle options\n * are ignored, and `close()` only closes this socket's connections.\n */\n dispatcher?: HostDispatcher\n /** See `HostDispatcherOptions.deferResume`: the caller calls `dispatcher.resumeAfterRestart()`. Ignored with a shared `dispatcher`. */\n deferResume?: boolean\n /**\n * A peer with more than this of signals queued for sending (it stopped\n * reading) is dropped; it re-attaches and resumes. Replies are bounded by\n * `maxMessageBytes` instead (`../transports/send-budget`). Default\n * `PEER_WRITE_HIGH_WATERMARK` (8 MiB).\n */\n maxBufferedBytes?: number\n /** A bigger reply goes out as an `IpcErrorCode.ResponseTooLarge` error. Default {@link SOCKET_MAX_REPLY_BYTES}. */\n maxMessageBytes?: number\n /**\n * Watch this package for a newer install and restart (close, then\n * `onIdle`) at the first fully idle point after one lands. Only for a\n * daemon run from an installed build. Ignored with a shared `dispatcher`.\n */\n updateWatch?: Pick<WatchDaemonUpdateOptions, 'spec' | 'currentVersion' | 'cacheDir' | 'pollMs' | 'idlePollMs' | 'watch'>\n}\n\n/**\n * Largest reply on the socket by default. Generous: the peer is this user's\n * own window on this machine, and whole-session reads (`sessions.get`) of a\n * long local session with images must keep fitting. The bound is there so\n * one reply cannot grow the write buffer without limit.\n */\nconst SOCKET_MAX_REPLY_BYTES = 256 * 1024 * 1024\n\n/** A running unix-socket daemon. */\nexport interface IpcDaemon {\n /** Path of the socket it listens on. */\n socketPath: string\n /** The chat host it serves. */\n host: ChatHost\n /** The dispatcher it serves, to connect an in-process client to it (`../memory` `connectInProcess`). */\n dispatcher: HostDispatcher\n /** Number of connected peers. */\n peerCount: () => number\n /** Drains the host, disconnects every peer and removes the socket file. Calling it again returns the same promise. With a shared `dispatcher`, the host is left to its owner. */\n close: () => Promise<void>\n}\n\n/** One open socket connection; `close()` ends them all. */\ninterface SocketConnection {\n socket: Socket\n connection: JsonRpcConnection\n}\n\n/**\n * Starts a unix-socket daemon around a chat host. Each peer must open with `ipc.hello`.\n * A stale socket file left by a dead daemon is replaced. Throws when a live daemon already listens on `socketPath`.\n * @param options - Socket path, environment and lifecycle settings.\n * @returns The running daemon.\n * @example\n * ```ts\n * import { startIpcDaemon } from 'zidane/ipc'\n *\n * const daemon = await startIpcDaemon({\n * socketPath: '/tmp/zidane-demo/daemon/ipc.sock',\n * onLog: line => console.log(line),\n * })\n * console.log(daemon.peerCount())\n * await daemon.close()\n * ```\n */\nexport async function startIpcDaemon(options: IpcDaemonOptions): Promise<IpcDaemon> {\n const { socketPath } = options\n const log = options.onLog ?? (() => undefined)\n const startedAt = Date.now()\n const appVersion = options.appVersion ?? 'dev'\n const maxBuffered = options.maxBufferedBytes ?? PEER_WRITE_HIGH_WATERMARK\n const maxMessage = options.maxMessageBytes ?? SOCKET_MAX_REPLY_BYTES\n\n const connections = new Set<SocketConnection>()\n let idleTimer: ReturnType<typeof setTimeout> | undefined\n // See `retireWhenIdle`.\n let retiring = false\n /** A newer zidane is installed and `./update-retire` waits for full idle; separate so `retireWhenIdle` still arms. */\n let updatePending = false\n let retireTimer: ReturnType<typeof setInterval> | undefined\n\n const shared = options.dispatcher\n const dispatcher = shared ?? await createHostDispatcher({\n ...(options.createEnvironment ? { createEnvironment: options.createEnvironment } : {}),\n appVersion,\n startedAt,\n identity: { kind: 'daemon' },\n ...(options.deferResume ? { deferResume: true } : {}),\n lifecycle: {\n shutdown: () => {\n void close().then(() => options.onIdle?.())\n },\n retireWhenIdle,\n isRetiring: () => retiring || updatePending,\n },\n })\n const host = dispatcher.host\n\n /* ----------------------------------------------------------------------\n * Socket plumbing\n * -------------------------------------------------------------------- */\n\n /*\n * Retire-when-idle: a NEWER client found this daemon mid-work. Draining\n * now would abort every window's runs (a dev edit under `src/ipc` or an\n * upgrade mid-`/review` did exactly that), so keep serving and exit at\n * the first idle point. Two consecutive idle polls: a queue drain is\n * scheduled just after a dispatch releases, and one poll could land in\n * that gap.\n */\n function retireWhenIdle(): void {\n if (retiring)\n return\n retiring = true\n log('[ipc-daemon] a newer client attached mid-work; retiring once idle')\n let idlePolls = 0\n retireTimer = setInterval(() => {\n if (host.hasActiveWork()) {\n idlePolls = 0\n return\n }\n idlePolls += 1\n if (idlePolls < 2)\n return\n clearInterval(retireTimer)\n void close().then(() => options.onIdle?.())\n }, 1000)\n }\n\n // A newer zidane on disk: retire like above, but only once fully idle (`./update-retire`).\n const updates = options.updateWatch && !shared\n ? watchDaemonUpdate({ ...options.updateWatch, isIdle: () => daemonFullyIdle(host), onPending: () => { updatePending = true }, retire: () => void close().then(() => options.onIdle?.()), log })\n : null\n\n function armIdleTimer(): void {\n if (shared || !options.idleShutdownMs || !options.onIdle)\n return\n clearTimeout(idleTimer)\n idleTimer = setTimeout(() => {\n if (dispatcher.peerCount() > 0)\n return // Peers reconnected — the next last-disconnect re-arms.\n /*\n * Never abort a live run just because every window detached — `/exit`\n * is explicitly \"the run keeps going\". Re-arm and check again later.\n */\n if (host.hasActiveWork()) {\n armIdleTimer()\n return\n }\n options.onIdle?.()\n }, options.idleShutdownMs)\n }\n\n function handleConnection(socket: Socket): void {\n // Assigned right below; a signal can only reach this peer after `ipc.hello`, i.e. once it is set.\n let connection: JsonRpcConnection | undefined\n const writer = createPacedWriter(socket)\n const budget = createPeerSend(\n {\n buffered: writer.buffered,\n // NDJSON: `JSON.stringify` escapes newlines, so a message is one line.\n write: (json) => {\n writer.write(`${json}\\n`)\n return true\n },\n },\n {\n maxBuffered,\n maxMessage,\n log,\n label: '[ipc-daemon]',\n stuck: (why) => {\n log(`[ipc-daemon] dropping peer: ${why}`)\n socket.destroy()\n },\n },\n )\n const peer = createRpcPeer({ rpc: () => connection })\n\n const rpc = createJsonRpcConnection({\n input: socket,\n output: socket,\n send: budget.send,\n ...dispatcherHandlers(dispatcher, peer),\n onError: err => log(`[ipc-daemon] peer error: ${err.message}`),\n })\n\n connection = rpc\n const entry: SocketConnection = { socket, connection: rpc }\n connections.add(entry)\n dispatcher.addPeer(peer)\n rpc.start()\n log(`[ipc-daemon] peer connected (${dispatcher.peerCount()} total)`)\n\n const drop = (): void => {\n if (!connections.delete(entry))\n return\n rpc.close()\n dispatcher.removePeer(peer)\n log(`[ipc-daemon] peer disconnected (${dispatcher.peerCount()} left)`)\n if (dispatcher.peerCount() === 0)\n armIdleTimer()\n }\n\n socket.on('close', drop)\n socket.on('error', drop)\n }\n\n /*\n * Stale-socket recovery: a previous daemon that died without cleanup\n * leaves the socket file behind and `listen` would fail EADDRINUSE.\n * Probe before unlinking so a LIVE daemon is never yanked out from\n * under its peers.\n */\n if (existsSync(socketPath)) {\n if (await probeSocket(socketPath))\n throw new Error(`A zidane daemon is already listening on ${socketPath}.`)\n /*\n * Narrow the concurrent-spawn race: another daemon may have bound the\n * socket between the probe above and the unlink below (each probe is a\n * full connect attempt). Re-probe immediately before unlinking and\n * abort startup if something now answers — never yank a live daemon's\n * socket out from under its peers.\n */\n if (await probeSocket(socketPath))\n throw new Error(`A zidane daemon is already listening on ${socketPath}.`)\n unlinkSync(socketPath)\n }\n /*\n * The daemon speaks an unauthenticated RPC surface that can execute tools\n * as the daemon user — restrict access to the owner. The containing dir\n * is created 0700 (belt) and the socket is chmod'd to 0600 right after\n * `listen` (suspenders) so connectability never depends on ambient umask.\n *\n * `mkdirSync`'s mode only applies on CREATION — a pre-existing dir keeps\n * its old mode. When the dir is the DEDICATED daemon dir (the `daemon/`\n * subdir `defaultSocketPath` uses, or one we created fresh for an\n * explicit socket path) chmod it 0700 explicitly. A shared, pre-existing\n * dir (tests pointing the socket at a tmpdir) is left alone — never\n * tighten a directory that also holds unrelated state.\n */\n const socketDir = dirname(socketPath)\n const dedicatedSocketDir = basename(socketDir) === 'daemon' || !existsSync(socketDir)\n mkdirSync(socketDir, { recursive: true, mode: 0o700 })\n if (dedicatedSocketDir) {\n try {\n chmodSync(socketDir, 0o700)\n }\n catch {\n // Best-effort — mirrors the socket chmod below.\n }\n }\n\n const server: Server = createServer(handleConnection)\n await new Promise<void>((resolvePromise, reject) => {\n server.once('error', reject)\n server.listen(socketPath, () => {\n server.off('error', reject)\n resolvePromise()\n })\n })\n try {\n chmodSync(socketPath, 0o600)\n }\n catch {\n // Best-effort on platforms where socket chmod is a no-op (e.g. some\n // network filesystems); the 0700 dir still constrains access.\n }\n log(`[ipc-daemon] listening on ${socketPath}`)\n // We bound the socket, so we own the file — close() unlinks it exactly\n // once. Cleared after the unlink so a file later re-created by a NEW\n // daemon on the same path is never yanked by a stale close.\n let ownsSocketFile = true\n armIdleTimer()\n\n /*\n * Drain any daemon still serving the legacy socket path\n * (`<stateDir>/daemon.sock`). New clients never probe it,\n * so a `--idle-exit 0` service daemon there would run forever alongside\n * this one — two sets of live agents, run guards, and heartbeat writers\n * against the same sessions.db. Fire-and-forget: version mismatch is\n * the EXPECTED case (a legacy daemon speaks an older protocol) and\n * `drainOnMismatch: true` performs the shutdown for us; a same-version\n * survivor (explicit env overrides) gets an explicit daemon.shutdown.\n */\n const legacyPath = shared ? null : legacySocketPath(socketPath)\n if (legacyPath) {\n void (async () => {\n if (!(await probeSocket(legacyPath)))\n return\n log(`[ipc-daemon] draining legacy daemon on ${legacyPath}`)\n try {\n const survivor = await connectIpcClient({ socketPath: legacyPath, appVersion: `${appVersion}/legacy-drain`, drainOnMismatch: true })\n await survivor.request('daemon.shutdown', {}).catch(() => undefined)\n survivor.close()\n }\n catch {\n // IpcVersionMismatchError = drained by the handshake path; anything\n // else (raced exit, wedged socket) is best-effort — leave it.\n }\n })()\n }\n\n async function doClose(): Promise<void> {\n clearTimeout(idleTimer)\n clearInterval(retireTimer)\n updates?.close()\n // A shared host is its owner's to drain and detach (see `dispatcher`).\n if (!shared)\n await host.drain()\n // Stop accepting before closing what is open: a connection landing in\n // between would otherwise keep `server.close` waiting forever.\n const stopped = new Promise<void>((resolvePromise) => {\n server.close(() => resolvePromise())\n })\n for (const { connection, socket } of connections) {\n connection.close()\n socket.destroy()\n }\n connections.clear()\n if (!shared)\n dispatcher.detachAll()\n await stopped\n if (ownsSocketFile) {\n ownsSocketFile = false\n try {\n unlinkSync(socketPath)\n }\n catch {\n // already gone\n }\n }\n }\n\n /*\n * Idempotent close: `daemon.shutdown` runs close() and then onIdle, whose\n * CLI implementation calls daemon.close() again — both callers share one\n * drain instead of double-unlinking the socket. Memoized rather than\n * flag-guarded so the second caller awaits actual completion.\n */\n let closePromise: Promise<void> | null = null\n function close(): Promise<void> {\n closePromise ??= doClose()\n return closePromise\n }\n\n return {\n socketPath,\n host,\n dispatcher,\n peerCount: () => dispatcher.peerCount(),\n close,\n }\n}\n","/**\n * Login-shell PATH for processes not started from a terminal.\n *\n * A Dock/Finder-launched GUI, or a daemon it spawns, inherits launchd's PATH\n * (`/usr/bin:/bin:/usr/sbin:/sbin`), so `node` / `bun` / `yarn` are invisible\n * to agent shell commands. Ask the user's login shell for its PATH and merge\n * it into `process.env.PATH`.\n *\n * Merge, don't replace: a terminal launch may have prepended entries the rc\n * files know nothing about (`nvm use`, direnv, `PATH=... zidane`), and those\n * must survive. Idempotent, so every surface (GUI, daemon) can call it and a\n * daemon spawned by an already-fixed GUI ends up with the same PATH.\n */\nimport { spawnSync } from 'node:child_process'\nimport { userInfo } from 'node:os'\nimport { delimiter } from 'node:path'\nimport process from 'node:process'\nimport { runBounded } from '../../contexts/run-bounded'\n\nconst DELIMITER = '_ZIDANE_SHELL_ENV_'\n\n/** A slow rc file costs startup time; a prompting one must never hang the process. */\nconst DEFAULT_TIMEOUT_MS = 3_000\n\nfunction defaultShell(env: NodeJS.ProcessEnv): string {\n try {\n const { shell } = userInfo()\n if (shell)\n return shell\n }\n catch {}\n return env.SHELL || (process.platform === 'darwin' ? '/bin/zsh' : '/bin/sh')\n}\n\nfunction parsePath(stdout: string): string | undefined {\n const body = stdout.split(DELIMITER)[1]\n if (body === undefined)\n return undefined\n // eslint-disable-next-line no-control-regex\n const clean = body.replace(/\\u001B\\[[0-9;]*[A-Z]/gi, '')\n for (const line of clean.split('\\n')) {\n if (line.startsWith('PATH='))\n return line.slice('PATH='.length) || undefined\n }\n return undefined\n}\n\n/**\n * Options for {@link shellPath} and {@link shellPathAsync}. Without `shell`,\n * the user's shell is tried first, then POSIX fallbacks for non-POSIX defaults\n * (nushell, xonsh) whose `-ilc` differs. An explicit `shell` is tried alone.\n * `timeoutMs` bounds each shell. Default 3000.\n */\nexport interface ShellPathOptions { env?: NodeJS.ProcessEnv, timeoutMs?: number, shell?: string }\n\n// `command env` sidesteps aliases/functions named `env`.\nconst SHELL_ARGS = ['-ilc', `echo -n \"${DELIMITER}\"; command env; echo -n \"${DELIMITER}\"; exit`]\n\nfunction shellCandidates(options: ShellPathOptions): { shells: string[], env: NodeJS.ProcessEnv, timeout: number } {\n const env = options.env ?? process.env\n return {\n shells: options.shell ? [options.shell] : [...new Set([defaultShell(env), '/bin/zsh', '/bin/bash'])],\n timeout: options.timeoutMs ?? DEFAULT_TIMEOUT_MS,\n env: {\n ...env,\n // Keep oh-my-zsh from blocking on its update prompt / tmux autostart.\n DISABLE_AUTO_UPDATE: 'true',\n ZSH_TMUX_AUTOSTARTED: 'true',\n ZSH_TMUX_AUTOSTART: 'false',\n },\n }\n}\n\n/**\n * Reads the PATH of the user's interactive login shell, blocking until it answers.\n * Tries the user's shell, then `/bin/zsh` and `/bin/bash`. Returns `undefined` on Windows, or when no shell answers in time.\n * @param options - Shell, environment and timeout overrides.\n * @returns The PATH string, or `undefined`.\n */\nexport function shellPath(options: ShellPathOptions = {}): string | undefined {\n if (process.platform === 'win32')\n return undefined\n const { shells, env, timeout } = shellCandidates(options)\n for (const shell of shells) {\n const result = spawnSync(shell, SHELL_ARGS, {\n encoding: 'utf8',\n timeout,\n stdio: ['ignore', 'pipe', 'ignore'],\n env,\n })\n if (result.error || result.status !== 0)\n continue\n const path = parsePath(result.stdout)\n if (path)\n return path\n }\n return undefined\n}\n\n/**\n * {@link shellPath} without blocking the event loop: same shells, args,\n * timeout and parsing, run with {@link runBounded} (a timeout ends the shell's\n * whole tree; under Bun its output survives a shell that exits before Bun\n * watches it). For hosts (the GUI main process) that can start on a cached\n * PATH and refresh in the background.\n * @param options - Shell, environment and timeout overrides.\n * @returns The PATH string, or `undefined`.\n */\nexport async function shellPathAsync(options: ShellPathOptions = {}): Promise<string | undefined> {\n if (process.platform === 'win32')\n return undefined\n const { shells, env, timeout } = shellCandidates(options)\n for (const shell of shells) {\n const run = await runBounded(shell, SHELL_ARGS, { env, timeoutMs: timeout })\n if (run.code !== 0)\n continue\n const path = parsePath(run.stdout)\n if (path)\n return path\n }\n return undefined\n}\n\n/**\n * Entries of `current` the shell doesn't know about (ad-hoc prepends from the\n * launching terminal) stay in front; then the shell's PATH in its own order.\n * From the Dock every launchd entry is already in the shell PATH, so the\n * result is exactly the shell PATH, with the shell's precedence intact.\n * @param current - The PATH of this process.\n * @param shell - The PATH reported by the login shell.\n * @returns The merged PATH string.\n */\nexport function mergePath(current: string | undefined, shell: string | undefined): string {\n const split = (path: string | undefined): string[] => (path ?? '').split(delimiter).filter(Boolean)\n const fromShell = split(shell)\n const known = new Set(fromShell)\n return [...new Set([...split(current).filter(entry => !known.has(entry)), ...fromShell])].join(delimiter)\n}\n\n/** Merge the login shell's PATH into `process.env.PATH`. No-op on Windows or when no shell answers. */\nexport function fixPath(): void {\n const extra = shellPath()\n if (extra)\n process.env.PATH = mergePath(process.env.PATH, extra)\n}\n","/**\n * In-process transport: the host dispatcher in the window's own process, and\n * `IpcClient`s that call it directly instead of over a unix socket.\n *\n * For a window that runs its own host (TUI local mode on the shared engine):\n * the same dispatcher, method table and signal fan-out a daemon serves, with\n * no socket, no spawn and no second process. A caller sees what a socket\n * client would, so the daemon-mode code paths run on it unchanged:\n * - params, results and signals are JSON copies (as on the wire: a top-level\n * `undefined` result arrives as `null`, nested `undefined` fields are\n * dropped, and nothing is shared between the window and the host);\n * - a failed request rejects with `JsonRpcRemoteError` carrying the\n * dispatcher's code; a closed connection rejects with\n * `JsonRpcConnectionClosedError`, in-flight requests included;\n * - responses and signals arrive asynchronously, through one queue in the\n * order the host produced them (a socket reads them in write order);\n * - `close()` detaches quietly; the host shutting down calls `onClose`.\n *\n * `connectInProcess` opens the same client on a dispatcher that already\n * serves other transports (a zidane-server's), optionally held to a client\n * scope like a WebSocket peer with that token.\n *\n * Two socket behaviors are deliberately absent. Request deadlines exist on\n * the socket to recover from a wedged daemon by dropping the connection and\n * reconnecting; in-process there is nothing to reconnect to. And\n * `daemon.shutdown` from a client does not stop the host: its lifetime\n * belongs to the embedding window (`InProcessHost.close()`).\n */\nimport type { ChatHost } from '../chat/host/engine'\nimport type { IpcClient } from './client'\nimport type { HostDispatcher, HostPeer } from './daemon/dispatcher'\nimport type { DaemonEnvironment } from './daemon/environment'\nimport type { HelloResult, HostSignal } from './protocol'\nimport type { ClientScope } from './scopes'\nimport type { SignalListener } from './transports/client-core'\nimport { JsonRpcConnectionClosedError, JsonRpcRemoteError } from '../acp/json-rpc'\nimport { ZIDANE_VERSION } from '../version'\nimport { createHostDispatcher } from './daemon/dispatcher'\nimport { IPC_BUILD_ID } from './daemon/lifecycle'\nimport { IPC_PROTOCOL_VERSION } from './protocol'\n\n/** Options for {@link startInProcessHost}. */\nexport interface InProcessHostOptions {\n /** The host's environment, given the broadcast sink wired to client fan-out. */\n createEnvironment: (broadcast: (signal: HostSignal) => void) => DaemonEnvironment | Promise<DaemonEnvironment>\n /** Reported to clients as the host's `appVersion`. */\n appVersion?: string\n}\n\n/** Options for {@link InProcessHost.connect}. */\nexport interface InProcessClientOptions {\n /** Client version, surfaced in the host's diagnostics. */\n appVersion?: string\n /** Called when the host shuts down under a still-open client. */\n onClose?: () => void\n}\n\n/** Options for {@link connectInProcess}. */\nexport interface InProcessConnectOptions extends InProcessClientOptions {\n /** The client scope the dispatcher holds the client to (`./scopes`). Absent: every method, like a local window. */\n grant?: ClientScope\n}\n\n/** A chat host running in the caller's process, with clients that call it directly. */\nexport interface InProcessHost {\n /** The chat host. */\n host: ChatHost\n /** A new client, already past the `ipc.hello` handshake. */\n connect: (options?: InProcessClientOptions) => Promise<IpcClient>\n /** Number of open clients. */\n peerCount: () => number\n /**\n * Shut the host down: refuse new work, suspend and await every run\n * (`ChatHost.drain`), then close the clients still open (their `onClose`\n * fires). Idempotent.\n */\n close: () => Promise<void>\n}\n\n/** JSON round-trip: what crossing the socket does to a value. */\nfunction wire<T>(value: T): T {\n return value === undefined ? (null as T) : JSON.parse(JSON.stringify(value)) as T\n}\n\n/** One open client, from the host's side. */\ninterface Connection {\n peer: HostPeer\n /** The host is shutting down: reject what is pending, then tell the client. */\n hostClosed: () => void\n}\n\n/**\n * Opens one client on `dispatcher`; `connections` (the in-process host's)\n * tracks it until it closes, so the host can close it when it shuts down.\n */\nasync function openClient(dispatcher: HostDispatcher, options: InProcessConnectOptions, connections?: Set<Connection>): Promise<IpcClient> {\n const listeners = new Set<SignalListener>()\n const pending = new Set<(err: Error) => void>()\n let closed = false\n\n /*\n * Everything bound for the client goes through one FIFO drained in a\n * microtask: signals, and request outcomes once the dispatcher settles\n * them. A signal the host emits after answering a request is therefore\n * delivered after that answer, as a socket would read them.\n */\n const outbox: Array<() => void> = []\n let draining = false\n const deliver = (item: () => void): void => {\n outbox.push(item)\n if (draining)\n return\n draining = true\n queueMicrotask(() => {\n try {\n while (outbox.length > 0) {\n try {\n outbox.shift()!()\n }\n catch {\n // A throwing listener costs that one message, as on the socket\n // (the JSON-RPC reader catches it), never the connection.\n }\n }\n }\n finally {\n draining = false\n }\n })\n }\n\n const peer: HostPeer = {\n ready: false,\n watching: null,\n ...(options.grant ? { grant: options.grant } : {}),\n send(signal, seq, encoded) {\n if (closed)\n return\n const meta = seq === undefined ? undefined : { seq }\n let copy: HostSignal\n try {\n // The fan-out's one serialization, when it has one.\n const json = encoded ? encoded.json() : JSON.stringify(signal)\n if (json === undefined)\n return\n copy = JSON.parse(json) as HostSignal\n }\n catch {\n // Not JSON-able: the socket server drops it the same way, and a\n // bad signal must never break fan-out to the other clients.\n return\n }\n deliver(() => {\n if (closed)\n return\n for (const listener of listeners)\n listener(copy, meta)\n })\n },\n }\n\n const request = (method: string, params: unknown): Promise<unknown> => {\n if (closed)\n return Promise.reject(new JsonRpcConnectionClosedError())\n return new Promise((resolve, reject) => {\n pending.add(reject)\n const settle = (outcome: () => void): void => {\n deliver(() => {\n if (!pending.delete(reject))\n return\n outcome()\n })\n }\n dispatcher.handleRequest(method, params === undefined ? undefined : wire(params), peer).then(\n (result) => {\n settle(() => {\n // The reject is already out of `pending`: a throw here (a result\n // that is not JSON-able) must fail the request, not hang it.\n try {\n if (result.ok)\n resolve(wire(result.result))\n else\n reject(new JsonRpcRemoteError(result.message, result.code, result.data))\n }\n catch (err) {\n reject(err instanceof Error ? err : new Error(String(err)))\n }\n })\n },\n err => settle(() => reject(err)),\n )\n })\n }\n\n /** Stop delivering and fail what is in flight, as a socket closing does. */\n const shut = (): void => {\n closed = true\n listeners.clear()\n outbox.length = 0\n for (const reject of pending)\n reject(new JsonRpcConnectionClosedError())\n pending.clear()\n }\n\n const connection: Connection = {\n peer,\n hostClosed: () => {\n if (closed)\n return\n shut()\n options.onClose?.()\n },\n }\n\n dispatcher.addPeer(peer)\n connections?.add(connection)\n const detach = (): void => {\n if (closed)\n return\n shut()\n connections?.delete(connection)\n dispatcher.removePeer(peer)\n }\n\n let hello: HelloResult\n try {\n hello = await request('ipc.hello', {\n protocolVersion: IPC_PROTOCOL_VERSION,\n appVersion: options.appVersion ?? 'dev',\n pid: process.pid,\n buildId: IPC_BUILD_ID,\n codeVersion: ZIDANE_VERSION,\n }) as HelloResult\n }\n catch (err) {\n detach()\n throw err\n }\n\n return {\n hello,\n request: request as IpcClient['request'],\n notify: (method, params) => {\n if (closed)\n return\n const copy = params === undefined ? undefined : wire(params)\n // Off the caller's stack, as a socket write would be.\n queueMicrotask(() => {\n if (!closed)\n void dispatcher.handleNotification(method, copy, peer)\n })\n },\n onSignal: (listener) => {\n listeners.add(listener)\n return () => listeners.delete(listener)\n },\n close: detach,\n }\n}\n\n/**\n * Connects an in-process client to a dispatcher that already runs (a\n * zidane-server's, the daemon's), next to its socket and WebSocket peers.\n * With a `grant`, the dispatcher checks every call against it as it does for\n * a WebSocket peer whose token has that scope (`./scopes`); without one the\n * client reaches every method, like a local window.\n *\n * The dispatcher's owner closes such clients before it stops the host:\n * `onClose` fires only when the in-process host of {@link startInProcessHost}\n * shuts down under one.\n * @param dispatcher - The running dispatcher.\n * @param options - Scope and version.\n * @returns The client, already past the `ipc.hello` handshake.\n */\nexport function connectInProcess(dispatcher: HostDispatcher, options: InProcessConnectOptions = {}): Promise<IpcClient> {\n return openClient(dispatcher, options)\n}\n\n/**\n * Starts a chat host in this process. Clients from `connect` behave like socket clients, without a socket or a second process.\n * @param options - Environment factory and version.\n * @returns The host handle.\n */\nexport async function startInProcessHost(options: InProcessHostOptions): Promise<InProcessHost> {\n const connections = new Set<Connection>()\n let closing: Promise<void> | null = null\n\n const dispatcher = await createHostDispatcher({\n createEnvironment: options.createEnvironment,\n appVersion: options.appVersion ?? 'dev',\n startedAt: Date.now(),\n identity: { kind: 'in-process' },\n lifecycle: {\n // Owned by the embedding window, see the module header.\n shutdown: () => undefined,\n // Clients are this build by construction: never a newer one to retire for.\n retireWhenIdle: () => undefined,\n isRetiring: () => false,\n },\n })\n\n function connect(clientOptions: InProcessClientOptions = {}): Promise<IpcClient> {\n if (closing)\n return Promise.reject(new JsonRpcConnectionClosedError())\n return openClient(dispatcher, clientOptions, connections)\n }\n\n function close(): Promise<void> {\n // Same order as the socket server's shutdown: drain the host, close\n // every connection, then forget the peers without per-peer cleanup.\n closing ??= (async () => {\n await dispatcher.host.drain()\n for (const connection of connections)\n connection.hostClosed()\n connections.clear()\n dispatcher.detachAll()\n })()\n return closing\n }\n\n return {\n host: dispatcher.host,\n connect,\n peerCount: () => dispatcher.peerCount(),\n close,\n }\n}\n"],"mappings":"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"}
|