zidane 8.2.3 → 8.2.5

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.
Files changed (166) hide show
  1. package/dist/{acp-oYRjlh71.js → acp-BIInKhVI.js} +6 -6
  2. package/dist/{acp-oYRjlh71.js.map → acp-BIInKhVI.js.map} +1 -1
  3. package/dist/acp-cli.js +4 -4
  4. package/dist/acp.d.ts +2 -2
  5. package/dist/acp.js +1 -1
  6. package/dist/{agent-CBQglXtH.js → agent-CmhCOmyO.js} +10 -5
  7. package/dist/{agent-CBQglXtH.js.map → agent-CmhCOmyO.js.map} +1 -1
  8. package/dist/agent.d.ts +1 -1
  9. package/dist/agent.js +1 -1
  10. package/dist/chat/pure.d.ts +4 -4
  11. package/dist/chat/pure.js +7 -7
  12. package/dist/chat.d.ts +3 -3
  13. package/dist/chat.js +16 -16
  14. package/dist/{cli-shared-E5m_pI8A.js → cli-shared-GOehTeqk.js} +2 -2
  15. package/dist/{cli-shared-E5m_pI8A.js.map → cli-shared-GOehTeqk.js.map} +1 -1
  16. package/dist/{client-core-EEEX_u6D.d.ts → client-core-Dz8hELs4.d.ts} +15 -5
  17. package/dist/client-core-Dz8hELs4.d.ts.map +1 -0
  18. package/dist/codemode-worker.js +1 -1
  19. package/dist/codemode.js +1 -1
  20. package/dist/{connection-loop-CpgfUmuw.d.ts → connection-loop-dm_TN-QD.d.ts} +3 -3
  21. package/dist/{connection-loop-CpgfUmuw.d.ts.map → connection-loop-dm_TN-QD.d.ts.map} +1 -1
  22. package/dist/contexts/daytona.d.ts +1 -1
  23. package/dist/contexts/e2b.d.ts +1 -1
  24. package/dist/{credentials-B9DfBJP9.js → credentials-DxOQmset.js} +2 -2
  25. package/dist/{credentials-B9DfBJP9.js.map → credentials-DxOQmset.js.map} +1 -1
  26. package/dist/daemon-cli.js +2 -2
  27. package/dist/{dispatcher-Bv9-c6I2.js → dispatcher-D_9_QFO3.js} +22 -18
  28. package/dist/dispatcher-D_9_QFO3.js.map +1 -0
  29. package/dist/{engine-XmoPPB6U.js → engine-BsWBWgTB.js} +6 -6
  30. package/dist/{engine-XmoPPB6U.js.map → engine-BsWBWgTB.js.map} +1 -1
  31. package/dist/{eval-CfQlBR81.js → eval-CIHIF_Ns.js} +3 -3
  32. package/dist/{eval-CfQlBR81.js.map → eval-CIHIF_Ns.js.map} +1 -1
  33. package/dist/eval.d.ts +1 -1
  34. package/dist/eval.js +1 -1
  35. package/dist/{executor-BhthPE1q.js → executor-BSesPPcU.js} +3 -3
  36. package/dist/{executor-BhthPE1q.js.map → executor-BSesPPcU.js.map} +1 -1
  37. package/dist/{extensions-BgBwogRW.js → extensions-BJof-2mi.js} +3 -3
  38. package/dist/{extensions-BgBwogRW.js.map → extensions-BJof-2mi.js.map} +1 -1
  39. package/dist/extensions.d.ts +1 -1
  40. package/dist/extensions.js +1 -1
  41. package/dist/{fold-rules-DSypi36k.d.ts → fold-rules-CMpWNPqk.d.ts} +2 -2
  42. package/dist/{fold-rules-DSypi36k.d.ts.map → fold-rules-CMpWNPqk.d.ts.map} +1 -1
  43. package/dist/{headless-R4pbpTkm.js → headless-Bs9Lb4vs.js} +4 -4
  44. package/dist/{headless-R4pbpTkm.js.map → headless-Bs9Lb4vs.js.map} +1 -1
  45. package/dist/headless.d.ts +1 -1
  46. package/dist/headless.js +1 -1
  47. package/dist/history-worker.js +1 -1
  48. package/dist/{host-scoped-settings-C-Nmb6vr.js → host-scoped-settings-DxxI_yRo.js} +2 -2
  49. package/dist/{host-scoped-settings-C-Nmb6vr.js.map → host-scoped-settings-DxxI_yRo.js.map} +1 -1
  50. package/dist/{host-signals-BFudPyCT.js → host-signals-CUKPZZxC.js} +5 -5
  51. package/dist/{host-signals-BFudPyCT.js.map → host-signals-CUKPZZxC.js.map} +1 -1
  52. package/dist/{index-DyQyDLX1.d.ts → index-4mDRyTGJ.d.ts} +1722 -1691
  53. package/dist/index-4mDRyTGJ.d.ts.map +1 -0
  54. package/dist/{index-CDS7YdUC.d.ts → index-Dlmu8HnG.d.ts} +5 -5
  55. package/dist/{index-CDS7YdUC.d.ts.map → index-Dlmu8HnG.d.ts.map} +1 -1
  56. package/dist/{index-AqRZ3gEz.d.ts → index-QsAN9yjZ.d.ts} +3 -3
  57. package/dist/{index-AqRZ3gEz.d.ts.map → index-QsAN9yjZ.d.ts.map} +1 -1
  58. package/dist/index.d.ts +3 -3
  59. package/dist/index.js +8 -8
  60. package/dist/ipc/remote.d.ts +5 -5
  61. package/dist/ipc/remote.js +3 -3
  62. package/dist/ipc.d.ts +5 -5
  63. package/dist/ipc.js +9 -9
  64. package/dist/{links-rFaWqS2Y.js → links-Bto-5dVu.js} +10 -10
  65. package/dist/{links-rFaWqS2Y.js.map → links-Bto-5dVu.js.map} +1 -1
  66. package/dist/{mcp-allowlist-CLXweyxk.js → mcp-allowlist-BbnTBKNN.js} +2 -2
  67. package/dist/{mcp-allowlist-CLXweyxk.js.map → mcp-allowlist-BbnTBKNN.js.map} +1 -1
  68. package/dist/mcp.d.ts +1 -1
  69. package/dist/{oauth-7_48zR7n.js → oauth-BwPiX0hL.js} +66 -32
  70. package/dist/oauth-BwPiX0hL.js.map +1 -0
  71. package/dist/output/stream-json.d.ts +1 -1
  72. package/dist/output/terminal.d.ts +1 -1
  73. package/dist/plugins.d.ts +1 -1
  74. package/dist/{prelude-HzY_JEGq.js → prelude-qjPUkw4f.js} +26 -2
  75. package/dist/prelude-qjPUkw4f.js.map +1 -0
  76. package/dist/{presets-DXeHsd24.js → presets-C4hkykN-.js} +2 -2
  77. package/dist/{presets-DXeHsd24.js.map → presets-C4hkykN-.js.map} +1 -1
  78. package/dist/presets.d.ts +1 -1
  79. package/dist/presets.js +1 -1
  80. package/dist/{protocol-BIv1Yuvl.js → protocol-Do_i6Ras.js} +3 -1
  81. package/dist/protocol-Do_i6Ras.js.map +1 -0
  82. package/dist/providers/anthropic.d.ts +1 -1
  83. package/dist/providers/arcee.d.ts +1 -1
  84. package/dist/providers/baseten.d.ts +1 -1
  85. package/dist/providers/cerebras.d.ts +1 -1
  86. package/dist/providers/google.d.ts +1 -1
  87. package/dist/providers/local.d.ts +1 -1
  88. package/dist/providers/neuralwatt.d.ts +1 -1
  89. package/dist/providers/openai-compat.d.ts +1 -1
  90. package/dist/providers/openai.d.ts +1 -1
  91. package/dist/providers/openrouter.d.ts +1 -1
  92. package/dist/providers/xai.d.ts +1 -1
  93. package/dist/providers.d.ts +1 -1
  94. package/dist/{registry-eourRLY2.js → registry-DxPP_tAt.js} +3 -3
  95. package/dist/{registry-eourRLY2.js.map → registry-DxPP_tAt.js.map} +1 -1
  96. package/dist/{remote-hosts-DY2J07ut.js → remote-hosts-DcCh7fqp.js} +4 -4
  97. package/dist/{remote-hosts-DY2J07ut.js.map → remote-hosts-DcCh7fqp.js.map} +1 -1
  98. package/dist/restate.d.ts +1 -1
  99. package/dist/{secret-shapes-BjW4l6U0.js → secret-shapes-HvaYVzwc.js} +10 -2
  100. package/dist/secret-shapes-HvaYVzwc.js.map +1 -0
  101. package/dist/session/sqlite.d.ts +1 -1
  102. package/dist/{session-7TUHs42_.js → session-CCsKXID6.js} +6 -2
  103. package/dist/session-CCsKXID6.js.map +1 -0
  104. package/dist/{session-factory-CMwIXE-7.js → session-factory-Ct7J9CK1.js} +6 -6
  105. package/dist/{session-factory-CMwIXE-7.js.map → session-factory-Ct7J9CK1.js.map} +1 -1
  106. package/dist/session.d.ts +2 -2
  107. package/dist/session.js +1 -1
  108. package/dist/{settings-keys-CPdmkTz7.js → settings-keys-CnrJgT1T.js} +4 -4
  109. package/dist/{settings-keys-CPdmkTz7.js.map → settings-keys-CnrJgT1T.js.map} +1 -1
  110. package/dist/{shell-path-B8b3EOtK.js → shell-path-rJDa0OMv.js} +4 -4
  111. package/dist/{shell-path-B8b3EOtK.js.map → shell-path-rJDa0OMv.js.map} +1 -1
  112. package/dist/skills.d.ts +1 -1
  113. package/dist/{spaces-CyjMh5Zf.js → spaces-C_x2bvEl.js} +14 -4
  114. package/dist/spaces-C_x2bvEl.js.map +1 -0
  115. package/dist/{store-L01W0gGI.js → store-BpkWIaSH.js} +10 -30
  116. package/dist/store-BpkWIaSH.js.map +1 -0
  117. package/dist/{todo-edits-BERpCRPj.js → todo-edits-DKoxu7Ss.js} +3 -3
  118. package/dist/{todo-edits-BERpCRPj.js.map → todo-edits-DKoxu7Ss.js.map} +1 -1
  119. package/dist/tools/fetch-url.d.ts +1 -1
  120. package/dist/tools/web-search.d.ts +1 -1
  121. package/dist/{tools-pZVFIJ_K.js → tools-FHEIKGkh.js} +2 -2
  122. package/dist/{tools-pZVFIJ_K.js.map → tools-FHEIKGkh.js.map} +1 -1
  123. package/dist/tools.d.ts +1 -1
  124. package/dist/tools.js +2 -2
  125. package/dist/{transcript-anchors-jHrg-r-H.js → transcript-anchors-BcFLh3ZA.js} +10 -10
  126. package/dist/{transcript-anchors-jHrg-r-H.js.map → transcript-anchors-BcFLh3ZA.js.map} +1 -1
  127. package/dist/{transcript-cache-DXdgVuoy.js → transcript-cache-CdHKtx9y.js} +4 -4
  128. package/dist/{transcript-cache-DXdgVuoy.js.map → transcript-cache-CdHKtx9y.js.map} +1 -1
  129. package/dist/{transcript-reconcile-CPdrNbbR.js → transcript-reconcile-D_SWw6dX.js} +11 -3
  130. package/dist/transcript-reconcile-D_SWw6dX.js.map +1 -0
  131. package/dist/tui.d.ts +7 -7
  132. package/dist/tui.js +24 -23
  133. package/dist/tui.js.map +1 -1
  134. package/dist/{turn-operations-DuGtKuc_.d.ts → turn-operations-Dbk3xPKu.d.ts} +11 -3
  135. package/dist/{turn-operations-DuGtKuc_.d.ts.map → turn-operations-Dbk3xPKu.d.ts.map} +1 -1
  136. package/dist/{types-C0PJmBaO.d.ts → types-CMXR7A0b.d.ts} +2 -2
  137. package/dist/{types-C0PJmBaO.d.ts.map → types-CMXR7A0b.d.ts.map} +1 -1
  138. package/dist/types-CzmghX7C.js.map +1 -1
  139. package/dist/types.d.ts +2 -2
  140. package/dist/{url-D8KZ7Edw.js → url-D4vG7lzO.js} +2 -2
  141. package/dist/{url-D8KZ7Edw.js.map → url-D4vG7lzO.js.map} +1 -1
  142. package/dist/{version-bd3DQJkc.js → version-DOvIuU8M.js} +2 -2
  143. package/dist/{version-bd3DQJkc.js.map → version-DOvIuU8M.js.map} +1 -1
  144. package/dist/{workspace-exec-stream-CyfYgqAh.js → workspace-exec-stream-Bzxczzu2.js} +5 -5
  145. package/dist/{workspace-exec-stream-CyfYgqAh.js.map → workspace-exec-stream-Bzxczzu2.js.map} +1 -1
  146. package/dist/{write-file-QYrcDdl3.js → write-file-ChtRPdEL.js} +3 -3
  147. package/dist/{write-file-QYrcDdl3.js.map → write-file-ChtRPdEL.js.map} +1 -1
  148. package/dist/{ws-CURQ2igk.js → ws-CrD-4Mx6.js} +6 -6
  149. package/dist/{ws-CURQ2igk.js.map → ws-CrD-4Mx6.js.map} +1 -1
  150. package/dist/{ws-client-BVljYbdb.js → ws-client-Dond8vT3.js} +4 -4
  151. package/dist/{ws-client-BVljYbdb.js.map → ws-client-Dond8vT3.js.map} +1 -1
  152. package/docs/CODEMODE.md +6 -0
  153. package/docs/IPC.md +2 -0
  154. package/docs/ONBOARDING.md +1 -1
  155. package/package.json +1 -1
  156. package/dist/client-core-EEEX_u6D.d.ts.map +0 -1
  157. package/dist/dispatcher-Bv9-c6I2.js.map +0 -1
  158. package/dist/index-DyQyDLX1.d.ts.map +0 -1
  159. package/dist/oauth-7_48zR7n.js.map +0 -1
  160. package/dist/prelude-HzY_JEGq.js.map +0 -1
  161. package/dist/protocol-BIv1Yuvl.js.map +0 -1
  162. package/dist/secret-shapes-BjW4l6U0.js.map +0 -1
  163. package/dist/session-7TUHs42_.js.map +0 -1
  164. package/dist/spaces-CyjMh5Zf.js.map +0 -1
  165. package/dist/store-L01W0gGI.js.map +0 -1
  166. package/dist/transcript-reconcile-CPdrNbbR.js.map +0 -1
@@ -1 +0,0 @@
1
- {"version":3,"file":"dispatcher-Bv9-c6I2.js","names":["NAME_RE","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/history/rpc-client.ts","../src/ipc/history/transcript.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/ipc/daemon/redact.ts","../src/ipc/daemon/catalog-entries.ts","../src/ipc/daemon/handlers/catalogs.ts","../src/ipc/daemon/handlers/chat.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/extensions.ts","../src/ipc/daemon/handlers/fs.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/orchestration.ts","../src/ipc/daemon/handlers/presence.ts","../src/ipc/daemon/handlers/queue.ts","../src/ipc/daemon/handlers/resume.ts","../src/ipc/daemon/handlers/session-reads.ts","../src/ipc/daemon/handlers/sessions.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/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"],"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 { SessionStore } from '../../session/index'\nimport type { HostSettings, HostSignal, 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 { 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 and returns the settings in effect afterwards. */\n writeSettings: (patch: Partial<HostSettings>) => HostSettings\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 /**\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 /** 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>): 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)\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 hud.subscribe(() => {\n const state = hud.getState()\n options.broadcast({\n kind: 'hud:state',\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.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 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 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 runtimeConfig = (cwd: string): Promise<ResolvedConfig> => {\n const settings = readSettings()\n const key = [\n cwd,\n JSON.stringify(settings.enabledExtensions ?? null),\n String(settings.loadProjectExtensions === true),\n ].join('\\u0000')\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 })\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 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 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}\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 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 degraded = `${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 degraded = `${name} unavailable: ${err instanceof Error ? err.message : String(err)}`\n throw new WorkerUnavailableError(degraded, 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 */\nimport type { SessionStore } from '../../session/index'\nimport type { SqliteStoreFile } from '../../session/sqlite-store'\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 { InvalidParamsError } from '../daemon/handlers/params'\nimport { changedSessionOf, createTranscriptReplayCache } from '../daemon/handlers/transcript-cache'\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\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 /** 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'>): TranscriptHistoryWorker {\n const { dbPath, create = spawnHistoryWorker, ...rest } = options\n const client = createWorkerRpcClient<HistoryWorkerRequest, SessionEventsPage>({ 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 })\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 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 /** 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] history page fell back to the host thread:', 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 close() {\n closed = true\n worker?.client.close()\n worker = null\n },\n }\n}\n","/** Session artifacts: list, delete, upsert, with change fan-out. */\nimport type { SessionStore } from '../../../session/index'\nimport type { HostSignal } from '../../protocol'\nimport type { Handlers } from './types'\nimport { normalizeArtifactInput } from '../../../session/artifacts'\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 }: {\n store: SessionStore\n broadcast: (signal: HostSignal) => void\n}): Handlers<'sessions.artifacts' | 'artifacts.list' | 'artifacts.delete' | 'artifacts.upsert'> {\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 }\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, remove.\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, readProviderCredentials, removeProviderCredential, removeStoredCredential, setProviderCredential } from '../../../chat/credentials'\n\n/** Longest API key accepted (keys are well under 1 KiB; this bounds a mistaken paste). */\nconst MAX_KEY_LENGTH = 8192\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 auth = detectAuth(dataDir(), { [key]: registry()[key]! })[0]!\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 }\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.remove'> {\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.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 }\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`): the local Settings actions, run on\n * the host for a window attached to a zidane-server.\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 { mcpsWritePath, removeMcpServer, upsertMcpServer } from '../../../chat/mcps-write'\nimport { projectUserPaths } from '../../../chat/project-user-paths'\nimport { ExtensionInstallError, installExtensionFromSpec, removeInstalledExtension, updateInstalledExtension } from '../../../extensions/install'\nimport { abortableInstallIo } from '../../../install/source'\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'\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 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 checkName(c.name, '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\nexport function createCatalogInstallHandlers({ host, env, broadcast, setSettings, options }: {\n host: Pick<ChatHost, 'rebuildAllAgents'>\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 /** Gate, run, audit: every attempt leaves one line, refusals and failures included. */\n async function guarded<T>(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 }\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\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 }, () => {\n const config = checkMcpConfig(p.config)\n const result = upsertMcpServer(mcpsWritePath('user', { home: homedir(), cwd: homedir(), prefix: prefix() }), config)\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 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 = checkName(p.name, '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 rebuild()\n changed('mcps')\n return { removed: true }\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 * 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 { 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): { 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 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 ...(config.scope !== undefined ? { scope: config.scope } : {}),\n ...(config.auth !== undefined ? { auth: config.auth } : {}),\n ...(env ? { env } : {}),\n ...(headers ? { headers } : {}),\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.*`) and the\n * models its credentials can run (`models.list`), so a window editing a\n * server lists the server's skills, MCP servers, extensions, plugins and\n * providers, not its own.\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 { DiscoveredPlugin } from '../../../chat/plugins-discovery'\nimport type { HostModelProvider } from '../../protocol'\nimport type { DaemonEnvironment } from '../environment'\nimport type { Handlers } from './types'\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'\n\ntype CatalogMethod = 'catalog.skills' | 'catalog.mcps' | 'catalog.extensions' | 'catalog.plugins' | 'models.list' | 'models.test' | 'decisions.test'\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 }: { env: DaemonEnvironment, host: Pick<ChatHost, 'resolveFolder' | 'folderCatalog'> }): 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 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 { 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 { servers: found, errors } = discoverProjectMcps({ cwd: dir, prefix: config.prefix, foreignAgents, ruler })\n const machineNames = new Set((project?.mcps ?? []).map(server => server.config.name))\n const servers = [...(project?.mcps ?? []), ...found.filter(server => !machineNames.has(server.config.name))]\n return mcpEntries(servers, errors, settings)\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 '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","/** Runs: send, interrupt, steer, follow-up, running work, and slash-command discovery. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { SendOptions } from '../../protocol'\nimport type { HostPeer } from '../peers'\nimport type { Handlers } from './types'\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 }: {\n host: ChatHost\n clearDraft: (sessionId: string, origin: HostPeer | null) => void\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, ...params } = p as SendOptions\n const result = await host.sendPrompt(params)\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),\n 'chat.followUp': p => host.followUp(p.sessionId, p.message),\n 'chat.pushQueued': async (p, peer) => {\n const result = await host.pushQueued(p.sessionId, p.message, p.activatedSkills)\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","/** 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 and shutdown. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { HelloResult } from '../../protocol'\nimport type { Handlers } from './types'\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 }\n /** The host identity fields `ipc.hello` reports. */\n identity: Pick<HelloResult, 'hostId' | 'hostKind' | 'hostName'>\n}): Handlers<'daemon.info' | '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 }),\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.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.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","/** Extension bus emits from clients whose extensions run client-side. */\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'> {\n return {\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","/** Folder browsing on the host's machine (`fs.roots`, `fs.listDirs`), within its workspace roots. */\nimport type { WorkspaceRoots } from '../workspace-roots'\nimport type { Handlers } from './types'\nimport { optionalString } from './params'\n\nexport function createFsHandlers({ workspace }: { workspace: WorkspaceRoots }): Handlers<'fs.roots' | 'fs.listDirs'> {\n return {\n 'fs.roots': () => workspace.describe(),\n 'fs.listDirs': p => workspace.list(optionalString(p?.path, 'path')),\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","/** Human-in-the-loop: tool approvals and interactions (questions, plans) awaiting an answer. */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { Handlers } from './types'\n\ntype HitlMethod\n = | 'interactions.list' | 'interactions.respond' | 'interactions.cancel' | 'interactions.rehydrate'\n | 'approvals.resolve' | 'approvals.denyAll' | 'approvals.listPending'\n\nexport function createHitlHandlers({ host }: { host: ChatHost }): 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 'interactions.rehydrate': p => host.interactions.rehydrate(p.sessionId),\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}\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); 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 { 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 { 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 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/** `http://<loopback>:<port>/<path>`, nothing else: where an MCP sign-in may send the browser. */\nfunction loopbackRedirect(raw: unknown): string {\n let url: URL | undefined\n try {\n url = typeof raw === 'string' ? new URL(raw) : undefined\n }\n catch {}\n if (!url || url.protocol !== 'http:' || !LOOPBACK_HOSTS.has(url.hostname) || !url.port || url.username || url.password || url.search || url.hash)\n throw new InvalidParamsError('redirectUri must be a loopback URL on the client (http://127.0.0.1:<port>/callback).')\n return url.toString()\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\nexport function createOAuthFlowHandlers({ host, env, auth, isConnected, ttlMs = OAUTH_FLOW_TTL_MS }: {\n host: Pick<ChatHost, 'resolveFolder' | 'rebuildAllAgents'>\n env: DaemonEnvironment\n auth: ProviderAuth\n isConnected: (peer: HostPeer) => 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} {\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, 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 clientRedirectUri = loopbackRedirect(p.redirectUri)\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 const redirectUri = pinnedMcpRedirectUri(entry) ?? clientRedirectUri\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 const flow = register(peer, {\n abort,\n result,\n expectedState: state,\n redirectUri,\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, 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 }\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","/** Which sessions have windows attached, and which one this window watches. */\nimport type { DaemonEnvironment } from '../environment'\nimport type { PeerRegistry } from '../peers'\nimport type { Handlers } from './types'\n\nexport function createPresenceHandlers({ env, peers }: {\n env: DaemonEnvironment\n peers: Pick<PeerRegistry, 'computePresence' | 'broadcastPresence'>\n}): Handlers<'presence.list' | 'presence.watch'> {\n return {\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 { Handlers } from './types'\nimport { boundAttachments } from './drafts'\nimport { InvalidParamsError } from './params'\n\nexport function createQueueHandlers({ host, clearDraft }: {\n host: ChatHost\n clearDraft: (sessionId: string, origin: HostPeer | null) => void\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 result = await host.queueAdd(p.sessionId, text, activatedSkills, attachments, asCommand)\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 * 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. 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 { 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.setExtensionState'\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.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.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","/** Session rows: list, create, delete, and metadata edits (title, archive, agent, model, folder). */\nimport type { ChatHost } from '../../../chat/host/engine'\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 } from '../../../chat/orchestration'\nimport { PINNED_SKILLS_META_KEY, pinnedSkillsValue, readPinnedSkills } from '../../../chat/pinned-skills'\nimport { DEFAULT_SPACE_ID, readSessionSpaceId, SPACE_METADATA_KEY } from '../../../chat/spaces'\nimport { deriveSessionTitle, runInProgress, sessionEnvironmentSummary } from '../../../chat/store'\nimport { loadOrThrow } from './session-load'\n\ntype SessionMethod\n = | 'sessions.list' | 'sessions.create' | 'sessions.delete' | 'sessions.setTitle' | 'sessions.setArchived' | 'sessions.setFavorite' | 'sessions.setSpace'\n | 'sessions.setAgentId' | 'sessions.setEffort' | 'sessions.setModel' | 'sessions.setModelOptions' | 'sessions.setFolder'\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 /**\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): 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 = 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 'sessions.create': p => createSessionRow(p),\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 // 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': p => patchSessionMeta(p.sessionId, { archived: p.archived }),\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 // 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\nasync 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)\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/** 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)\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","/** Host settings and the runtime registry: read, write (rebuilding what a change requires), reload. */\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 { InvalidParamsError } from './params'\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'> {\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 }\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","/**\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 { isWindowOnlySetting } from '../../chat/host-scoped-settings'\nimport { parseMcpsFile } from '../../chat/mcps-discovery'\nimport { 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, 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 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 (!NAME_RE.test(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 ---------------------------------------------------\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 { 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'>\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, 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 {\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.remove'\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 => [`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.remove': (p, peer) => after(() => handlers['auth.remove'](p, peer), r => (r.removed ? [`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 : []),\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","/** Commands and file access inside a session's workspace (its execution environment). */\nimport type { ChatHost } from '../../../chat/host/engine'\nimport type { Handlers } from './types'\n\ntype WorkspaceMethod\n = | 'sessions.workspaceExec' | 'sessions.workspaceReadFile' | 'sessions.workspaceWriteFile'\n | 'sessions.workspaceListFiles' | 'sessions.workspaceFileSize'\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 }\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_PROTOCOL_VERSION } from '../protocol'\n\nexport type HelloVerdict\n /** `retire`: attach, but the host must exit at its first idle point. */\n = | { accept: true, retire: boolean }\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\nfunction evaluateServerHello(params: Partial<HelloParams>): HelloVerdict {\n if (params.protocolVersion === IPC_PROTOCOL_VERSION)\n return { accept: true, retire: false }\n const client = typeof params.protocolVersion === 'number' ? params.protocolVersion : undefined\n const upgrade = client !== undefined && client > IPC_PROTOCOL_VERSION ? 'server' : 'client'\n return {\n accept: false,\n message: `Protocol version mismatch: the server speaks v${IPC_PROTOCOL_VERSION}, 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 }\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 }\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 { randomUUID } from 'node:crypto'\nimport { mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { hostname } from 'node:os'\nimport { join } from 'node:path'\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 UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i\nconst FILE = 'host-id'\n\nfunction readId(path: string): string | undefined {\n try {\n const id = readFileSync(path, 'utf8').trim()\n return UUID.test(id) ? id : undefined\n }\n catch {\n return undefined\n }\n}\n\n/**\n * The id persisted in `dataDir`, created on first use. Two processes starting\n * at once agree: the file is created exclusively (`wx`) and the loser reads\n * the winner's id. A missing or corrupt file gets a fresh id.\n */\nfunction readOrCreateHostId(dataDir: string): string | undefined {\n const path = join(dataDir, FILE)\n const existing = readId(path)\n if (existing)\n return existing\n const id = randomUUID()\n try {\n mkdirSync(dataDir, { recursive: true })\n writeFileSync(path, `${id}\\n`, { flag: 'wx', mode: 0o600 })\n return id\n }\n catch (err) {\n if ((err as NodeJS.ErrnoException).code === 'EEXIST') {\n // Another process won the race, or the file is corrupt: theirs if valid, else replace it.\n const raced = readId(path)\n if (raced)\n return raced\n try {\n writeFileSync(path, `${id}\\n`, { mode: 0o600 })\n // Re-read: a concurrent replacer may have written last.\n return readId(path) ?? id\n }\n catch {\n return undefined\n }\n }\n return undefined\n }\n}\n\nexport function resolveHostIdentity(dataDir: string, options: HostIdentityOptions): HostIdentity {\n return {\n id: readOrCreateHostId(dataDir),\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'\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\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, 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. 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, readdirSync, realpathSync, statSync } from 'node:fs'\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\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}\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 }\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 { HelloParams, HelloResult, HostSignal } from '../protocol'\nimport type { DaemonEnvironment } from './environment'\nimport type { RemoteInstallsOptions } from './handlers/catalog-install'\nimport type { MachineLinksHandlerOptions } from './handlers/machine-links'\nimport type { MachineServeOptions } from './handlers/machine-serve'\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 { AcpErrorCode } from '../../acp/types'\nimport { createChatHost } from '../../chat/host/engine'\nimport { ZIDANE_VERSION } from '../../version'\nimport { createHostTranscriptPager } from '../history/index'\nimport { IPC_PROTOCOL_VERSION, IpcErrorCode, MachineErrorCode, PING_METHOD } from '../protocol'\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 { createContextHandlers } from './handlers/context'\nimport { createDaemonHandlers } from './handlers/daemon'\nimport { createDraftHandlers } from './handlers/drafts'\nimport { createEnvironmentHandlers } from './handlers/environments'\nimport { createExtensionHandlers } from './handlers/extensions'\nimport { createFsHandlers } from './handlers/fs'\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 { createOrchestrationHandlers } from './handlers/orchestration'\nimport { checkParams, InvalidParamsError } from './handlers/params'\nimport { createPresenceHandlers } from './handlers/presence'\nimport { createQueueHandlers } from './handlers/queue'\nimport { createResumeHandlers } from './handlers/resume'\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 { 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 { 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 /** Mint machine tokens for clients (`tokens.createMachineToken`): a zidane-server's token store. Absent: refused. */\n tokens?: { createMachineToken: (name: string, by: string | undefined) => { id: string, name: string, token: string } }\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 /**\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\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 /** 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}\n\n/** A handler's throw, as the outcome its caller gets. */\nfunction failureOutcome(err: unknown): DispatchOutcome {\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 return { ok: false, code: IpcErrorCode.HandlerFailed, message: err instanceof Error ? err.message : String(err) }\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 host.approvals.rehydrate()\n\n const store = env.store\n const identity = resolveHostIdentity(env.userDataDir(), options.identity ?? { kind: 'daemon' })\n const identityFields = {\n ...(identity.id ? { hostId: identity.id } : {}),\n hostKind: identity.kind,\n hostName: identity.name,\n }\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 oauth = createOAuthFlowHandlers({ host, env, auth, isConnected: peers.has, ...(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 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 peers.onClose(browser.releasePeer)\n peers.onClose(terminal.releasePeer)\n peers.onClose(launchOverrides.releasePeer)\n peers.onClose(machineServe.releasePeer)\n peers.onClose(execStreams.releasePeer)\n peers.onClose(oauth.releasePeer)\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 }),\n ...createQueueHandlers({ host, clearDraft: drafts.clearDraft }),\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 ...createFsHandlers({ workspace }),\n ...authHandlers,\n ...oauth.methods,\n ...installs,\n ...createCatalogHandlers({ env, host }),\n ...createArtifactHandlers({ store, broadcast }),\n ...createHistoryHandlers({ host, store }),\n ...createTodoHandlers({ host, store }),\n ...createOrchestrationHandlers({ host }),\n ...createHitlHandlers({ host }),\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 'tokens.createMachineToken': (p, peer) => {\n if (!options.tokens)\n throw new Error('This host has no tokens to mint (only a zidane-server does).')\n if (typeof p.name !== 'string' || p.name.trim() === '')\n throw new InvalidParamsError('tokens.createMachineToken: \"name\" must be a non-empty string.')\n // Counted against, and audited with, the token that asks.\n return options.tokens.createMachineToken(p.name.trim().slice(0, 100), peer.principal)\n },\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 'auth.setApiKey': authHandlers['auth.setApiKey'],\n 'auth.remove': authHandlers['auth.remove'],\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 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 ...(machineServe.allowed() ? { machineServe: true } : {}),\n ...(remoteInstallsAllowed(options.remoteInstalls) ? { remoteInstalls: true } : {}),\n ...(options.sync ? { sync: true } : {}),\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 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)\n }\n }\n\n return {\n host,\n addPeer: peers.add,\n removePeer: peers.remove,\n detachAll: peers.clear,\n peerCount: peers.size,\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 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 }\n}\n"],"mappings":"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"}