@asm-agent/coding-agent 0.8.7 → 0.9.0

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 (195) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +2 -7
  3. package/dist/asm-agent-runtime/src/__pycache__/asm_cm_driver.cpython-313.pyc +0 -0
  4. package/dist/asm-agent-runtime/src/__pycache__/phase76_address_head.cpython-313.pyc +0 -0
  5. package/dist/asm-agent-runtime/src/rlm/__init__.py +1 -1
  6. package/dist/asm-agent-runtime/src/rlm/__pycache__/__init__.cpython-312.pyc +0 -0
  7. package/dist/asm-agent-runtime/src/rlm/__pycache__/__init__.cpython-313.pyc +0 -0
  8. package/dist/asm-agent-runtime/src/rlm/__pycache__/_winjob.cpython-313.pyc +0 -0
  9. package/dist/asm-agent-runtime/src/rlm/__pycache__/bash.cpython-312.pyc +0 -0
  10. package/dist/asm-agent-runtime/src/rlm/__pycache__/bash.cpython-313.pyc +0 -0
  11. package/dist/asm-agent-runtime/src/rlm/__pycache__/harness.cpython-313.pyc +0 -0
  12. package/dist/asm-agent-runtime/src/rlm/__pycache__/mcp.cpython-312.pyc +0 -0
  13. package/dist/asm-agent-runtime/src/rlm/__pycache__/mcp.cpython-313.pyc +0 -0
  14. package/dist/asm-agent-runtime/src/rlm/__pycache__/mcp_base.cpython-312.pyc +0 -0
  15. package/dist/asm-agent-runtime/src/rlm/__pycache__/mcp_base.cpython-313.pyc +0 -0
  16. package/dist/asm-agent-runtime/src/rlm/__pycache__/repl.cpython-312.pyc +0 -0
  17. package/dist/asm-agent-runtime/src/rlm/__pycache__/repl.cpython-313.pyc +0 -0
  18. package/dist/asm-agent-runtime/src/rlm/__pycache__/skill.cpython-313.pyc +0 -0
  19. package/dist/asm-agent-runtime/src/rlm/bash.py +94 -31
  20. package/dist/asm-agent-runtime/src/rlm/repl.md +3 -3
  21. package/dist/asm-agent-runtime/src/rlm/repl.py +46 -45
  22. package/dist/asm-agent-runtime/test/__pycache__/test_agent_message_skill.cpython-313.pyc +0 -0
  23. package/dist/asm-agent-runtime/test/__pycache__/test_bash.cpython-313.pyc +0 -0
  24. package/dist/asm-agent-runtime/test/__pycache__/test_harness.cpython-313.pyc +0 -0
  25. package/dist/asm-agent-runtime/test/__pycache__/test_mcp.cpython-313.pyc +0 -0
  26. package/dist/asm-agent-runtime/test/__pycache__/test_mcp_base.cpython-313.pyc +0 -0
  27. package/dist/asm-agent-runtime/test/__pycache__/test_repl.cpython-313.pyc +0 -0
  28. package/dist/asm-agent-runtime/test/__pycache__/test_subagent_registry.cpython-313.pyc +0 -0
  29. package/dist/asm-agent-runtime/test/__pycache__/test_winjob.cpython-313.pyc +0 -0
  30. package/dist/asm-agent-runtime/test/test_bash.py +74 -19
  31. package/dist/asm-agent-runtime/test/test_repl.py +67 -3
  32. package/dist/asm-agent-runtime/uv.lock +446 -155
  33. package/dist/bundle/{anthropic-XSMQHGYB.js → anthropic-ZOZNPFXS.js} +2 -2
  34. package/dist/bundle/{azure-openai-responses-XLQAIKKH.js → azure-openai-responses-TDHCU647.js} +2 -2
  35. package/dist/bundle/{bundled-modules-5OCN73BM.js → bundled-modules-Q2YODC4B.js} +3 -3
  36. package/dist/bundle/{chunk-IAQLPSMN.js → chunk-AMKLNEAK.js} +47 -47
  37. package/dist/bundle/{chunk-2LPSALBF.js → chunk-FPY7FFJS.js} +978 -1821
  38. package/dist/bundle/{chunk-E3YE2Q7A.js → chunk-G6SC4YYW.js} +4973 -1926
  39. package/dist/bundle/{chunk-YPNK4MRU.js → chunk-QLHAP3FT.js} +1 -1
  40. package/dist/bundle/{cli-main-QYX5R3LF.js → cli-main-277AG2BR.js} +3 -3
  41. package/dist/bundle/cli.js +1 -1
  42. package/dist/bundle/{google-ZXJEPWJA.js → google-Q3AJWUOY.js} +1 -1
  43. package/dist/bundle/{google-vertex-WAF3RIJ6.js → google-vertex-2CSNOUBS.js} +1 -1
  44. package/dist/bundle/{main-EOUAQCJH.js → main-TNXWJXIU.js} +3 -3
  45. package/dist/bundle/{mistral-GDZXSXRS.js → mistral-XRYJGLLG.js} +1 -1
  46. package/dist/bundle/{openai-codex-responses-7XMPW4LG.js → openai-codex-responses-C6BRO2BN.js} +2 -2
  47. package/dist/bundle/{openai-completions-LNSVGDMF.js → openai-completions-DNXCK2JW.js} +4 -4
  48. package/dist/bundle/{openai-responses-MFZOBMIT.js → openai-responses-BEMWVIXE.js} +2 -2
  49. package/dist/config.d.ts +0 -1
  50. package/dist/config.d.ts.map +1 -1
  51. package/dist/config.js +0 -3
  52. package/dist/config.js.map +1 -1
  53. package/dist/core/agent-session-config.d.ts +1 -2
  54. package/dist/core/agent-session-config.d.ts.map +1 -1
  55. package/dist/core/agent-session-config.js +0 -3
  56. package/dist/core/agent-session-config.js.map +1 -1
  57. package/dist/core/agent-session-runtime.d.ts.map +1 -1
  58. package/dist/core/agent-session-runtime.js +0 -8
  59. package/dist/core/agent-session-runtime.js.map +1 -1
  60. package/dist/core/agent-session-services.d.ts +0 -2
  61. package/dist/core/agent-session-services.d.ts.map +1 -1
  62. package/dist/core/agent-session-services.js +0 -22
  63. package/dist/core/agent-session-services.js.map +1 -1
  64. package/dist/core/agent-session.d.ts +8 -1
  65. package/dist/core/agent-session.d.ts.map +1 -1
  66. package/dist/core/agent-session.js +100 -22
  67. package/dist/core/agent-session.js.map +1 -1
  68. package/dist/core/kernel/bootstrap.d.ts.map +1 -1
  69. package/dist/core/kernel/bootstrap.js +1 -1
  70. package/dist/core/kernel/bootstrap.js.map +1 -1
  71. package/dist/core/kernel/repl-manager.d.ts +32 -8
  72. package/dist/core/kernel/repl-manager.d.ts.map +1 -1
  73. package/dist/core/kernel/repl-manager.js +401 -102
  74. package/dist/core/kernel/repl-manager.js.map +1 -1
  75. package/dist/core/kernel/shared.d.ts +11 -7
  76. package/dist/core/kernel/shared.d.ts.map +1 -1
  77. package/dist/core/kernel/shared.js +2 -5
  78. package/dist/core/kernel/shared.js.map +1 -1
  79. package/dist/core/mcp/mcp-manager.d.ts +4 -2
  80. package/dist/core/mcp/mcp-manager.d.ts.map +1 -1
  81. package/dist/core/mcp/mcp-manager.js +9 -7
  82. package/dist/core/mcp/mcp-manager.js.map +1 -1
  83. package/dist/core/model-registry.d.ts.map +1 -1
  84. package/dist/core/model-registry.js +1 -1
  85. package/dist/core/model-registry.js.map +1 -1
  86. package/dist/core/ollama-models.d.ts +3 -1
  87. package/dist/core/ollama-models.d.ts.map +1 -1
  88. package/dist/core/ollama-models.js +31 -10
  89. package/dist/core/ollama-models.js.map +1 -1
  90. package/dist/core/prime-inference-auth.d.ts +0 -9
  91. package/dist/core/prime-inference-auth.d.ts.map +1 -1
  92. package/dist/core/prime-inference-auth.js +0 -50
  93. package/dist/core/prime-inference-auth.js.map +1 -1
  94. package/dist/core/provider-display-names.d.ts.map +1 -1
  95. package/dist/core/provider-display-names.js +0 -1
  96. package/dist/core/provider-display-names.js.map +1 -1
  97. package/dist/core/session-manager.d.ts +0 -4
  98. package/dist/core/session-manager.d.ts.map +1 -1
  99. package/dist/core/session-manager.js +0 -22
  100. package/dist/core/session-manager.js.map +1 -1
  101. package/dist/core/settings-manager.d.ts +4 -16
  102. package/dist/core/settings-manager.d.ts.map +1 -1
  103. package/dist/core/settings-manager.js +13 -43
  104. package/dist/core/settings-manager.js.map +1 -1
  105. package/dist/core/slash-commands.d.ts.map +1 -1
  106. package/dist/core/slash-commands.js +0 -5
  107. package/dist/core/slash-commands.js.map +1 -1
  108. package/dist/core/tools/acp-mcp.d.ts +6 -0
  109. package/dist/core/tools/acp-mcp.d.ts.map +1 -0
  110. package/dist/core/tools/acp-mcp.js +86 -0
  111. package/dist/core/tools/acp-mcp.js.map +1 -0
  112. package/dist/core/tools/index.d.ts +1 -0
  113. package/dist/core/tools/index.d.ts.map +1 -1
  114. package/dist/core/tools/index.js +1 -0
  115. package/dist/core/tools/index.js.map +1 -1
  116. package/dist/core/tools/ipython.d.ts.map +1 -1
  117. package/dist/core/tools/ipython.js +9 -4
  118. package/dist/core/tools/ipython.js.map +1 -1
  119. package/dist/main.d.ts.map +1 -1
  120. package/dist/main.js +2 -11
  121. package/dist/main.js.map +1 -1
  122. package/dist/modes/acp/acp-mode.d.ts.map +1 -1
  123. package/dist/modes/acp/acp-mode.js +1 -1
  124. package/dist/modes/acp/acp-mode.js.map +1 -1
  125. package/dist/modes/agent-connection/daemon-agent-connection.d.ts +0 -2
  126. package/dist/modes/agent-connection/daemon-agent-connection.d.ts.map +1 -1
  127. package/dist/modes/agent-connection/daemon-agent-connection.js +0 -2
  128. package/dist/modes/agent-connection/daemon-agent-connection.js.map +1 -1
  129. package/dist/modes/agents-view/agents-view-mode.d.ts.map +1 -1
  130. package/dist/modes/agents-view/agents-view-mode.js +0 -19
  131. package/dist/modes/agents-view/agents-view-mode.js.map +1 -1
  132. package/dist/modes/daemon/daemon-mode.d.ts +1 -10
  133. package/dist/modes/daemon/daemon-mode.d.ts.map +1 -1
  134. package/dist/modes/daemon/daemon-mode.js +134 -274
  135. package/dist/modes/daemon/daemon-mode.js.map +1 -1
  136. package/dist/modes/daemon/daemon-protocol.d.ts +11 -5
  137. package/dist/modes/daemon/daemon-protocol.d.ts.map +1 -1
  138. package/dist/modes/daemon/daemon-protocol.js +6 -8
  139. package/dist/modes/daemon/daemon-protocol.js.map +1 -1
  140. package/dist/modes/daemon/daemon-supervisor.d.ts +0 -3
  141. package/dist/modes/daemon/daemon-supervisor.d.ts.map +1 -1
  142. package/dist/modes/daemon/daemon-supervisor.js +18 -52
  143. package/dist/modes/daemon/daemon-supervisor.js.map +1 -1
  144. package/dist/modes/daemon/daemon-worker-protocol.d.ts +1 -6
  145. package/dist/modes/daemon/daemon-worker-protocol.d.ts.map +1 -1
  146. package/dist/modes/daemon/daemon-worker-protocol.js +0 -2
  147. package/dist/modes/daemon/daemon-worker-protocol.js.map +1 -1
  148. package/dist/modes/interactive/auth-flows.d.ts +0 -2
  149. package/dist/modes/interactive/auth-flows.d.ts.map +1 -1
  150. package/dist/modes/interactive/auth-flows.js +1 -101
  151. package/dist/modes/interactive/auth-flows.js.map +1 -1
  152. package/dist/modes/interactive/components/assistant-message.d.ts +6 -1
  153. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  154. package/dist/modes/interactive/components/assistant-message.js +13 -3
  155. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  156. package/dist/modes/interactive/components/footer.d.ts +1 -1
  157. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  158. package/dist/modes/interactive/components/footer.js +2 -2
  159. package/dist/modes/interactive/components/footer.js.map +1 -1
  160. package/dist/modes/interactive/components/mermaid.d.ts +12 -0
  161. package/dist/modes/interactive/components/mermaid.d.ts.map +1 -0
  162. package/dist/modes/interactive/components/mermaid.js +63 -0
  163. package/dist/modes/interactive/components/mermaid.js.map +1 -0
  164. package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
  165. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  166. package/dist/modes/interactive/components/settings-selector.js +10 -0
  167. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  168. package/dist/modes/interactive/feature-hints.d.ts.map +1 -1
  169. package/dist/modes/interactive/feature-hints.js +0 -4
  170. package/dist/modes/interactive/feature-hints.js.map +1 -1
  171. package/dist/modes/interactive/interactive-mode.d.ts +1 -7
  172. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  173. package/dist/modes/interactive/interactive-mode.js +23 -279
  174. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  175. package/dist/utils/version-check.d.ts.map +1 -1
  176. package/dist/utils/version-check.js +1 -1
  177. package/dist/utils/version-check.js.map +1 -1
  178. package/docs/settings.md +1 -31
  179. package/docs/usage.md +1 -4
  180. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  181. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  182. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  183. package/examples/extensions/sandbox/package-lock.json +2 -2
  184. package/examples/extensions/sandbox/package.json +1 -1
  185. package/examples/extensions/with-deps/package-lock.json +2 -2
  186. package/examples/extensions/with-deps/package.json +1 -1
  187. package/package.json +6 -5
  188. package/dist/core/agent-traces.d.ts +0 -130
  189. package/dist/core/agent-traces.d.ts.map +0 -1
  190. package/dist/core/agent-traces.js +0 -746
  191. package/dist/core/agent-traces.js.map +0 -1
  192. package/dist/core/telemetry.d.ts +0 -92
  193. package/dist/core/telemetry.d.ts.map +0 -1
  194. package/dist/core/telemetry.js +0 -633
  195. package/dist/core/telemetry.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"daemon-agent-connection.d.ts","sourceRoot":"","sources":["../../../src/modes/agent-connection/daemon-agent-connection.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport type { AgentMessage, ThinkingLevel } from \"@asm-agent/agent\";\nimport type { ImageContent, ServiceTier, Transport } from \"@asm-agent/ai\";\nimport { appendRotatingLog, getAgentLogPath, getDaemonLogPath } from \"../../config.js\";\nimport type { AgentSessionMessageReceipt, AgentSessionMessageSafetyStatus } from \"../../core/agent-messages.js\";\nimport type { AgentSessionEvent } from \"../../core/agent-session.js\";\nimport type { AgentSessionRuntimeConfig } from \"../../core/agent-session-config.js\";\nimport type { AgentAutonomousStatus } from \"../../core/autonomous.js\";\nimport type { BashResult } from \"../../core/bash-executor.js\";\nimport type { CompactionResult } from \"../../core/compaction/index.js\";\nimport type { ContextTreeNode } from \"../../core/context-tree.js\";\nimport type {\n\tAgentCronJob,\n\tAgentHeartbeatDeliveryMode,\n\tAgentHeartbeatManagementAction,\n\tAgentHeartbeatUpdateAction,\n} from \"../../core/cron-jobs.js\";\nimport type { AcpMcpServerConfig } from \"../../core/mcp/acp-mcp-types.js\";\nimport type { RefinementResult } from \"../../core/refinement/index.js\";\nimport type { DeleteSessionFileResult } from \"../../core/session-file-actions.js\";\nimport { SessionAlreadyActiveError } from \"../../core/session-lease.js\";\nimport type { SessionStats } from \"../../core/session-stats.js\";\nimport {\n\tDaemonCapabilityUnavailableError,\n\ttype DaemonClient,\n\tgetDaemonSocketCloseReason,\n} from \"../daemon/daemon-client.js\";\nimport { deserializeDaemonError } from \"../daemon/daemon-errors.js\";\nimport {\n\tcollectDaemonClientEnv,\n\tcollectDaemonLaunchEnv,\n\ttype DaemonAttachResult,\n\ttype DaemonCommand,\n\ttype DaemonEventCursor,\n\ttype DaemonOutbound,\n\ttype DaemonReplayInfo,\n\ttype DaemonSessionClosedReason,\n\ttype DaemonSessionSnapshot,\n\tisUnknownDaemonCommandError,\n} from \"../daemon/daemon-protocol.js\";\nimport type { SessionSummary } from \"../daemon/daemon-session-list.js\";\nimport { listDaemonHeartbeats } from \"../daemon/heartbeat-catalog.js\";\nimport {\n\tdeleteDaemonSavedSession,\n\tlistDaemonSavedSessions,\n\trenameDaemonSavedSession,\n} from \"../daemon/saved-session-catalog.js\";\nimport type {\n\tAgentConnection,\n\tAgentConnectionBeforeSessionInvalidateListener,\n\tAgentConnectionEvent,\n\tAgentConnectionEventListener,\n\tAgentConnectionExecuteBashOptions,\n\tAgentConnectionExtensionUiResponse,\n\tAgentConnectionForkOptions,\n\tAgentConnectionHeadlessCompletionOptions,\n\tAgentConnectionHeartbeat,\n\tAgentConnectionModel,\n\tAgentConnectionModelCatalog,\n\tAgentConnectionModelCycleResult,\n\tAgentConnectionNavigateTreeOptions,\n\tAgentConnectionNavigateTreeResult,\n\tAgentConnectionNewSessionOptions,\n\tAgentConnectionPromptOptions,\n\tAgentConnectionQueuedMessageLane,\n\tAgentConnectionQueuedMessageMutation,\n\tAgentConnectionQueuedMessageMutationStatus,\n\tAgentConnectionQueueMode,\n\tAgentConnectionQueueState,\n\tAgentConnectionResourceSnapshot,\n\tAgentConnectionRlmChildAgentSnapshot,\n\tAgentConnectionSavedSessionInfo,\n\tAgentConnectionSavedSessionScope,\n\tAgentConnectionScopedModel,\n\tAgentConnectionSessionContext,\n\tAgentConnectionSessionHeader,\n\tAgentConnectionSessionInputPause,\n\tAgentConnectionSessionListCallbacks,\n\tAgentConnectionSessionTreeFlatNode,\n\tAgentConnectionSessionTreeNode,\n\tAgentConnectionSessionWatcher,\n\tAgentConnectionSideQuestionEvent,\n\tAgentConnectionSideQuestionTurn,\n\tAgentConnectionSlashCommand,\n\tAgentConnectionSnapshot,\n\tAgentConnectionState,\n\tAgentConnectionSwitchSessionOptions,\n\tAgentConnectionToolDefinition,\n\tAgentConnectionUserMessage,\n} from \"./types.js\";\nimport { AgentConnectionPromptAdmissionError } from \"./types.js\";\n\ntype DistributiveOmit<T, K extends keyof T> = T extends unknown ? Omit<T, K> : never;\ntype DaemonCommandBody = DistributiveOmit<DaemonCommand, \"id\">;\ntype DaemonSnapshotBegin = Extract<DaemonOutbound, { type: \"session_snapshot_begin\" }>;\n\ninterface DaemonSnapshotAssembly {\n\tbegin?: DaemonSnapshotBegin;\n\tchunks: Map<number, AgentMessage[]>;\n\tpromise: Promise<DaemonSessionSnapshot>;\n\tresolve: (snapshot: DaemonSessionSnapshot) => void;\n\treject: (error: Error) => void;\n\ttimeout: ReturnType<typeof setTimeout>;\n}\n\nexport const DAEMON_REFINE_REQUEST_TIMEOUT_MS = 10 * 60 * 1000;\nconst DAEMON_LONG_RUNNING_REQUEST_TIMEOUT_MS = 24 * 60 * 60 * 1000;\nexport const DAEMON_RECONNECT_TIMEOUT_MS = 60_000;\nexport const DAEMON_SNAPSHOT_TIMEOUT_MS = 30_000;\nconst MAX_IGNORED_SNAPSHOT_IDS = 128;\nconst UPDATE_RECONNECT_TIMEOUT_MS = 120000;\nconst UPDATE_RECONNECT_RETRY_MS = 100;\nconst MAX_COMPLETED_SNAPSHOTS = 128;\nconst OWNED_SESSION_DISPOSE_RECONNECT_WAIT_MS = 10_000;\nconst updateTransportReconnects = new WeakMap<DaemonClient, Promise<void>>();\n\nfunction delay(ms: number): Promise<void> {\n\treturn new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction formatErrorSentence(error: unknown): string {\n\tconst message = (error instanceof Error ? error.message : String(error)).trim();\n\tif (!message) {\n\t\treturn \"Unknown daemon error.\";\n\t}\n\treturn /[.!?]$/.test(message) ? message : `${message}.`;\n}\n\nfunction reconnectDaemonTransportAfterUpdate(client: DaemonClient): Promise<void> {\n\tconst existing = updateTransportReconnects.get(client);\n\tif (existing) {\n\t\treturn existing;\n\t}\n\tconst reconnectPromise = Promise.resolve()\n\t\t.then(async () => {\n\t\t\tclient.disconnectForReconnect(\"update\");\n\t\t\tconst deadline = Date.now() + UPDATE_RECONNECT_TIMEOUT_MS;\n\t\t\tlet lastError: unknown;\n\t\t\twhile (Date.now() < deadline) {\n\t\t\t\ttry {\n\t\t\t\t\tawait client.reconnect(1000);\n\t\t\t\t\treturn;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tlastError = error;\n\t\t\t\t}\n\t\t\t\tawait delay(UPDATE_RECONNECT_RETRY_MS);\n\t\t\t}\n\t\t\tthrow lastError ?? new Error(\"the updated daemon did not become available\");\n\t\t})\n\t\t.finally(() => {\n\t\t\tif (updateTransportReconnects.get(client) === reconnectPromise) {\n\t\t\t\tupdateTransportReconnects.delete(client);\n\t\t\t}\n\t\t});\n\tupdateTransportReconnects.set(client, reconnectPromise);\n\treturn reconnectPromise;\n}\n\nexport interface DaemonAgentConnectionOptions {\n\tcloseClientOnDispose?: boolean;\n\t/** Restart/probe the detached supervisor after a transient socket loss. */\n\trecoverDaemon?: () => Promise<void>;\n\t/** Bound supervisor recovery before surfacing a fatal connection error. */\n\treconnectTimeoutMs?: number;\n\t/** Bound an incomplete streamed snapshot before failing the attach or resync. */\n\tsnapshotTimeoutMs?: number;\n\t/**\n\t * Send this client's allowlisted env (herdr pane identity) with attach so\n\t * an env-less session (e.g. cron-created) adopts it. Set only by the\n\t * primary interactive connection — the daemon adopts-if-absent, never\n\t * rebinds, so watchers must not send env at all.\n\t */\n\tsendClientEnv?: boolean;\n\t/** Advertise support for interactive extension dialogs. */\n\tsupportsExtensionUi?: boolean;\n\t/** Dispose the connection by stopping its hidden worker instead of detaching. */\n\townedSession?: boolean;\n\t/** Fresh runtime context used only if the owned worker must be relaunched. */\n\townedSessionRecoveryConfig?: AgentSessionRuntimeConfig;\n\t/** Require the target worker to have been created with telemetry disabled. */\n\ttelemetryDisabled?: true;\n}\n\n/**\n * AgentConnection adapter for the local daemon JSONL socket transport.\n *\n * InteractiveMode depends only on AgentConnection; local socket ownership and\n * daemon command details stay inside this adapter.\n */\nexport function buildSessionTreeFromFlatNodes(\n\tflatNodes: readonly AgentConnectionSessionTreeFlatNode[],\n): AgentConnectionSessionTreeNode[] {\n\tconst byId = new Map<string, AgentConnectionSessionTreeNode>();\n\tconst roots: AgentConnectionSessionTreeNode[] = [];\n\tfor (const flatNode of flatNodes) {\n\t\tbyId.set(flatNode.entry.id, { ...flatNode, children: [] });\n\t}\n\tfor (const flatNode of flatNodes) {\n\t\tconst entry = flatNode.entry;\n\t\tconst node = byId.get(entry.id)!;\n\t\tconst parent = entry.parentId === null || entry.parentId === entry.id ? undefined : byId.get(entry.parentId);\n\t\tif (parent) parent.children.push(node);\n\t\telse roots.push(node);\n\t}\n\t// Match SessionManager.getTree() ordering without recursively walking deep\n\t// chains: every node is already indexed, so sort each sibling array directly.\n\tfor (const node of byId.values()) {\n\t\tnode.children.sort(\n\t\t\t(left, right) => new Date(left.entry.timestamp).getTime() - new Date(right.entry.timestamp).getTime(),\n\t\t);\n\t}\n\treturn roots;\n}\n\nexport class DaemonAgentConnection implements AgentConnection {\n\tprivate readonly listeners = new Set<AgentConnectionEventListener>();\n\tprivate readonly unsubscribeDaemonMessages: () => void;\n\tprivate readonly unsubscribeDaemonClose: () => void;\n\tprivate readonly clientId = `daemon-agent-connection:${randomUUID()}`;\n\tprivate readonly sessionInputPauses = new Map<string, Promise<AgentConnectionSessionInputPause>>();\n\tprivate sessionInputPauseGeneration = 0;\n\tprivate ownedSessionPromotionTail = Promise.resolve();\n\tprivate lastEventCursor: DaemonEventCursor | undefined;\n\tprivate readonly retiredEventGenerations = new Set<string>();\n\tprivate lastEventSequence: number | undefined;\n\tprivate childRosterSequence: number | undefined;\n\tprivate latestSnapshot: AgentConnectionSnapshot | undefined;\n\tprivate latestSnapshotIsFresh = false;\n\tprivate attachedSessionId: string | undefined;\n\tprivate attachedSessionFile: string | undefined;\n\tprivate daemonLogPath: string | undefined;\n\tprivate updateRestartPending = false;\n\tprivate updateReconnectFailed = false;\n\tprivate terminalCloseEmitted = false;\n\tprivate updateReconnectPromise?: Promise<void>;\n\tprivate readonly activeSideQuestionIds = new Set<string>();\n\tprivate readonly snapshotAssemblies = new Map<string, DaemonSnapshotAssembly>();\n\tprivate readonly completedSnapshots = new Map<string, DaemonSessionSnapshot>();\n\tprivate readonly pendingReattachActiveSessionIds = new Set<string>();\n\tprivate readonly snapshotRecoveryPromises = new Map<string, Promise<void>>();\n\tprivate readonly ignoredSnapshotIds = new Set<string>();\n\tprivate reconnectPromise?: Promise<void>;\n\tprivate readonly definitiveRequestErrors = new WeakSet<Error>();\n\tprivate disposing = false;\n\tprivate disposed = false;\n\n\tconstructor(\n\t\tprivate readonly client: DaemonClient,\n\t\tprivate activeSessionId: string,\n\t\tprivate readonly options: DaemonAgentConnectionOptions = {},\n\t) {\n\t\tif (options.recoverDaemon) {\n\t\t\tthis.client.enableRequestRecovery();\n\t\t}\n\t\tthis.unsubscribeDaemonMessages = this.client.onMessage((message) => {\n\t\t\tvoid this.handleDaemonMessage(message).catch((error: unknown) => {\n\t\t\t\ttry {\n\t\t\t\t\tappendRotatingLog(\n\t\t\t\t\t\tgetAgentLogPath(),\n\t\t\t\t\t\t`[${new Date().toISOString()}] daemon-message: ignored ${message.type} failure: ${String(error)}`,\n\t\t\t\t\t);\n\t\t\t\t} catch {\n\t\t\t\t\t// Logging failure must not turn an isolated message error into a connection failure.\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t\tthis.captureDaemonLogPath();\n\t\tthis.unsubscribeDaemonClose = this.client.onClose((error) => {\n\t\t\tconst invalidatedInputPause = this.sessionInputPauses.size > 0;\n\t\t\tthis.sessionInputPauses.clear();\n\t\t\tthis.sessionInputPauseGeneration++;\n\t\t\tthis.rejectSnapshotAssemblies(error);\n\t\t\tif (this.disposed || this.terminalCloseEmitted) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (invalidatedInputPause) {\n\t\t\t\tthis.terminalCloseEmitted = true;\n\t\t\t\tvoid this.emit({\n\t\t\t\t\ttype: \"closed\",\n\t\t\t\t\terror: \"Daemon connection closed while session input was paused; the fence was invalidated.\",\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst closeReason = getDaemonSocketCloseReason(error);\n\t\t\tif (closeReason === \"shutdown\") {\n\t\t\t\tthis.terminalCloseEmitted = true;\n\t\t\t\tvoid this.emit({ type: \"closed\", error: this.formatDaemonSessionClosedError(\"shutdown\") });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif ((this.updateRestartPending || closeReason === \"update\") && !this.updateReconnectFailed) {\n\t\t\t\tthis.updateRestartPending = true;\n\t\t\t\tvoid this.reconnectAfterUpdate();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (this.options.recoverDaemon) {\n\t\t\t\tvoid this.reconnect(error);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.terminalCloseEmitted = true;\n\t\t\tvoid this.emit({ type: \"closed\", error: this.formatDaemonConnectionClosedError(error) });\n\t\t});\n\t}\n\n\tstatic async attach(\n\t\tclient: DaemonClient,\n\t\tactiveSessionId: string,\n\t\toptions?: DaemonAgentConnectionOptions,\n\t): Promise<DaemonAgentConnection> {\n\t\tconst connection = new DaemonAgentConnection(client, activeSessionId, options);\n\t\ttry {\n\t\t\tawait connection.attach();\n\t\t\treturn connection;\n\t\t} catch (error) {\n\t\t\tawait connection.dispose();\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync attach(): Promise<void> {\n\t\tconst supportsExtensionUi = this.options.supportsExtensionUi !== false;\n\t\tconst result = await this.requestData<SessionSummary | DaemonAttachResult>({\n\t\t\ttype: \"attach\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tsupportsExtensionUi,\n\t\t\tclientId: this.clientId,\n\t\t\tcapabilities: [\n\t\t\t\t\"attach_snapshot\",\n\t\t\t\t\"event_sequence\",\n\t\t\t\t...(supportsExtensionUi ? ([\"extension_ui\"] as const) : []),\n\t\t\t\t\"slim_attach\",\n\t\t\t\t\"chunked_snapshot\",\n\t\t\t\t...(this.options.ownedSession ? ([\"client_owned_sessions\"] as const) : []),\n\t\t\t],\n\t\t\tenv: this.options.sendClientEnv ? collectDaemonClientEnv() : undefined,\n\t\t\tlaunchEnv: this.options.ownedSession ? collectDaemonLaunchEnv() : undefined,\n\t\t\t...(this.options.ownedSession &&\n\t\t\tthis.options.ownedSessionRecoveryConfig &&\n\t\t\tthis.client.supportsServerCapability(\"owned_session_recovery_context\")\n\t\t\t\t? { recoveryConfig: this.options.ownedSessionRecoveryConfig }\n\t\t\t\t: {}),\n\t\t\ttelemetryDisabled: this.options.telemetryDisabled,\n\t\t\tresumeCursor:\n\t\t\t\tthis.lastEventCursor === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: {\n\t\t\t\t\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\t\t\t\t\t...this.lastEventCursor,\n\t\t\t\t\t\t},\n\t\t});\n\t\tthis.activeSessionId = getAttachActiveSessionId(result);\n\t\tconst summary = \"snapshot\" in result ? result.snapshot.summary : result;\n\t\tthis.attachedSessionId = summary.sessionId;\n\t\tthis.attachedSessionFile =\n\t\t\tsummary.sessionFile ?? (\"snapshot\" in result ? result.snapshot.state.sessionFile : undefined);\n\t\tthis.captureDaemonLogPath();\n\t\tthis.updateReconnectFailed = false;\n\t\tthis.terminalCloseEmitted = false;\n\t\tconst attachCursor = getAttachLastEventCursor(result);\n\t\tif (attachCursor) {\n\t\t\tthis.observeEventCursor(attachCursor);\n\t\t}\n\t\tthis.lastEventSequence = maxEventSequence(this.lastEventSequence, getAttachLastEventSequence(result));\n\t\tif (\"snapshot\" in result) {\n\t\t\tconst snapshot = result.snapshotStream\n\t\t\t\t? await this.waitForSnapshot(result.snapshotStream.id)\n\t\t\t\t: result.snapshot;\n\t\t\tthis.latestSnapshot = mapDaemonSessionSnapshot(snapshot, result.replay);\n\t\t\tif (Array.isArray(snapshot.children)) this.childRosterSequence = snapshot.lastEventSequence;\n\t\t\tif (this.lastEventSequence !== undefined) {\n\t\t\t\tthis.latestSnapshot.lastEventSequence = this.lastEventSequence;\n\t\t\t}\n\t\t\tif (this.lastEventCursor) {\n\t\t\t\tthis.latestSnapshot.lastEventCursor = this.lastEventCursor;\n\t\t\t}\n\t\t\tthis.latestSnapshotIsFresh = true;\n\t\t} else {\n\t\t\tthis.latestSnapshot = undefined;\n\t\t\tthis.latestSnapshotIsFresh = false;\n\t\t}\n\t}\n\n\tsubscribe(listener: AgentConnectionEventListener): () => void {\n\t\tthis.listeners.add(listener);\n\t\treturn () => {\n\t\t\tthis.listeners.delete(listener);\n\t\t};\n\t}\n\n\tonBeforeSessionInvalidate(_listener: AgentConnectionBeforeSessionInvalidateListener): () => void {\n\t\treturn () => {};\n\t}\n\n\tasync getState(): Promise<AgentConnectionState> {\n\t\tif (this.latestSnapshotIsFresh && this.latestSnapshot) {\n\t\t\treturn this.latestSnapshot.state;\n\t\t}\n\t\treturn this.requestData<AgentConnectionState>({\n\t\t\ttype: \"get_connection_state\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t}\n\n\tasync getInitialSnapshot(): Promise<AgentConnectionSnapshot> {\n\t\tif (this.latestSnapshotIsFresh && this.latestSnapshot) {\n\t\t\treturn this.latestSnapshot;\n\t\t}\n\t\t// The session tree is intentionally not fetched here: it is large on long\n\t\t// sessions and only needed when the user opens the tree/branch selector.\n\t\t// getSessionTree() fetches it lazily via get_session_tree on first use.\n\t\tconst snapshotCursor = this.lastEventCursor;\n\t\tconst snapshotSequence = this.lastEventSequence;\n\t\tconst [state, messagesData, sessionContextData] = await Promise.all([\n\t\t\tthis.requestData<AgentConnectionState>({\n\t\t\t\ttype: \"get_connection_state\",\n\t\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\t}),\n\t\t\tthis.requestData<{ messages: AgentMessage[] }>({\n\t\t\t\ttype: \"get_messages\",\n\t\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\t}),\n\t\t\tthis.requestData<{ context: AgentConnectionSessionContext }>({\n\t\t\t\ttype: \"get_session_context\",\n\t\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\t}),\n\t\t]);\n\t\tconst children = this.latestSnapshot?.children;\n\t\tconst streamingMessage = this.latestSnapshot?.streamingMessage;\n\t\tthis.latestSnapshot = {\n\t\t\tstate,\n\t\t\tmessages: messagesData.messages,\n\t\t\tsessionContext: sessionContextData.context,\n\t\t\t...(children ? { children } : {}),\n\t\t\t...(streamingMessage ? { streamingMessage } : {}),\n\t\t};\n\t\tif (snapshotSequence !== undefined) {\n\t\t\tthis.latestSnapshot.lastEventSequence = snapshotSequence;\n\t\t}\n\t\tif (snapshotCursor) {\n\t\t\tthis.latestSnapshot.lastEventCursor = snapshotCursor;\n\t\t}\n\t\tthis.latestSnapshotIsFresh =\n\t\t\tsnapshotSequence === this.lastEventSequence &&\n\t\t\tsnapshotCursor?.generation === this.lastEventCursor?.generation &&\n\t\t\tsnapshotCursor?.sequence === this.lastEventCursor?.sequence;\n\t\treturn this.latestSnapshot;\n\t}\n\n\tasync getRlmChildSnapshots(): Promise<AgentConnectionRlmChildAgentSnapshot[]> {\n\t\tif (!this.client.supportsServerCapability(\"authoritative_child_roster\")) {\n\t\t\tthrow new DaemonCapabilityUnavailableError(\"get_rlm_children\", \"authoritative_child_roster\");\n\t\t}\n\t\tconst data = await this.requestData<{\n\t\t\tchildren: AgentConnectionRlmChildAgentSnapshot[];\n\t\t\teventSequence: number;\n\t\t}>({ type: \"get_rlm_children\", activeSessionId: this.activeSessionId });\n\t\tif (!Array.isArray(data.children) || !Number.isInteger(data.eventSequence)) {\n\t\t\tthrow new Error(\"Daemon returned an invalid child roster\");\n\t\t}\n\t\tif ((this.childRosterSequence ?? -1) > data.eventSequence) {\n\t\t\treturn this.latestSnapshot?.children ?? data.children;\n\t\t}\n\t\tthis.childRosterSequence = data.eventSequence;\n\t\tif (this.latestSnapshot) {\n\t\t\tthis.latestSnapshot = { ...this.latestSnapshot, children: data.children };\n\t\t}\n\t\treturn data.children;\n\t}\n\n\tasync getMessages(): Promise<AgentMessage[]> {\n\t\tif (this.latestSnapshotIsFresh && this.latestSnapshot) {\n\t\t\treturn this.latestSnapshot.messages;\n\t\t}\n\t\tconst data = await this.requestData<{ messages: AgentMessage[] }>({\n\t\t\ttype: \"get_messages\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t\treturn data.messages;\n\t}\n\n\tasync getSessionHeader(): Promise<AgentConnectionSessionHeader | undefined> {\n\t\tconst data = await this.requestData<{ header?: AgentConnectionSessionHeader | null }>({\n\t\t\ttype: \"get_session_header\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t\treturn data.header ?? undefined;\n\t}\n\n\tasync getCommands(): Promise<AgentConnectionSlashCommand[]> {\n\t\tconst data = await this.requestData<{ commands: AgentConnectionSlashCommand[] }>({\n\t\t\ttype: \"get_commands\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t\treturn data.commands;\n\t}\n\n\tasync getResourceSnapshot(): Promise<AgentConnectionResourceSnapshot> {\n\t\treturn this.requestData<AgentConnectionResourceSnapshot>({\n\t\t\ttype: \"get_resource_snapshot\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t}\n\n\tsupportsAcpMcpServers(): boolean {\n\t\treturn this.client.supportsServerCapability(\"acp_mcp_servers\");\n\t}\n\n\tasync replaceAcpMcpServers(servers: readonly AcpMcpServerConfig[], ownerId: string): Promise<void> {\n\t\tif (!this.supportsAcpMcpServers()) {\n\t\t\tthrow new DaemonCapabilityUnavailableError(\"replace_acp_mcp_servers\", \"acp_mcp_servers\");\n\t\t}\n\t\tawait this.requestOk({\n\t\t\ttype: \"replace_acp_mcp_servers\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\townerId,\n\t\t\tservers: [...servers],\n\t\t});\n\t}\n\n\tasync releaseAcpMcpServers(ownerId: string, _serverNames: readonly string[]): Promise<void> {\n\t\tawait this.replaceAcpMcpServers([], ownerId);\n\t}\n\n\tasync getAvailableModels(): Promise<AgentConnectionModel[]> {\n\t\tconst data = await this.requestData<{ models: AgentConnectionModel[] }>({\n\t\t\ttype: \"get_available_models\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t\treturn data.models;\n\t}\n\n\tasync getModelCatalog(): Promise<AgentConnectionModelCatalog> {\n\t\tif (!this.client.supportsServerCapability(\"model_catalog\")) {\n\t\t\tconst models = await this.getAvailableModels();\n\t\t\treturn {\n\t\t\t\tmodels,\n\t\t\t\tconfiguredProviders: [...new Set(models.map((model) => model.provider))],\n\t\t\t};\n\t\t}\n\t\treturn this.requestData<AgentConnectionModelCatalog>({\n\t\t\ttype: \"get_model_catalog\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t}\n\n\tasync getSessionStats(): Promise<SessionStats> {\n\t\treturn this.requestData<SessionStats>({\n\t\t\ttype: \"get_session_stats\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t}\n\n\tasync getContextTree(): Promise<ContextTreeNode> {\n\t\treturn this.requestData<ContextTreeNode>({\n\t\t\ttype: \"get_context_tree\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t}\n\n\tasync getSessionContext(): Promise<AgentConnectionSessionContext> {\n\t\tif (this.latestSnapshotIsFresh && this.latestSnapshot?.sessionContext) {\n\t\t\treturn this.latestSnapshot.sessionContext;\n\t\t}\n\t\tconst data = await this.requestData<{ context: AgentConnectionSessionContext }>({\n\t\t\ttype: \"get_session_context\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t\treturn data.context;\n\t}\n\n\tasync getSessionTree(): Promise<{ tree: AgentConnectionSessionTreeNode[]; leafId: string | null }> {\n\t\tif (this.latestSnapshotIsFresh && this.latestSnapshot?.sessionTree) {\n\t\t\treturn this.latestSnapshot.sessionTree;\n\t\t}\n\t\tconst data = await this.requestData<{\n\t\t\tflatNodes: AgentConnectionSessionTreeFlatNode[];\n\t\t\tleafId: string | null;\n\t\t}>({\n\t\t\ttype: \"get_session_tree\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t\treturn { tree: buildSessionTreeFromFlatNodes(data.flatNodes), leafId: data.leafId };\n\t}\n\n\tasync listSavedSessions(\n\t\tscope: AgentConnectionSavedSessionScope,\n\t\tcallbacks?: AgentConnectionSessionListCallbacks,\n\t): Promise<AgentConnectionSavedSessionInfo[]> {\n\t\treturn listDaemonSavedSessions(this.client, { activeSessionId: this.activeSessionId }, scope, callbacks);\n\t}\n\n\tasync getQueue(): Promise<AgentConnectionQueueState> {\n\t\treturn this.requestData<AgentConnectionQueueState>({\n\t\t\ttype: \"get_queue\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t}\n\n\tasync mutateQueuedMessage(\n\t\tlane: AgentConnectionQueuedMessageLane,\n\t\tindex: number,\n\t\texpectedText: string,\n\t\tmutation: AgentConnectionQueuedMessageMutation,\n\t): Promise<AgentConnectionQueuedMessageMutationStatus> {\n\t\tif (!this.client.supportsServerCapability(\"queue_message_mutation\")) return \"unsupported\";\n\t\tconst data = await this.requestData<{ status: AgentConnectionQueuedMessageMutationStatus }>({\n\t\t\ttype: \"mutate_queued_message\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tlane,\n\t\t\tindex,\n\t\t\texpectedText,\n\t\t\tmutation,\n\t\t});\n\t\treturn data.status;\n\t}\n\n\tasync clearQueue(): Promise<AgentConnectionQueueState> {\n\t\treturn this.requestData<AgentConnectionQueueState>({\n\t\t\ttype: \"clear_queue\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t}\n\n\tasync abortAndClearQueue(): Promise<AgentConnectionQueueState> {\n\t\ttry {\n\t\t\treturn await this.requestData<AgentConnectionQueueState>({\n\t\t\t\ttype: \"abort_and_clear_queue\",\n\t\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (isUnknownDaemonCommandError(error, \"abort_and_clear_queue\")) {\n\t\t\t\tthrow new Error(\"the daemon is running an older build; restart the daemon and try again\");\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync acquireSessionInputPause(leaseKey: string): Promise<AgentConnectionSessionInputPause> {\n\t\tif (this.terminalCloseEmitted) throw new Error(\"Daemon connection is closed; cannot acquire an input pause.\");\n\t\tconst activeSessionId = this.activeSessionId;\n\t\tconst generation = this.sessionInputPauseGeneration;\n\t\tconst acquisitionKey = JSON.stringify([activeSessionId, leaseKey]);\n\t\tconst existing = this.sessionInputPauses.get(acquisitionKey);\n\t\tif (existing) return existing;\n\t\tconst acquisition = (async (): Promise<AgentConnectionSessionInputPause> => {\n\t\t\tconst { pauseId } = await this.requestData<{ pauseId: string }>({\n\t\t\t\ttype: \"acquire_session_input_pause\",\n\t\t\t\tactiveSessionId,\n\t\t\t\tleaseKey,\n\t\t\t});\n\t\t\tif (generation !== this.sessionInputPauseGeneration || this.terminalCloseEmitted) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.requestData({\n\t\t\t\t\t\ttype: \"release_session_input_pause\",\n\t\t\t\t\t\tactiveSessionId,\n\t\t\t\t\t\tpauseId,\n\t\t\t\t\t});\n\t\t\t\t} catch {\n\t\t\t\t\tthis.client.close();\n\t\t\t\t}\n\t\t\t\tthrow new Error(\"Session input pause acquisition was invalidated by a daemon reconnect.\");\n\t\t\t}\n\t\t\tlet released = false;\n\t\t\treturn {\n\t\t\t\trelease: async () => {\n\t\t\t\t\tif (released) return;\n\t\t\t\t\tif (generation !== this.sessionInputPauseGeneration) {\n\t\t\t\t\t\tthrow new Error(\"Session input pause was invalidated by a daemon reconnect.\");\n\t\t\t\t\t}\n\t\t\t\t\tawait this.requestData({\n\t\t\t\t\t\ttype: \"release_session_input_pause\",\n\t\t\t\t\t\tactiveSessionId,\n\t\t\t\t\t\tpauseId,\n\t\t\t\t\t});\n\t\t\t\t\treleased = true;\n\t\t\t\t\tif (this.sessionInputPauses.get(acquisitionKey) === acquisition) {\n\t\t\t\t\t\tthis.sessionInputPauses.delete(acquisitionKey);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t};\n\t\t})();\n\t\tthis.sessionInputPauses.set(acquisitionKey, acquisition);\n\t\ttry {\n\t\t\treturn await acquisition;\n\t\t} catch (error) {\n\t\t\tif (this.sessionInputPauses.get(acquisitionKey) === acquisition)\n\t\t\t\tthis.sessionInputPauses.delete(acquisitionKey);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync listCronJobs(options: { includeInactive?: boolean } = {}): Promise<AgentCronJob[]> {\n\t\tconst data = await this.requestData<{ jobs: AgentCronJob[] }>({\n\t\t\ttype: \"cron_list\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tincludeInactive: options.includeInactive,\n\t\t});\n\t\treturn data.jobs;\n\t}\n\n\tasync listHeartbeats(): Promise<AgentConnectionHeartbeat[]> {\n\t\treturn listDaemonHeartbeats(this.client, this.options.ownedSession ? this.activeSessionId : undefined);\n\t}\n\n\tasync manageHeartbeat(\n\t\tactiveSessionId: string,\n\t\tjobId: string,\n\t\taction: AgentHeartbeatManagementAction,\n\t): Promise<AgentCronJob> {\n\t\tif (!this.client.supportsServerCapability(\"heartbeat_management\")) {\n\t\t\tthrow new Error(\"Heartbeat management requires a newer ASM Agent daemon.\");\n\t\t}\n\t\ttry {\n\t\t\tconst data = await this.requestData<{ heartbeat: AgentCronJob }>({\n\t\t\t\ttype: \"heartbeat_manage\",\n\t\t\t\tactiveSessionId,\n\t\t\t\tjobId,\n\t\t\t\taction,\n\t\t\t});\n\t\t\treturn data.heartbeat;\n\t\t} catch (error) {\n\t\t\tif (isUnknownDaemonCommandError(error, \"heartbeat_manage\")) {\n\t\t\t\tthrow new Error(\"Heartbeat management requires a newer ASM Agent daemon.\");\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync addCronJob(schedule: string, prompt: string): Promise<AgentCronJob> {\n\t\treturn this.withOwnedSessionPromotion(async (promoteOwnedSession) => {\n\t\t\tconst data = await this.requestData<{ job: AgentCronJob }>({\n\t\t\t\ttype: \"cron_add\",\n\t\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\t\tschedule,\n\t\t\t\tprompt,\n\t\t\t\tpromoteOwnedSession,\n\t\t\t});\n\t\t\treturn data.job;\n\t\t});\n\t}\n\n\tasync cancelCronJob(jobId: string): Promise<AgentCronJob> {\n\t\tconst data = await this.requestData<{ job: AgentCronJob }>({\n\t\t\ttype: \"cron_cancel\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tjobId,\n\t\t});\n\t\treturn data.job;\n\t}\n\n\tasync getHeartbeat(): Promise<AgentCronJob | undefined> {\n\t\tconst data = await this.requestData<{ heartbeat?: AgentCronJob | null }>({\n\t\t\ttype: \"heartbeat_get\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t\treturn data.heartbeat ?? undefined;\n\t}\n\n\tasync setHeartbeat(\n\t\tschedule: string,\n\t\tinstruction: string,\n\t\tdeliveryMode?: AgentHeartbeatDeliveryMode,\n\t): Promise<AgentCronJob> {\n\t\treturn this.withOwnedSessionPromotion(async (promoteOwnedSession) => {\n\t\t\tconst data = await this.requestData<{ heartbeat: AgentCronJob }>({\n\t\t\t\ttype: \"heartbeat_set\",\n\t\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\t\tschedule,\n\t\t\t\tprompt: instruction,\n\t\t\t\t...(deliveryMode ? { deliveryMode } : {}),\n\t\t\t\tpromoteOwnedSession,\n\t\t\t});\n\t\t\treturn data.heartbeat;\n\t\t});\n\t}\n\n\tasync updateHeartbeat(action: AgentHeartbeatUpdateAction): Promise<AgentCronJob | undefined> {\n\t\tconst data = await this.requestData<{ heartbeat?: AgentCronJob | null }>({\n\t\t\ttype: \"heartbeat_update\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\taction,\n\t\t});\n\t\treturn data.heartbeat ?? undefined;\n\t}\n\n\tasync sendAgentMessage(targetActiveSessionId: string, message: string): Promise<AgentSessionMessageReceipt> {\n\t\treturn this.requestData<AgentSessionMessageReceipt>({\n\t\t\ttype: \"send_message\",\n\t\t\ttargetActiveSessionId,\n\t\t\tmessage,\n\t\t\tfromActiveSessionId: this.activeSessionId,\n\t\t});\n\t}\n\n\tasync getAgentMessageStatus(): Promise<AgentSessionMessageSafetyStatus> {\n\t\treturn this.requestData<AgentSessionMessageSafetyStatus>({\n\t\t\ttype: \"agent_messages_status\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t}\n\n\tasync pauseAgentMessages(): Promise<AgentSessionMessageSafetyStatus> {\n\t\treturn this.requestData<AgentSessionMessageSafetyStatus>({\n\t\t\ttype: \"agent_messages_pause\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t}\n\n\tasync resumeAgentMessages(): Promise<AgentSessionMessageSafetyStatus> {\n\t\treturn this.requestData<AgentSessionMessageSafetyStatus>({\n\t\t\ttype: \"agent_messages_resume\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t}\n\n\tasync clearAgentMessages(): Promise<number> {\n\t\treturn this.requestData<number>({\n\t\t\ttype: \"agent_messages_clear\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t}\n\n\tasync getUserMessagesForForking(): Promise<AgentConnectionUserMessage[]> {\n\t\tconst data = await this.requestData<{ messages: AgentConnectionUserMessage[] }>({\n\t\t\ttype: \"get_user_messages_for_forking\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t\treturn data.messages;\n\t}\n\n\tasync getLastAssistantText(): Promise<string | undefined> {\n\t\tconst data = await this.requestData<{ text?: string | null }>({\n\t\t\ttype: \"get_last_assistant_text\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t\treturn data.text ?? undefined;\n\t}\n\n\tasync getSystemPrompt(): Promise<string> {\n\t\tconst data = await this.requestData<{ systemPrompt: string }>({\n\t\t\ttype: \"get_system_prompt\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t\treturn data.systemPrompt;\n\t}\n\n\tasync getToolDefinition(name: string): Promise<AgentConnectionToolDefinition | undefined> {\n\t\tconst data = await this.requestData<{ toolDefinition?: AgentConnectionToolDefinition }>({\n\t\t\ttype: \"get_tool_definition\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tname,\n\t\t});\n\t\treturn data.toolDefinition;\n\t}\n\n\tasync setSessionEntryLabel(entryId: string, label: string | undefined): Promise<void> {\n\t\tawait this.requestOk({\n\t\t\ttype: \"set_session_entry_label\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tentryId,\n\t\t\tlabel,\n\t\t});\n\t}\n\n\tasync respondToExtensionUiRequest(requestId: string, response: AgentConnectionExtensionUiResponse): Promise<void> {\n\t\tawait this.requestOk({\n\t\t\ttype: \"extension_ui_response\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\trequestId,\n\t\t\tresponse,\n\t\t});\n\t}\n\n\tasync prompt(message: string, options?: AgentConnectionPromptOptions): Promise<void> {\n\t\tawait this.promptWithAdmissionCancellation(\"prompt\", message, options);\n\t}\n\n\tasync promptAndWait(message: string, options?: AgentConnectionPromptOptions): Promise<void> {\n\t\tawait this.promptWithAdmissionCancellation(\"prompt_and_wait\", message, options);\n\t}\n\n\tprivate async promptWithAdmissionCancellation(\n\t\ttype: \"prompt\" | \"prompt_and_wait\",\n\t\tmessage: string,\n\t\toptions?: AgentConnectionPromptOptions,\n\t): Promise<void> {\n\t\tconst signal = options?.signal;\n\t\tif (signal?.aborted) {\n\t\t\tthrow new AgentConnectionPromptAdmissionError(\"Prompt admission was cancelled.\", \"cancelled\");\n\t\t}\n\t\tif (!signal) {\n\t\t\tawait this.requestData<unknown>(\n\t\t\t\t{\n\t\t\t\t\ttype,\n\t\t\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\t\t\tmessage,\n\t\t\t\t\timages: options?.images,\n\t\t\t\t\tstreamingBehavior: options?.streamingBehavior,\n\t\t\t\t\tqueueIfBusy: options?.queueIfBusy,\n\t\t\t\t\tsource: options?.source,\n\t\t\t\t},\n\t\t\t\tDAEMON_LONG_RUNNING_REQUEST_TIMEOUT_MS,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tconst admissionId = `prompt-admission:${randomUUID()}`;\n\t\tlet resolveAbort = () => {};\n\t\tconst aborted = new Promise<\"abort\">((resolve) => {\n\t\t\tresolveAbort = () => resolve(\"abort\");\n\t\t});\n\t\tconst onAbort = () => resolveAbort();\n\t\tsignal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t// Close the listener-registration race before issuing the first request.\n\t\tif (signal.aborted) {\n\t\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\t\tthrow new AgentConnectionPromptAdmissionError(\"Prompt admission was cancelled.\", \"cancelled\");\n\t\t}\n\t\tconst command = {\n\t\t\ttype,\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tmessage,\n\t\t\timages: options.images,\n\t\t\tstreamingBehavior: options.streamingBehavior,\n\t\t\tqueueIfBusy: options.queueIfBusy,\n\t\t\tsource: options.source,\n\t\t\tadmissionId,\n\t\t} as Extract<DaemonCommandBody, { type: typeof type }>;\n\t\tlet promptError: unknown;\n\t\tconst promptRequest = this.requestData<unknown>(command, DAEMON_LONG_RUNNING_REQUEST_TIMEOUT_MS).catch(\n\t\t\t(error: unknown) => {\n\t\t\t\tpromptError =\n\t\t\t\t\terror instanceof DaemonCapabilityUnavailableError && !error.afterReconnect\n\t\t\t\t\t\t? new AgentConnectionPromptAdmissionError(error.message, \"unsupported\", { cause: error })\n\t\t\t\t\t\t: error;\n\t\t\t\treturn \"failed\" as const;\n\t\t\t},\n\t\t);\n\t\ttry {\n\t\t\tconst first = await Promise.race([promptRequest.then(() => \"settled\" as const), aborted]);\n\t\t\tif (first === \"settled\" && promptError === undefined) return;\n\t\t\tif (first === \"settled\" && promptError instanceof AgentConnectionPromptAdmissionError) throw promptError;\n\t\t\tif (\n\t\t\t\tfirst === \"settled\" &&\n\t\t\t\t!signal.aborted &&\n\t\t\t\tpromptError instanceof Error &&\n\t\t\t\tthis.definitiveRequestErrors.has(promptError)\n\t\t\t) {\n\t\t\t\tthrow promptError;\n\t\t\t}\n\t\t\tlet status: \"cancelled\" | \"owned\" | \"unknown\" = \"unknown\";\n\t\t\ttry {\n\t\t\t\tconst result = await this.requestData<{ status: \"cancelled\" | \"owned\" | \"unknown\" }>({\n\t\t\t\t\ttype: \"cancel_prompt_admission\",\n\t\t\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\t\t\tadmissionId,\n\t\t\t\t\t...(this.client.supportsServerCapability(\"owned_prompt_cancellation\") ? { cancelOwned: true } : {}),\n\t\t\t\t});\n\t\t\t\tstatus = result.status;\n\t\t\t} catch {\n\t\t\t\t// Timeout/transport is indistinguishable from accepted ownership.\n\t\t\t}\n\t\t\tawait promptRequest;\n\t\t\tif (promptError instanceof AgentConnectionPromptAdmissionError) throw promptError;\n\t\t\tconst definitiveFailure = promptError instanceof Error && this.definitiveRequestErrors.has(promptError);\n\t\t\tif (promptError === undefined || (status === \"owned\" && type === \"prompt\" && !definitiveFailure)) return;\n\t\t\tthrow new AgentConnectionPromptAdmissionError(\n\t\t\t\tpromptError instanceof Error ? promptError.message : \"Prompt admission did not complete.\",\n\t\t\t\tstatus,\n\t\t\t\tpromptError === undefined ? undefined : { cause: promptError },\n\t\t\t);\n\t\t} finally {\n\t\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\t}\n\t}\n\n\tasync startSideQuestion(\n\t\tid: string,\n\t\tquestion: string,\n\t\tpreviousTurns?: AgentConnectionSideQuestionTurn[],\n\t): Promise<void> {\n\t\tif (previousTurns?.length && !this.client.supportsServerCapability(\"side_question_transcript\")) {\n\t\t\t// An older daemon would silently ignore previousTurns and answer the\n\t\t\t// follow-up without the side-conversation context; fail loudly instead.\n\t\t\tthrow new Error(\n\t\t\t\t\"the daemon is running an older build without side-conversation follow-ups; restart the daemon and try again\",\n\t\t\t);\n\t\t}\n\t\tthis.activeSideQuestionIds.add(id);\n\t\ttry {\n\t\t\tawait this.requestOk({\n\t\t\t\ttype: \"start_side_question\",\n\t\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\t\tsideQuestionId: id,\n\t\t\t\tquestion,\n\t\t\t\tpreviousTurns,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tthis.activeSideQuestionIds.delete(id);\n\t\t\tif (isUnknownDaemonCommandError(error, \"start_side_question\")) {\n\t\t\t\tthrow new Error(\"the daemon is running an older build; restart the daemon and try again\");\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync abortSideQuestion(id: string): Promise<boolean> {\n\t\tconst data = await this.requestData<{ aborted: boolean }>({\n\t\t\ttype: \"abort_side_question\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tsideQuestionId: id,\n\t\t});\n\t\tthis.activeSideQuestionIds.delete(id);\n\t\treturn data.aborted;\n\t}\n\n\tasync steer(message: string, images?: ImageContent[]): Promise<void> {\n\t\tawait this.requestOk({ type: \"steer\", activeSessionId: this.activeSessionId, message, images });\n\t}\n\n\tasync followUp(message: string, images?: ImageContent[]): Promise<void> {\n\t\tawait this.requestOk({ type: \"follow_up\", activeSessionId: this.activeSessionId, message, images });\n\t}\n\n\tasync abort(): Promise<void> {\n\t\tawait this.requestOk({ type: \"abort\", activeSessionId: this.activeSessionId });\n\t}\n\n\tasync cancelRlmChild(childId: string): Promise<boolean> {\n\t\ttry {\n\t\t\tconst result = await this.requestData<{ cancelled: boolean }>({\n\t\t\t\ttype: \"cancel_rlm_child\",\n\t\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\t\tchildId,\n\t\t\t});\n\t\t\treturn result.cancelled;\n\t\t} catch (error) {\n\t\t\tif (isUnknownDaemonCommandError(error, \"cancel_rlm_child\")) {\n\t\t\t\tthrow new Error(\"the daemon is running an older build; restart the daemon and try again\");\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync waitForIdle(): Promise<void> {\n\t\tawait this.requestData<unknown>(\n\t\t\t{ type: \"wait_for_idle\", activeSessionId: this.activeSessionId },\n\t\t\tDAEMON_LONG_RUNNING_REQUEST_TIMEOUT_MS,\n\t\t);\n\t}\n\n\tasync waitForHeadlessCompletion(options?: AgentConnectionHeadlessCompletionOptions): Promise<AgentAutonomousStatus> {\n\t\tif (options?.waitForRlmQuiescence && !this.client.supportsServerCapability(\"rlm_quiescence_barrier\")) {\n\t\t\tthrow new Error(\n\t\t\t\t\"the daemon is running an older build without RLM quiescence barriers; restart the daemon and try again\",\n\t\t\t);\n\t\t}\n\t\treturn this.requestData<AgentAutonomousStatus>(\n\t\t\t{\n\t\t\t\ttype: \"wait_for_headless_completion\",\n\t\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\t\t...(options?.waitForRlmQuiescence ? { waitForRlmQuiescence: true } : {}),\n\t\t\t},\n\t\t\tDAEMON_LONG_RUNNING_REQUEST_TIMEOUT_MS,\n\t\t);\n\t}\n\n\tasync executeBash(command: string, options?: AgentConnectionExecuteBashOptions): Promise<void> {\n\t\tif (options?.transient && !this.client.supportsServerCapability(\"transient_bash\")) {\n\t\t\t// An older daemon would record the run into the session, leaking the\n\t\t\t// side conversation into the main transcript; fail loudly instead.\n\t\t\tthrow new Error(\n\t\t\t\t\"the daemon is running an older build without side-conversation bash; restart the daemon and try again\",\n\t\t\t);\n\t\t}\n\t\ttry {\n\t\t\tawait this.requestOk({\n\t\t\t\ttype: \"execute_bash\",\n\t\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\t\tcommand,\n\t\t\t\texcludeFromContext: options?.excludeFromContext,\n\t\t\t\ttransient: options?.transient,\n\t\t\t\trunId: options?.runId,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (isUnknownDaemonCommandError(error, \"execute_bash\")) {\n\t\t\t\tthrow new Error(\"the daemon is running an older build; restart the daemon and try again\");\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync executeBashAndWait(command: string): Promise<BashResult> {\n\t\treturn this.requestData<BashResult>(\n\t\t\t{\n\t\t\t\ttype: \"execute_bash_and_wait\",\n\t\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\t\tcommand,\n\t\t\t},\n\t\t\tDAEMON_LONG_RUNNING_REQUEST_TIMEOUT_MS,\n\t\t);\n\t}\n\n\tasync abortBash(): Promise<void> {\n\t\ttry {\n\t\t\tawait this.requestOk({ type: \"abort_bash\", activeSessionId: this.activeSessionId });\n\t\t} catch (error) {\n\t\t\tif (isUnknownDaemonCommandError(error, \"abort_bash\")) {\n\t\t\t\tthrow new Error(\"the daemon is running an older build; restart the daemon and try again\");\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync setModel(provider: string, modelId: string): Promise<AgentConnectionModel> {\n\t\treturn this.requestData<AgentConnectionModel>({\n\t\t\ttype: \"set_model\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tprovider,\n\t\t\tmodelId,\n\t\t});\n\t}\n\n\tasync cycleModel(direction?: \"forward\" | \"backward\"): Promise<AgentConnectionModelCycleResult | undefined> {\n\t\tconst result = await this.requestData<AgentConnectionModelCycleResult | null>({\n\t\t\ttype: \"cycle_model\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tdirection,\n\t\t});\n\t\treturn result ?? undefined;\n\t}\n\n\tasync setScopedModels(scopedModels: AgentConnectionScopedModel[]): Promise<void> {\n\t\tawait this.requestOk({\n\t\t\ttype: \"set_scoped_models\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tscopedModels,\n\t\t});\n\t}\n\n\tasync setThinkingLevel(level: ThinkingLevel): Promise<void> {\n\t\tawait this.requestOk({ type: \"set_thinking_level\", activeSessionId: this.activeSessionId, level });\n\t}\n\n\tasync setServiceTier(serviceTier: ServiceTier): Promise<void> {\n\t\tawait this.requestOk({ type: \"set_service_tier\", activeSessionId: this.activeSessionId, serviceTier });\n\t}\n\n\tasync cycleThinkingLevel(): Promise<ThinkingLevel | undefined> {\n\t\tconst result = await this.requestData<{ level: ThinkingLevel } | null>({\n\t\t\ttype: \"cycle_thinking_level\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t\treturn result?.level;\n\t}\n\n\tasync setTransport(transport: Transport): Promise<void> {\n\t\tawait this.requestOk({ type: \"set_transport\", activeSessionId: this.activeSessionId, transport });\n\t}\n\n\tasync setSteeringMode(mode: AgentConnectionQueueMode): Promise<void> {\n\t\tawait this.requestOk({ type: \"set_steering_mode\", activeSessionId: this.activeSessionId, mode });\n\t}\n\n\tasync setFollowUpMode(mode: AgentConnectionQueueMode): Promise<void> {\n\t\tawait this.requestOk({ type: \"set_follow_up_mode\", activeSessionId: this.activeSessionId, mode });\n\t}\n\n\tasync setAutoCompactionEnabled(enabled: boolean): Promise<void> {\n\t\tawait this.requestOk({ type: \"set_auto_compaction\", activeSessionId: this.activeSessionId, enabled });\n\t}\n\n\tasync setAutoRetryEnabled(enabled: boolean): Promise<void> {\n\t\tawait this.requestOk({ type: \"set_auto_retry\", activeSessionId: this.activeSessionId, enabled });\n\t}\n\n\tasync compact(customInstructions?: string): Promise<CompactionResult> {\n\t\treturn this.requestData<CompactionResult>({\n\t\t\ttype: \"compact\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tcustomInstructions,\n\t\t});\n\t}\n\n\tasync refine(\n\t\toptions: { instructions?: string; rollbackId?: string; global?: boolean } = {},\n\t): Promise<RefinementResult> {\n\t\tconst command: {\n\t\t\ttype: \"refine\";\n\t\t\tactiveSessionId: string;\n\t\t\tinstructions?: string;\n\t\t\trollbackId?: string;\n\t\t\tglobal?: boolean;\n\t\t} = {\n\t\t\ttype: \"refine\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tinstructions: options.instructions,\n\t\t\trollbackId: options.rollbackId,\n\t\t};\n\t\tif (options.global !== undefined) {\n\t\t\tcommand.global = options.global;\n\t\t}\n\t\treturn this.requestData<RefinementResult>(command, DAEMON_REFINE_REQUEST_TIMEOUT_MS);\n\t}\n\n\tasync abortCompaction(): Promise<void> {\n\t\tawait this.requestOk({ type: \"abort_compaction\", activeSessionId: this.activeSessionId });\n\t}\n\n\tasync abortBranchSummary(): Promise<void> {\n\t\tawait this.requestOk({ type: \"abort_branch_summary\", activeSessionId: this.activeSessionId });\n\t}\n\n\tasync abortRetry(): Promise<void> {\n\t\tawait this.requestOk({ type: \"abort_retry\", activeSessionId: this.activeSessionId });\n\t}\n\n\tasync reload(): Promise<void> {\n\t\tawait this.requestOk({ type: \"reload\", activeSessionId: this.activeSessionId });\n\t}\n\n\tasync newSession(options?: AgentConnectionNewSessionOptions): Promise<{ cancelled: boolean }> {\n\t\treturn this.requestData<{ cancelled: boolean }>({\n\t\t\ttype: \"new_session\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tparentSession: options?.parentSession,\n\t\t});\n\t}\n\n\tasync switchSession(\n\t\tsessionPath: string,\n\t\toptions?: AgentConnectionSwitchSessionOptions,\n\t): Promise<{ cancelled: boolean }> {\n\t\tconst sourceActiveSessionId = this.activeSessionId;\n\t\ttry {\n\t\t\treturn await this.requestData<{ cancelled: boolean }>({\n\t\t\t\ttype: \"switch_session\",\n\t\t\t\tactiveSessionId: sourceActiveSessionId,\n\t\t\t\tsessionPath,\n\t\t\t\tcwdOverride: options?.cwdOverride,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (!(error instanceof SessionAlreadyActiveError) || !error.activeSessionId) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tif (this.options.ownedSession) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tif (error.activeSessionId === sourceActiveSessionId) {\n\t\t\t\treturn { cancelled: false };\n\t\t\t}\n\t\t\treturn this.reattachSession(sourceActiveSessionId, error.activeSessionId);\n\t\t}\n\t}\n\n\tprivate async reattachSession(\n\t\tsourceActiveSessionId: string,\n\t\ttargetActiveSessionId: string,\n\t): Promise<{ cancelled: false }> {\n\t\tconst previousState = {\n\t\t\tlastEventCursor: this.lastEventCursor,\n\t\t\tlastEventSequence: this.lastEventSequence,\n\t\t\tlatestSnapshot: this.latestSnapshot,\n\t\t\tlatestSnapshotIsFresh: this.latestSnapshotIsFresh,\n\t\t\tretiredEventGenerations: new Set(this.retiredEventGenerations),\n\t\t};\n\t\tthis.activeSessionId = targetActiveSessionId;\n\t\tthis.lastEventCursor = undefined;\n\t\tthis.lastEventSequence = undefined;\n\t\tthis.latestSnapshot = undefined;\n\t\tthis.latestSnapshotIsFresh = false;\n\t\tthis.retiredEventGenerations.clear();\n\t\tthis.pendingReattachActiveSessionIds.add(targetActiveSessionId);\n\t\tlet reattached = false;\n\t\ttry {\n\t\t\tconst supportsExtensionUi = this.options.supportsExtensionUi !== false;\n\t\t\tconst result = await this.requestData<DaemonAttachResult>({\n\t\t\t\ttype: \"reattach\",\n\t\t\t\tactiveSessionId: sourceActiveSessionId,\n\t\t\t\ttargetActiveSessionId,\n\t\t\t\tsupportsExtensionUi,\n\t\t\t\tclientId: this.clientId,\n\t\t\t\tcapabilities: [\n\t\t\t\t\t\"attach_snapshot\",\n\t\t\t\t\t\"event_sequence\",\n\t\t\t\t\t...(supportsExtensionUi ? ([\"extension_ui\"] as const) : []),\n\t\t\t\t\t\"slim_attach\",\n\t\t\t\t\t\"chunked_snapshot\",\n\t\t\t\t\t...(this.options.ownedSession ? ([\"client_owned_sessions\"] as const) : []),\n\t\t\t\t],\n\t\t\t\tenv: this.options.sendClientEnv ? collectDaemonClientEnv() : undefined,\n\t\t\t\tlaunchEnv: this.options.ownedSession ? collectDaemonLaunchEnv() : undefined,\n\t\t\t\ttelemetryDisabled: this.options.telemetryDisabled,\n\t\t\t});\n\t\t\treattached = true;\n\t\t\tthis.activeSessionId = result.activeSessionId;\n\t\t\tthis.activeSideQuestionIds.clear();\n\t\t\tif (result.snapshotStream) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.waitForSnapshot(result.snapshotStream.id);\n\t\t\t\t} catch (snapshotError) {\n\t\t\t\t\tawait this.snapshotRecoveryPromises.get(result.snapshotStream.id);\n\t\t\t\t\tif (!this.latestSnapshotIsFresh) {\n\t\t\t\t\t\tthrow snapshotError;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.applyReplacementSnapshot(result.snapshot, result.replay);\n\t\t\t\tawait this.emit({\n\t\t\t\t\ttype: \"session_replaced\",\n\t\t\t\t\tstate: result.snapshot.state,\n\t\t\t\t\tmessages: result.snapshot.messages,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { cancelled: false };\n\t\t} catch (error) {\n\t\t\tif (!reattached) {\n\t\t\t\tthis.activeSessionId = sourceActiveSessionId;\n\t\t\t\tthis.lastEventCursor = previousState.lastEventCursor;\n\t\t\t\tthis.lastEventSequence = previousState.lastEventSequence;\n\t\t\t\tthis.latestSnapshot = previousState.latestSnapshot;\n\t\t\t\tthis.latestSnapshotIsFresh = previousState.latestSnapshotIsFresh;\n\t\t\t\tthis.retiredEventGenerations.clear();\n\t\t\t\tfor (const generation of previousState.retiredEventGenerations) {\n\t\t\t\t\tthis.retiredEventGenerations.add(generation);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\tthis.pendingReattachActiveSessionIds.delete(targetActiveSessionId);\n\t\t}\n\t}\n\n\tasync fork(\n\t\tentryId: string,\n\t\toptions?: AgentConnectionForkOptions,\n\t): Promise<{ cancelled: boolean; selectedText?: string }> {\n\t\treturn this.requestData<{ cancelled: boolean; selectedText?: string }>({\n\t\t\ttype: \"fork\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tentryId,\n\t\t\tposition: options?.position,\n\t\t});\n\t}\n\n\tasync navigateTree(\n\t\ttargetId: string,\n\t\toptions?: AgentConnectionNavigateTreeOptions,\n\t): Promise<AgentConnectionNavigateTreeResult> {\n\t\treturn this.requestData<AgentConnectionNavigateTreeResult>({\n\t\t\ttype: \"navigate_tree\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\ttargetId,\n\t\t\tsummarize: options?.summarize,\n\t\t\tcustomInstructions: options?.customInstructions,\n\t\t\treplaceInstructions: options?.replaceInstructions,\n\t\t\tlabel: options?.label,\n\t\t});\n\t}\n\n\tasync importFromJsonl(inputPath: string, cwdOverride?: string): Promise<{ cancelled: boolean }> {\n\t\treturn this.requestData<{ cancelled: boolean }>({\n\t\t\ttype: \"import_jsonl\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tinputPath,\n\t\t\tcwdOverride,\n\t\t});\n\t}\n\n\tasync exportToHtml(outputPath?: string): Promise<string> {\n\t\tconst data = await this.requestData<{ path: string }>({\n\t\t\ttype: \"export_html\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\toutputPath,\n\t\t});\n\t\treturn data.path;\n\t}\n\n\tasync exportToJsonl(outputPath?: string): Promise<string> {\n\t\tconst data = await this.requestData<{ path: string }>({\n\t\t\ttype: \"export_jsonl\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\toutputPath,\n\t\t});\n\t\treturn data.path;\n\t}\n\n\tasync setSessionName(name: string): Promise<void> {\n\t\tawait this.requestOk({ type: \"set_session_name\", activeSessionId: this.activeSessionId, name });\n\t}\n\n\tasync getRlmMaxDepthStatus() {\n\t\treturn this.requestData<{ maxDepth: number; source: \"default\" | \"env\" | \"global\" | \"inherited\" | \"chat\" }>({\n\t\t\ttype: \"get_rlm_max_depth_status\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t}\n\n\tasync setRlmMaxDepth(maxDepth: number, options?: { global?: boolean }) {\n\t\treturn this.requestData<{\n\t\t\tmaxDepth: number;\n\t\t\tsource: \"default\" | \"env\" | \"global\" | \"inherited\" | \"chat\";\n\t\t\tglobalSaved: boolean;\n\t\t\tglobalError?: string;\n\t\t}>({\n\t\t\ttype: \"set_rlm_max_depth\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tmaxDepth,\n\t\t\tglobal: options?.global,\n\t\t});\n\t}\n\n\tasync renameSavedSession(sessionPath: string, name: string): Promise<void> {\n\t\tawait renameDaemonSavedSession(this.client, { activeSessionId: this.activeSessionId }, sessionPath, name);\n\t}\n\n\tasync deleteSavedSession(sessionPath: string): Promise<DeleteSessionFileResult> {\n\t\treturn deleteDaemonSavedSession(this.client, { activeSessionId: this.activeSessionId }, sessionPath);\n\t}\n\n\tasync watchSession(activeSessionId: string): Promise<AgentConnectionSessionWatcher | undefined> {\n\t\t// A second connection on the shared client; each one filters to its own session id.\n\t\t// attach() rejects for an unknown/exited session — treat that as unreachable.\n\t\tlet connection: DaemonAgentConnection;\n\t\ttry {\n\t\t\tconnection = await DaemonAgentConnection.attach(this.client, activeSessionId, { closeClientOnDispose: false });\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn {\n\t\t\tgetMessages: () => connection.getMessages(),\n\t\t\tgetCommands: () => connection.getCommands(),\n\t\t\tsubscribe: (listener) => connection.subscribe(listener),\n\t\t\tgetToolDefinition: (name) => connection.getToolDefinition(name),\n\t\t\tclose: () => connection.dispose(),\n\t\t};\n\t}\n\n\tasync dispose(): Promise<void> {\n\t\tif (this.disposed || this.disposing) {\n\t\t\treturn;\n\t\t}\n\t\tthis.disposing = true;\n\t\tif (this.options.ownedSession && !this.client.isConnected && this.reconnectPromise) {\n\t\t\tawait Promise.race([this.reconnectPromise, delay(OWNED_SESSION_DISPOSE_RECONNECT_WAIT_MS)]).catch(\n\t\t\t\t() => undefined,\n\t\t\t);\n\t\t}\n\t\tthis.disposed = true;\n\t\tthis.updateRestartPending = false;\n\t\tawait Promise.allSettled([...this.activeSideQuestionIds].map((id) => this.abortSideQuestion(id)));\n\t\tthis.unsubscribeDaemonMessages();\n\t\tthis.unsubscribeDaemonClose();\n\t\tif (this.options.ownedSession) {\n\t\t\tawait this.requestOk({ type: \"complete_owned_session\", activeSessionId: this.activeSessionId }).catch(\n\t\t\t\t() => undefined,\n\t\t\t);\n\t\t} else {\n\t\t\tawait this.requestOk({ type: \"detach\", activeSessionId: this.activeSessionId }).catch(() => undefined);\n\t\t}\n\t\tif (this.options.closeClientOnDispose) {\n\t\t\tthis.client.close();\n\t\t}\n\t\tthis.rejectSnapshotAssemblies(new Error(\"Daemon connection disposed during snapshot transfer\"));\n\t}\n\n\tasync promoteToResident(): Promise<void> {\n\t\tawait this.withOwnedSessionPromotion(async (promoteOwnedSession) => {\n\t\t\tif (!promoteOwnedSession) return;\n\t\t\tawait this.requestOk({ type: \"promote_owned_session\", activeSessionId: this.activeSessionId });\n\t\t});\n\t}\n\n\tprivate withOwnedSessionPromotion<T>(operation: (promoteOwnedSession: boolean) => Promise<T>): Promise<T> {\n\t\tconst run = this.ownedSessionPromotionTail.then(async () => {\n\t\t\tconst promoteOwnedSession = this.options.ownedSession === true;\n\t\t\tconst result = await operation(promoteOwnedSession);\n\t\t\tif (promoteOwnedSession) {\n\t\t\t\tthis.options.ownedSession = false;\n\t\t\t}\n\t\t\treturn result;\n\t\t});\n\t\tthis.ownedSessionPromotionTail = run.then(\n\t\t\t() => undefined,\n\t\t\t() => undefined,\n\t\t);\n\t\treturn run;\n\t}\n\n\tprivate async reconnect(cause: Error): Promise<void> {\n\t\tif (this.reconnectPromise) {\n\t\t\treturn this.reconnectPromise;\n\t\t}\n\t\tthis.reconnectPromise = (async () => {\n\t\t\tvoid this.emit({ type: \"connection_status\", status: \"reconnecting\", error: cause.message });\n\t\t\tconst deadline = Date.now() + (this.options.reconnectTimeoutMs ?? DAEMON_RECONNECT_TIMEOUT_MS);\n\t\t\tlet attempt = 0;\n\t\t\tlet lastError: Error = cause;\n\t\t\twhile (!this.disposed && Date.now() < deadline) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.options.recoverDaemon?.();\n\t\t\t\t\tif (this.disposed) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tawait this.client.connect(1000);\n\t\t\t\t\tawait this.client.waitForHello(3000);\n\t\t\t\t\tawait this.attach();\n\t\t\t\t\tif (!this.disposed) {\n\t\t\t\t\t\tconst snapshot = await this.getInitialSnapshot();\n\t\t\t\t\t\tvoid this.emit({ type: \"session_resynced\", snapshot });\n\t\t\t\t\t\tvoid this.emit({ type: \"connection_status\", status: \"connected\" });\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tlastError = error instanceof Error ? error : new Error(String(error));\n\t\t\t\t\tif (this.disposed) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthis.client.resetTransportForReconnect();\n\t\t\t\t\tconst remainingMs = deadline - Date.now();\n\t\t\t\t\tif (remainingMs <= 0) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tconst delayMs = Math.min(remainingMs, 2000, 100 * 2 ** Math.min(attempt, 5));\n\t\t\t\t\tattempt++;\n\t\t\t\t\tawait new Promise((resolveDelay) => setTimeout(resolveDelay, delayMs));\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!this.disposed) {\n\t\t\t\tthis.client.close();\n\t\t\t\tawait this.emit({ type: \"closed\", error: `Daemon reconnection failed: ${lastError.message}` });\n\t\t\t}\n\t\t})().finally(() => {\n\t\t\tthis.reconnectPromise = undefined;\n\t\t});\n\t\treturn this.reconnectPromise;\n\t}\n\n\tprivate async requestOk(command: DaemonCommandBody): Promise<void> {\n\t\tawait this.requestData<unknown>(command);\n\t}\n\n\tprivate async requestData<T>(\n\t\tcommand: DaemonCommandBody,\n\t\ttimeoutMs?: number,\n\t\toptions?: Parameters<DaemonClient[\"request\"]>[2],\n\t): Promise<T> {\n\t\tconst response = await this.client.request(command, timeoutMs, options);\n\t\tif (!response.success) {\n\t\t\tconst error = deserializeDaemonError(response);\n\t\t\tthis.definitiveRequestErrors.add(error);\n\t\t\tthrow error;\n\t\t}\n\t\tif (invalidatesCachedSnapshot(command.type)) {\n\t\t\tthis.latestSnapshotIsFresh = false;\n\t\t}\n\t\treturn response.data as T;\n\t}\n\n\tprivate async handleDaemonMessage(message: DaemonOutbound): Promise<void> {\n\t\tif (message.type === \"heartbeats_changed\") {\n\t\t\tawait this.emit({ type: \"heartbeats_changed\" });\n\t\t\treturn;\n\t\t}\n\t\tif (!this.isMessageForActiveSession(message)) {\n\t\t\treturn;\n\t\t}\n\t\tif (\"snapshotId\" in message && this.ignoredSnapshotIds.has(message.snapshotId)) {\n\t\t\tif (message.type === \"session_snapshot_end\" || message.type === \"session_snapshot_failed\") {\n\t\t\t\tthis.ignoredSnapshotIds.delete(message.snapshotId);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (message.type === \"session_snapshot_begin\") {\n\t\t\tconst assembly = this.getSnapshotAssembly(message.snapshotId);\n\t\t\tassembly.begin = message;\n\t\t\treturn;\n\t\t}\n\t\tif (message.type === \"session_snapshot_chunk\") {\n\t\t\tthis.getSnapshotAssembly(message.snapshotId).chunks.set(message.index, message.messages);\n\t\t\treturn;\n\t\t}\n\t\tif (message.type === \"session_snapshot_end\") {\n\t\t\tawait this.completeSnapshotAssembly(message);\n\t\t\treturn;\n\t\t}\n\t\tif (message.type === \"session_snapshot_failed\") {\n\t\t\tconst assembly = this.getSnapshotAssembly(message.snapshotId);\n\t\t\tconst purpose = assembly.begin?.purpose ?? \"attach\";\n\t\t\tconst snapshotError = new Error(message.error);\n\t\t\tconst recoveryPromise =\n\t\t\t\tpurpose === \"replacement\" || purpose === \"resync\"\n\t\t\t\t\t? this.recoverFailedSnapshot(purpose, snapshotError)\n\t\t\t\t\t: undefined;\n\t\t\tif (recoveryPromise) {\n\t\t\t\tthis.snapshotRecoveryPromises.set(message.snapshotId, recoveryPromise);\n\t\t\t}\n\t\t\tthis.rejectSnapshotAssembly(message.snapshotId, assembly, snapshotError);\n\t\t\tthis.ignoreSnapshotId(message.snapshotId);\n\t\t\tif (recoveryPromise) {\n\t\t\t\ttry {\n\t\t\t\t\tawait recoveryPromise;\n\t\t\t\t} finally {\n\t\t\t\t\tthis.snapshotRecoveryPromises.delete(message.snapshotId);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (this.isStaleSequencedMessage(message)) {\n\t\t\treturn;\n\t\t}\n\t\tthis.observeDaemonEventSequence(message);\n\n\t\tif (message.type === \"session_event\") {\n\t\t\tif (message.event.type !== \"refine_complete\" && message.event.type !== \"refine_failed\") {\n\t\t\t\tthis.observeStreamingMessage(message.event);\n\t\t\t}\n\t\t\tif (message.event.type === \"rlm_child_update\") {\n\t\t\t\tthis.childRosterSequence = maxEventSequence(this.childRosterSequence, getDaemonMessageSequence(message));\n\t\t\t\tthis.observeRlmChildUpdate(message.event.child);\n\t\t\t}\n\t\t\tthis.latestSnapshotIsFresh = false;\n\t\t\tawait this.emit({ type: \"session_event\", event: message.event });\n\t\t\treturn;\n\t\t}\n\t\tif (message.type === \"side_question_event\") {\n\t\t\tthis.observeSideQuestionEvent(message.event);\n\t\t\tawait this.emit({ type: \"side_question_event\", event: message.event });\n\t\t\treturn;\n\t\t}\n\t\tif (message.type === \"session_status\") {\n\t\t\t// Keep a cached snapshot's recap current so a later re-attach seeds it.\n\t\t\tif (this.latestSnapshot) {\n\t\t\t\tthis.latestSnapshot = {\n\t\t\t\t\t...this.latestSnapshot,\n\t\t\t\t\tstate: { ...this.latestSnapshot.state, recap: message.recap },\n\t\t\t\t};\n\t\t\t}\n\t\t\tawait this.emit({ type: \"session_status\", recap: message.recap });\n\t\t\treturn;\n\t\t}\n\t\tif (message.type === \"session_resynced\") {\n\t\t\tthis.attachedSessionId = message.snapshot.state.sessionId;\n\t\t\tthis.attachedSessionFile = message.snapshot.state.sessionFile;\n\t\t\tthis.latestSnapshot = mapDaemonSessionSnapshot(message.snapshot);\n\t\t\tif (Array.isArray(message.snapshot.children)) {\n\t\t\t\tthis.childRosterSequence = message.snapshot.lastEventSequence;\n\t\t\t}\n\t\t\tif (this.lastEventSequence !== undefined) {\n\t\t\t\tthis.latestSnapshot.lastEventSequence = this.lastEventSequence;\n\t\t\t}\n\t\t\tif (this.lastEventCursor) {\n\t\t\t\tthis.latestSnapshot.lastEventCursor = this.lastEventCursor;\n\t\t\t}\n\t\t\tthis.latestSnapshotIsFresh = true;\n\t\t\tawait this.emit({ type: \"session_resynced\", snapshot: this.latestSnapshot });\n\t\t\treturn;\n\t\t}\n\t\tif (message.type === \"session_replaced\") {\n\t\t\tthis.attachedSessionId = message.state.sessionId;\n\t\t\tthis.attachedSessionFile = message.state.sessionFile;\n\t\t\tif (message.snapshotFollows) {\n\t\t\t\tthis.latestSnapshotIsFresh = false;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst latestSnapshot: AgentConnectionSnapshot = {\n\t\t\t\tstate: message.state,\n\t\t\t\tmessages: message.messages,\n\t\t\t};\n\t\t\tif (this.lastEventSequence !== undefined) {\n\t\t\t\tlatestSnapshot.lastEventSequence = this.lastEventSequence;\n\t\t\t}\n\t\t\tif (this.lastEventCursor) {\n\t\t\t\tlatestSnapshot.lastEventCursor = this.lastEventCursor;\n\t\t\t}\n\t\t\tthis.latestSnapshot = latestSnapshot;\n\t\t\tthis.childRosterSequence = undefined;\n\t\t\tthis.latestSnapshotIsFresh = true;\n\t\t\tawait this.emit({ type: \"session_replaced\", state: message.state, messages: message.messages });\n\t\t\treturn;\n\t\t}\n\t\tif (message.type === \"extension_ui_request\") {\n\t\t\tawait this.emit({\n\t\t\t\ttype: \"extension_ui_request\",\n\t\t\t\trequest: {\n\t\t\t\t\tid: message.id,\n\t\t\t\t\tmethod: message.method,\n\t\t\t\t\tpayload: message.payload,\n\t\t\t\t},\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tif (message.type === \"extension_error\") {\n\t\t\tawait this.emit({\n\t\t\t\ttype: \"extension_error\",\n\t\t\t\textensionPath: message.extensionPath,\n\t\t\t\tevent: message.event,\n\t\t\t\terror: message.error,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tif (message.type === \"session_closed\") {\n\t\t\tif (message.reason === \"update\") {\n\t\t\t\tthis.captureDaemonLogPath();\n\t\t\t\tthis.updateRestartPending = true;\n\t\t\t\tvoid this.reconnectAfterUpdate();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.terminalCloseEmitted = true;\n\t\t\tawait this.emit({ type: \"closed\", error: this.formatDaemonSessionClosedError(message.reason) });\n\t\t}\n\t}\n\n\tprivate captureDaemonLogPath(): void {\n\t\tconst socketPath = this.client.hello?.socketPath;\n\t\tif (socketPath) {\n\t\t\tthis.daemonLogPath = getDaemonLogPath(socketPath);\n\t\t}\n\t}\n\n\tprivate formatDaemonSessionClosedError(reason: DaemonSessionClosedReason): string {\n\t\tconst explanation: Record<DaemonSessionClosedReason, string> = {\n\t\t\tkilled:\n\t\t\t\t\"The daemon stopped this agent session. Its transcript remains saved and can be reopened from Agents View.\",\n\t\t\tshutdown:\n\t\t\t\t\"The ASM Agent daemon shut down while this window was attached. The session transcript remains saved; restart ASM Agent and reopen it from Agents View.\",\n\t\t\tcompleted:\n\t\t\t\t\"The daemon closed this agent session after it completed. Its transcript remains available from Agents View.\",\n\t\t\treplaced:\n\t\t\t\t\"The daemon replaced this agent session with another session. Reopen the current session from Agents View.\",\n\t\t\tupdate:\n\t\t\t\t\"The ASM Agent daemon restarted for an update, but this window did not restore automatically. The session transcript remains saved; restart ASM Agent and reopen it from Agents View.\",\n\t\t};\n\t\treturn `${explanation[reason]} ${this.formatDaemonDiagnosticContext()}`;\n\t}\n\n\tprivate formatDaemonConnectionClosedError(error: Error): string {\n\t\treturn `Lost connection to the ASM Agent daemon. Cause: ${formatErrorSentence(error)} The session transcript remains saved; restart ASM Agent or reopen the session from Agents View. ${this.formatDaemonDiagnosticContext()}`;\n\t}\n\n\tprivate formatUpdateReconnectError(error: unknown): string {\n\t\treturn `The ASM Agent daemon restarted for an update, but this window could not reconnect to its restored session before the recovery timeout expired. Last error: ${formatErrorSentence(error)} The session transcript remains saved; restart ASM Agent and reopen it from Agents View. ${this.formatDaemonDiagnosticContext()}`;\n\t}\n\n\tprivate formatDaemonDiagnosticContext(): string {\n\t\tconst details: string[] = [];\n\t\tif (this.attachedSessionId) {\n\t\t\tdetails.push(`Session ID: ${this.attachedSessionId}.`);\n\t\t}\n\t\tif (this.attachedSessionFile) {\n\t\t\tdetails.push(`Session file: ${this.attachedSessionFile}.`);\n\t\t}\n\t\tdetails.push(`Diagnostic log: ${this.daemonLogPath ?? getAgentLogPath()}.`);\n\t\treturn details.join(\" \");\n\t}\n\n\tprivate reconnectAfterUpdate(): Promise<void> {\n\t\tif (this.updateReconnectPromise) {\n\t\t\treturn this.updateReconnectPromise;\n\t\t}\n\t\tvoid this.emit({\n\t\t\ttype: \"connection_status\",\n\t\t\tstatus: \"reconnecting\",\n\t\t\terror: \"The ASM Agent daemon is restarting for an update.\",\n\t\t});\n\t\tconst reconnectPromise = reconnectDaemonTransportAfterUpdate(this.client)\n\t\t\t.then(() => this.restoreConnectionAfterUpdate())\n\t\t\t.then(() => {\n\t\t\t\tif (!this.disposed) {\n\t\t\t\t\tvoid this.emit({ type: \"connection_status\", status: \"connected\" });\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch(async (error: unknown) => {\n\t\t\t\tthis.updateRestartPending = false;\n\t\t\t\tthis.updateReconnectFailed = true;\n\t\t\t\tif (!this.disposed) {\n\t\t\t\t\tthis.terminalCloseEmitted = true;\n\t\t\t\t\tawait this.emit({\n\t\t\t\t\t\ttype: \"closed\",\n\t\t\t\t\t\terror: this.formatUpdateReconnectError(error),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\tif (this.updateReconnectPromise === reconnectPromise) {\n\t\t\t\t\tthis.updateReconnectPromise = undefined;\n\t\t\t\t}\n\t\t\t});\n\t\tthis.updateReconnectPromise = reconnectPromise;\n\t\treturn reconnectPromise;\n\t}\n\n\tprivate async restoreConnectionAfterUpdate(): Promise<void> {\n\t\tconst sessionId = this.attachedSessionId;\n\t\tconst sessionFile = this.attachedSessionFile;\n\t\tif (!sessionId && !sessionFile) {\n\t\t\tthrow new Error(\"the previous session identity is unavailable\");\n\t\t}\n\t\tconst deadline = Date.now() + UPDATE_RECONNECT_TIMEOUT_MS;\n\t\tlet lastError: unknown;\n\t\twhile (!this.disposed && Date.now() < deadline) {\n\t\t\ttry {\n\t\t\t\tawait this.client.reconnect(1000);\n\t\t\t\tif (this.disposed) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst response = await this.client.request({ type: \"list\" }, 30000);\n\t\t\t\tif (this.disposed) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!response.success) {\n\t\t\t\t\tthrow deserializeDaemonError(response);\n\t\t\t\t}\n\t\t\t\tconst sessions = readSessionSummaries(response.data);\n\t\t\t\tconst restored = sessions.find(\n\t\t\t\t\t(summary) =>\n\t\t\t\t\t\tsummary.activeSessionId !== undefined &&\n\t\t\t\t\t\t((sessionFile !== undefined && summary.sessionFile === sessionFile) ||\n\t\t\t\t\t\t\t(sessionId !== undefined && summary.sessionId === sessionId)),\n\t\t\t\t);\n\t\t\t\tif (restored?.activeSessionId) {\n\t\t\t\t\tif (this.disposed) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthis.activeSessionId = restored.activeSessionId;\n\t\t\t\t\tthis.lastEventSequence = undefined;\n\t\t\t\t\tthis.lastEventCursor = undefined;\n\t\t\t\t\tthis.retiredEventGenerations.clear();\n\t\t\t\t\tawait this.attach();\n\t\t\t\t\tif (this.disposed) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tconst snapshot = await this.getInitialSnapshot();\n\t\t\t\t\tif (this.disposed) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthis.updateRestartPending = false;\n\t\t\t\t\tvoid this.emit({ type: \"session_resynced\", snapshot });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tlastError = error;\n\t\t\t}\n\t\t\tawait delay(UPDATE_RECONNECT_RETRY_MS);\n\t\t}\n\t\tif (this.disposed) {\n\t\t\treturn;\n\t\t}\n\t\tthrow lastError ?? new Error(\"the restored session did not become available\");\n\t}\n\n\tprivate getSnapshotAssembly(snapshotId: string): DaemonSnapshotAssembly {\n\t\tconst existing = this.snapshotAssemblies.get(snapshotId);\n\t\tif (existing) {\n\t\t\treturn existing;\n\t\t}\n\t\tlet resolveSnapshot!: (snapshot: DaemonSessionSnapshot) => void;\n\t\tlet rejectSnapshot!: (error: Error) => void;\n\t\tconst promise = new Promise<DaemonSessionSnapshot>((resolve, reject) => {\n\t\t\tresolveSnapshot = resolve;\n\t\t\trejectSnapshot = reject;\n\t\t});\n\t\tvoid promise.catch(() => undefined);\n\t\tconst timeout = setTimeout(() => {\n\t\t\tconst current = this.snapshotAssemblies.get(snapshotId);\n\t\t\tif (current) {\n\t\t\t\tcurrent.reject(new Error(`Timed out waiting for snapshot ${snapshotId}`));\n\t\t\t\tthis.snapshotAssemblies.delete(snapshotId);\n\t\t\t\tthis.ignoreSnapshotId(snapshotId);\n\t\t\t}\n\t\t}, this.options.snapshotTimeoutMs ?? DAEMON_SNAPSHOT_TIMEOUT_MS);\n\t\ttimeout.unref();\n\t\tconst assembly: DaemonSnapshotAssembly = {\n\t\t\tchunks: new Map(),\n\t\t\tpromise,\n\t\t\tresolve: resolveSnapshot,\n\t\t\treject: rejectSnapshot,\n\t\t\ttimeout,\n\t\t};\n\t\tthis.snapshotAssemblies.set(snapshotId, assembly);\n\t\treturn assembly;\n\t}\n\n\tprivate rejectSnapshotAssemblies(error: Error): void {\n\t\tfor (const assembly of this.snapshotAssemblies.values()) {\n\t\t\tclearTimeout(assembly.timeout);\n\t\t\tassembly.reject(error);\n\t\t}\n\t\tthis.snapshotAssemblies.clear();\n\t\tthis.completedSnapshots.clear();\n\t\tthis.snapshotRecoveryPromises.clear();\n\t\tthis.ignoredSnapshotIds.clear();\n\t}\n\n\tprivate ignoreSnapshotId(snapshotId: string): void {\n\t\tthis.ignoredSnapshotIds.add(snapshotId);\n\t\twhile (this.ignoredSnapshotIds.size > MAX_IGNORED_SNAPSHOT_IDS) {\n\t\t\tconst oldest = this.ignoredSnapshotIds.values().next().value;\n\t\t\tif (oldest === undefined) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tthis.ignoredSnapshotIds.delete(oldest);\n\t\t}\n\t}\n\n\tprivate rejectSnapshotAssembly(snapshotId: string, assembly: DaemonSnapshotAssembly, error: Error): void {\n\t\tassembly.reject(error);\n\t\tclearTimeout(assembly.timeout);\n\t\tif (assembly.begin?.purpose && assembly.begin.purpose !== \"attach\") {\n\t\t\tthis.snapshotAssemblies.delete(snapshotId);\n\t\t}\n\t}\n\n\tprivate async recoverFailedSnapshot(purpose: \"replacement\" | \"resync\", snapshotError: Error): Promise<void> {\n\t\tthis.latestSnapshotIsFresh = false;\n\t\tif (purpose === \"replacement\") {\n\t\t\tthis.latestSnapshot = undefined;\n\t\t}\n\t\ttry {\n\t\t\tconst snapshot = await this.getInitialSnapshot();\n\t\t\tif (this.disposed) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.attachedSessionId = snapshot.state.sessionId;\n\t\t\tthis.attachedSessionFile = snapshot.state.sessionFile;\n\t\t\tif (purpose === \"replacement\") {\n\t\t\t\tawait this.emit({ type: \"session_replaced\", state: snapshot.state, messages: snapshot.messages });\n\t\t\t} else {\n\t\t\t\tawait this.emit({ type: \"session_resynced\", snapshot });\n\t\t\t}\n\t\t} catch (recoveryError) {\n\t\t\tif (this.disposed) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.terminalCloseEmitted = true;\n\t\t\tawait this.emit({\n\t\t\t\ttype: \"closed\",\n\t\t\t\terror: `Failed to recover from a ${purpose} snapshot transfer. Snapshot error: ${formatErrorSentence(snapshotError)} Recovery error: ${formatErrorSentence(recoveryError)} ${this.formatDaemonDiagnosticContext()}`,\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate async waitForSnapshot(snapshotId: string): Promise<DaemonSessionSnapshot> {\n\t\tconst completed = this.completedSnapshots.get(snapshotId);\n\t\tif (completed) {\n\t\t\tthis.completedSnapshots.delete(snapshotId);\n\t\t\treturn completed;\n\t\t}\n\t\tconst assembly = this.getSnapshotAssembly(snapshotId);\n\t\ttry {\n\t\t\treturn await assembly.promise;\n\t\t} finally {\n\t\t\tclearTimeout(assembly.timeout);\n\t\t\tthis.snapshotAssemblies.delete(snapshotId);\n\t\t\tthis.completedSnapshots.delete(snapshotId);\n\t\t}\n\t}\n\n\tprivate applyReplacementSnapshot(snapshot: DaemonSessionSnapshot, replay?: DaemonReplayInfo): void {\n\t\tif (snapshot.lastEventCursor) {\n\t\t\tthis.observeEventCursor(snapshot.lastEventCursor);\n\t\t}\n\t\tthis.lastEventSequence = maxEventSequence(this.lastEventSequence, snapshot.lastEventSequence);\n\t\tthis.attachedSessionId = snapshot.state.sessionId;\n\t\tthis.attachedSessionFile = snapshot.state.sessionFile;\n\t\tthis.latestSnapshot = mapDaemonSessionSnapshot(snapshot, replay);\n\t\tthis.childRosterSequence = Array.isArray(snapshot.children) ? snapshot.lastEventSequence : undefined;\n\t\tthis.latestSnapshotIsFresh = true;\n\t}\n\n\tprivate async completeSnapshotAssembly(\n\t\tmessage: Extract<DaemonOutbound, { type: \"session_snapshot_end\" }>,\n\t): Promise<void> {\n\t\tconst assembly = this.getSnapshotAssembly(message.snapshotId);\n\t\tif (!assembly.begin) {\n\t\t\tthis.rejectSnapshotAssembly(\n\t\t\t\tmessage.snapshotId,\n\t\t\t\tassembly,\n\t\t\t\tnew Error(`Snapshot ${message.snapshotId} ended before it began`),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tif (assembly.chunks.size !== message.chunkCount) {\n\t\t\tthis.rejectSnapshotAssembly(\n\t\t\t\tmessage.snapshotId,\n\t\t\t\tassembly,\n\t\t\t\tnew Error(\n\t\t\t\t\t`Snapshot ${message.snapshotId} ended with ${assembly.chunks.size} of ${message.chunkCount} chunks`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tconst messages: AgentMessage[] = [];\n\t\tfor (let index = 0; index < message.chunkCount; index++) {\n\t\t\tconst chunk = assembly.chunks.get(index);\n\t\t\tif (!chunk) {\n\t\t\t\tthis.rejectSnapshotAssembly(\n\t\t\t\t\tmessage.snapshotId,\n\t\t\t\t\tassembly,\n\t\t\t\t\tnew Error(`Snapshot ${message.snapshotId} is missing chunk ${index}`),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tmessages.push(...chunk);\n\t\t}\n\t\tif (messages.length !== assembly.begin.messageCount) {\n\t\t\tthis.rejectSnapshotAssembly(\n\t\t\t\tmessage.snapshotId,\n\t\t\t\tassembly,\n\t\t\t\tnew Error(\n\t\t\t\t\t`Snapshot ${message.snapshotId} contained ${messages.length} of ${assembly.begin.messageCount} messages`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tconst snapshot: DaemonSessionSnapshot = {\n\t\t\t...assembly.begin.snapshot,\n\t\t\tmessages,\n\t\t\tlastEventSequence: message.lastEventSequence,\n\t\t\tlastEventCursor: message.lastEventCursor,\n\t\t};\n\t\tif (message.lastEventCursor) {\n\t\t\tthis.observeEventCursor(message.lastEventCursor);\n\t\t}\n\t\tthis.lastEventSequence = maxEventSequence(this.lastEventSequence, message.lastEventSequence);\n\t\tthis.attachedSessionId = snapshot.state.sessionId;\n\t\tthis.attachedSessionFile = snapshot.state.sessionFile;\n\t\tthis.latestSnapshot = mapDaemonSessionSnapshot(snapshot);\n\t\tthis.latestSnapshotIsFresh = true;\n\t\tassembly.resolve(snapshot);\n\t\tconst purpose = assembly.begin.purpose ?? \"attach\";\n\t\tclearTimeout(assembly.timeout);\n\t\tif (purpose !== \"attach\") {\n\t\t\tthis.snapshotAssemblies.delete(message.snapshotId);\n\t\t\tif (this.pendingReattachActiveSessionIds.has(message.activeSessionId)) {\n\t\t\t\tthis.completedSnapshots.set(message.snapshotId, snapshot);\n\t\t\t\twhile (this.completedSnapshots.size > MAX_COMPLETED_SNAPSHOTS) {\n\t\t\t\t\tconst oldest = this.completedSnapshots.keys().next().value;\n\t\t\t\t\tif (oldest === undefined) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tthis.completedSnapshots.delete(oldest);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (purpose === \"replacement\") {\n\t\t\tawait this.emit({ type: \"session_replaced\", state: snapshot.state, messages });\n\t\t} else if (purpose === \"resync\") {\n\t\t\tawait this.emit({ type: \"session_resynced\", snapshot: this.latestSnapshot });\n\t\t}\n\t}\n\n\tprivate observeRlmChildUpdate(child: AgentConnectionRlmChildAgentSnapshot): void {\n\t\tif (!this.latestSnapshot) return;\n\t\tconst children = this.latestSnapshot.children ?? [];\n\t\tconst index = children.findIndex((candidate) => candidate.id === child.id);\n\t\tconst updatedChildren = [...children];\n\t\tif (index === -1) {\n\t\t\tupdatedChildren.push(child);\n\t\t} else {\n\t\t\tupdatedChildren[index] = child;\n\t\t}\n\t\tthis.latestSnapshot = { ...this.latestSnapshot, children: updatedChildren };\n\t}\n\n\tprivate observeStreamingMessage(event: AgentSessionEvent): void {\n\t\tif (!this.latestSnapshot) {\n\t\t\treturn;\n\t\t}\n\t\tif ((event.type === \"message_start\" || event.type === \"message_update\") && event.message.role === \"assistant\") {\n\t\t\tthis.latestSnapshot = { ...this.latestSnapshot, streamingMessage: event.message };\n\t\t\treturn;\n\t\t}\n\t\tif ((event.type === \"message_end\" && event.message.role === \"assistant\") || event.type === \"agent_end\") {\n\t\t\tconst { streamingMessage: _streamingMessage, ...snapshot } = this.latestSnapshot;\n\t\t\tthis.latestSnapshot = snapshot;\n\t\t}\n\t}\n\n\tprivate isMessageForActiveSession(message: DaemonOutbound): boolean {\n\t\tif (!(\"activeSessionId\" in message)) {\n\t\t\treturn false;\n\t\t}\n\t\treturn message.activeSessionId === this.activeSessionId;\n\t}\n\n\tprivate isStaleSequencedMessage(message: DaemonOutbound): boolean {\n\t\tconst cursor = getDaemonMessageCursor(message);\n\t\tif (cursor) {\n\t\t\tif (this.retiredEventGenerations.has(cursor.generation)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn (\n\t\t\t\tthis.lastEventCursor?.generation === cursor.generation && cursor.sequence <= this.lastEventCursor.sequence\n\t\t\t);\n\t\t}\n\t\tconst sequence = getDaemonMessageSequence(message);\n\t\treturn sequence !== undefined && this.lastEventSequence !== undefined && sequence <= this.lastEventSequence;\n\t}\n\n\tprivate observeDaemonEventSequence(message: DaemonOutbound): void {\n\t\tconst cursor = getDaemonMessageCursor(message);\n\t\tif (cursor) {\n\t\t\tthis.observeEventCursor(cursor);\n\t\t\tthis.lastEventSequence = cursor.sequence;\n\t\t\treturn;\n\t\t}\n\t\tconst sequence = getDaemonMessageSequence(message);\n\t\tif (sequence === undefined) {\n\t\t\treturn;\n\t\t}\n\t\tthis.lastEventSequence =\n\t\t\tthis.lastEventSequence === undefined ? sequence : Math.max(this.lastEventSequence, sequence);\n\t\tif (this.lastEventCursor) {\n\t\t\tthis.lastEventCursor = {\n\t\t\t\t...this.lastEventCursor,\n\t\t\t\tsequence: Math.max(this.lastEventCursor.sequence, sequence),\n\t\t\t};\n\t\t}\n\t}\n\n\tprivate observeEventCursor(cursor: DaemonEventCursor): void {\n\t\tconst current = this.lastEventCursor;\n\t\tif (current && current.generation !== cursor.generation) {\n\t\t\tthis.retiredEventGenerations.add(current.generation);\n\t\t}\n\t\tif (!current || current.generation !== cursor.generation || cursor.sequence > current.sequence) {\n\t\t\tthis.lastEventCursor = cursor;\n\t\t}\n\t}\n\n\tprivate async emit(event: AgentConnectionEvent): Promise<void> {\n\t\tconst deliveries: Promise<void>[] = [];\n\t\tfor (const listener of [...this.listeners]) {\n\t\t\ttry {\n\t\t\t\tdeliveries.push(Promise.resolve(listener(event)));\n\t\t\t} catch {\n\t\t\t\t// One attachment must not interrupt delivery or transport recovery for the others.\n\t\t\t}\n\t\t}\n\t\tawait Promise.allSettled(deliveries);\n\t}\n\n\tprivate observeSideQuestionEvent(event: AgentConnectionSideQuestionEvent): void {\n\t\tif (event.status !== \"running\") {\n\t\t\tthis.activeSideQuestionIds.delete(event.id);\n\t\t}\n\t}\n}\n\nfunction readSessionSummaries(value: unknown): SessionSummary[] {\n\tif (!value || typeof value !== \"object\" || !Array.isArray((value as { sessions?: unknown }).sessions)) {\n\t\tthrow new Error(\"Daemon returned an invalid session list response\");\n\t}\n\treturn (value as { sessions: SessionSummary[] }).sessions;\n}\n\nfunction getAttachActiveSessionId(result: SessionSummary | DaemonAttachResult): string {\n\tif (\"snapshot\" in result) {\n\t\treturn result.activeSessionId;\n\t}\n\treturn result.activeSessionId ?? result.id;\n}\n\nfunction getAttachLastEventSequence(result: SessionSummary | DaemonAttachResult): number | undefined {\n\tif (\"lastEventSequence\" in result) {\n\t\treturn result.lastEventSequence;\n\t}\n\treturn undefined;\n}\n\nfunction getAttachLastEventCursor(result: SessionSummary | DaemonAttachResult): DaemonEventCursor | undefined {\n\tif (\"lastEventCursor\" in result) {\n\t\treturn result.lastEventCursor;\n\t}\n\treturn undefined;\n}\n\nfunction maxEventSequence(current: number | undefined, observed: number | undefined): number | undefined {\n\tif (current === undefined) {\n\t\treturn observed;\n\t}\n\tif (observed === undefined) {\n\t\treturn current;\n\t}\n\treturn Math.max(current, observed);\n}\n\nfunction mapDaemonSessionSnapshot(snapshot: DaemonSessionSnapshot, replay?: DaemonReplayInfo): AgentConnectionSnapshot {\n\tconst connectionSnapshot: AgentConnectionSnapshot = {\n\t\tstate: snapshot.state,\n\t\tmessages: snapshot.messages,\n\t\t...(snapshot.summary.streamingMessage ? { streamingMessage: snapshot.summary.streamingMessage } : {}),\n\t\tlastEventSequence: snapshot.lastEventSequence,\n\t\tlastEventCursor: snapshot.lastEventCursor,\n\t};\n\tif (snapshot.sessionContext) {\n\t\tconnectionSnapshot.sessionContext = snapshot.sessionContext;\n\t}\n\tif (snapshot.sessionTree) {\n\t\tconnectionSnapshot.sessionTree = snapshot.sessionTree;\n\t}\n\tif (snapshot.parent) {\n\t\tconnectionSnapshot.parent = snapshot.parent;\n\t}\n\tif (snapshot.children) {\n\t\tconnectionSnapshot.children = snapshot.children;\n\t}\n\tif (replay) {\n\t\tconnectionSnapshot.replay = replay;\n\t}\n\treturn connectionSnapshot;\n}\n\nfunction getDaemonMessageSequence(message: DaemonOutbound): number | undefined {\n\tif (!(\"meta\" in message)) {\n\t\treturn undefined;\n\t}\n\treturn message.meta?.sequence;\n}\n\nfunction getDaemonMessageCursor(message: DaemonOutbound): DaemonEventCursor | undefined {\n\tif (!(\"meta\" in message)) {\n\t\treturn undefined;\n\t}\n\treturn message.meta?.cursor;\n}\n\nfunction invalidatesCachedSnapshot(commandType: DaemonCommandBody[\"type\"]): boolean {\n\tswitch (commandType) {\n\t\tcase \"attach\":\n\t\tcase \"reattach\":\n\t\tcase \"detach\":\n\t\tcase \"list\":\n\t\tcase \"list_saved_sessions\":\n\t\tcase \"wait_for_idle\":\n\t\tcase \"get_state\":\n\t\tcase \"get_connection_state\":\n\t\tcase \"get_messages\":\n\t\tcase \"get_session_stats\":\n\t\tcase \"get_commands\":\n\t\tcase \"get_resource_snapshot\":\n\t\tcase \"get_model_catalog\":\n\t\tcase \"get_available_models\":\n\t\tcase \"get_queue\":\n\t\tcase \"cron_list\":\n\t\tcase \"heartbeats_list\":\n\t\tcase \"get_session_context\":\n\t\tcase \"get_session_tree\":\n\t\tcase \"get_user_messages_for_forking\":\n\t\tcase \"get_last_assistant_text\":\n\t\tcase \"get_system_prompt\":\n\t\tcase \"get_tool_definition\":\n\t\tcase \"start_side_question\":\n\t\tcase \"abort_side_question\":\n\t\tcase \"export_html\":\n\t\tcase \"export_jsonl\":\n\t\t\treturn false;\n\t\tdefault:\n\t\t\treturn true;\n\t}\n}\n"]}
1
+ {"version":3,"file":"daemon-agent-connection.d.ts","sourceRoot":"","sources":["../../../src/modes/agent-connection/daemon-agent-connection.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport type { AgentMessage, ThinkingLevel } from \"@asm-agent/agent\";\nimport type { ImageContent, ServiceTier, Transport } from \"@asm-agent/ai\";\nimport { appendRotatingLog, getAgentLogPath, getDaemonLogPath } from \"../../config.js\";\nimport type { AgentSessionMessageReceipt, AgentSessionMessageSafetyStatus } from \"../../core/agent-messages.js\";\nimport type { AgentSessionEvent } from \"../../core/agent-session.js\";\nimport type { AgentSessionRuntimeConfig } from \"../../core/agent-session-config.js\";\nimport type { AgentAutonomousStatus } from \"../../core/autonomous.js\";\nimport type { BashResult } from \"../../core/bash-executor.js\";\nimport type { CompactionResult } from \"../../core/compaction/index.js\";\nimport type { ContextTreeNode } from \"../../core/context-tree.js\";\nimport type {\n\tAgentCronJob,\n\tAgentHeartbeatDeliveryMode,\n\tAgentHeartbeatManagementAction,\n\tAgentHeartbeatUpdateAction,\n} from \"../../core/cron-jobs.js\";\nimport type { AcpMcpServerConfig } from \"../../core/mcp/acp-mcp-types.js\";\nimport type { RefinementResult } from \"../../core/refinement/index.js\";\nimport type { DeleteSessionFileResult } from \"../../core/session-file-actions.js\";\nimport { SessionAlreadyActiveError } from \"../../core/session-lease.js\";\nimport type { SessionStats } from \"../../core/session-stats.js\";\nimport {\n\tDaemonCapabilityUnavailableError,\n\ttype DaemonClient,\n\tgetDaemonSocketCloseReason,\n} from \"../daemon/daemon-client.js\";\nimport { deserializeDaemonError } from \"../daemon/daemon-errors.js\";\nimport {\n\tcollectDaemonClientEnv,\n\tcollectDaemonLaunchEnv,\n\ttype DaemonAttachResult,\n\ttype DaemonCommand,\n\ttype DaemonEventCursor,\n\ttype DaemonOutbound,\n\ttype DaemonReplayInfo,\n\ttype DaemonSessionClosedReason,\n\ttype DaemonSessionSnapshot,\n\tisUnknownDaemonCommandError,\n} from \"../daemon/daemon-protocol.js\";\nimport type { SessionSummary } from \"../daemon/daemon-session-list.js\";\nimport { listDaemonHeartbeats } from \"../daemon/heartbeat-catalog.js\";\nimport {\n\tdeleteDaemonSavedSession,\n\tlistDaemonSavedSessions,\n\trenameDaemonSavedSession,\n} from \"../daemon/saved-session-catalog.js\";\nimport type {\n\tAgentConnection,\n\tAgentConnectionBeforeSessionInvalidateListener,\n\tAgentConnectionEvent,\n\tAgentConnectionEventListener,\n\tAgentConnectionExecuteBashOptions,\n\tAgentConnectionExtensionUiResponse,\n\tAgentConnectionForkOptions,\n\tAgentConnectionHeadlessCompletionOptions,\n\tAgentConnectionHeartbeat,\n\tAgentConnectionModel,\n\tAgentConnectionModelCatalog,\n\tAgentConnectionModelCycleResult,\n\tAgentConnectionNavigateTreeOptions,\n\tAgentConnectionNavigateTreeResult,\n\tAgentConnectionNewSessionOptions,\n\tAgentConnectionPromptOptions,\n\tAgentConnectionQueuedMessageLane,\n\tAgentConnectionQueuedMessageMutation,\n\tAgentConnectionQueuedMessageMutationStatus,\n\tAgentConnectionQueueMode,\n\tAgentConnectionQueueState,\n\tAgentConnectionResourceSnapshot,\n\tAgentConnectionRlmChildAgentSnapshot,\n\tAgentConnectionSavedSessionInfo,\n\tAgentConnectionSavedSessionScope,\n\tAgentConnectionScopedModel,\n\tAgentConnectionSessionContext,\n\tAgentConnectionSessionHeader,\n\tAgentConnectionSessionInputPause,\n\tAgentConnectionSessionListCallbacks,\n\tAgentConnectionSessionTreeFlatNode,\n\tAgentConnectionSessionTreeNode,\n\tAgentConnectionSessionWatcher,\n\tAgentConnectionSideQuestionEvent,\n\tAgentConnectionSideQuestionTurn,\n\tAgentConnectionSlashCommand,\n\tAgentConnectionSnapshot,\n\tAgentConnectionState,\n\tAgentConnectionSwitchSessionOptions,\n\tAgentConnectionToolDefinition,\n\tAgentConnectionUserMessage,\n} from \"./types.js\";\nimport { AgentConnectionPromptAdmissionError } from \"./types.js\";\n\ntype DistributiveOmit<T, K extends keyof T> = T extends unknown ? Omit<T, K> : never;\ntype DaemonCommandBody = DistributiveOmit<DaemonCommand, \"id\">;\ntype DaemonSnapshotBegin = Extract<DaemonOutbound, { type: \"session_snapshot_begin\" }>;\n\ninterface DaemonSnapshotAssembly {\n\tbegin?: DaemonSnapshotBegin;\n\tchunks: Map<number, AgentMessage[]>;\n\tpromise: Promise<DaemonSessionSnapshot>;\n\tresolve: (snapshot: DaemonSessionSnapshot) => void;\n\treject: (error: Error) => void;\n\ttimeout: ReturnType<typeof setTimeout>;\n}\n\nexport const DAEMON_REFINE_REQUEST_TIMEOUT_MS = 10 * 60 * 1000;\nconst DAEMON_LONG_RUNNING_REQUEST_TIMEOUT_MS = 24 * 60 * 60 * 1000;\nexport const DAEMON_RECONNECT_TIMEOUT_MS = 60_000;\nexport const DAEMON_SNAPSHOT_TIMEOUT_MS = 30_000;\nconst MAX_IGNORED_SNAPSHOT_IDS = 128;\nconst UPDATE_RECONNECT_TIMEOUT_MS = 120000;\nconst UPDATE_RECONNECT_RETRY_MS = 100;\nconst MAX_COMPLETED_SNAPSHOTS = 128;\nconst OWNED_SESSION_DISPOSE_RECONNECT_WAIT_MS = 10_000;\nconst updateTransportReconnects = new WeakMap<DaemonClient, Promise<void>>();\n\nfunction delay(ms: number): Promise<void> {\n\treturn new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction formatErrorSentence(error: unknown): string {\n\tconst message = (error instanceof Error ? error.message : String(error)).trim();\n\tif (!message) {\n\t\treturn \"Unknown daemon error.\";\n\t}\n\treturn /[.!?]$/.test(message) ? message : `${message}.`;\n}\n\nfunction reconnectDaemonTransportAfterUpdate(client: DaemonClient): Promise<void> {\n\tconst existing = updateTransportReconnects.get(client);\n\tif (existing) {\n\t\treturn existing;\n\t}\n\tconst reconnectPromise = Promise.resolve()\n\t\t.then(async () => {\n\t\t\tclient.disconnectForReconnect(\"update\");\n\t\t\tconst deadline = Date.now() + UPDATE_RECONNECT_TIMEOUT_MS;\n\t\t\tlet lastError: unknown;\n\t\t\twhile (Date.now() < deadline) {\n\t\t\t\ttry {\n\t\t\t\t\tawait client.reconnect(1000);\n\t\t\t\t\treturn;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tlastError = error;\n\t\t\t\t}\n\t\t\t\tawait delay(UPDATE_RECONNECT_RETRY_MS);\n\t\t\t}\n\t\t\tthrow lastError ?? new Error(\"the updated daemon did not become available\");\n\t\t})\n\t\t.finally(() => {\n\t\t\tif (updateTransportReconnects.get(client) === reconnectPromise) {\n\t\t\t\tupdateTransportReconnects.delete(client);\n\t\t\t}\n\t\t});\n\tupdateTransportReconnects.set(client, reconnectPromise);\n\treturn reconnectPromise;\n}\n\nexport interface DaemonAgentConnectionOptions {\n\tcloseClientOnDispose?: boolean;\n\t/** Restart/probe the detached supervisor after a transient socket loss. */\n\trecoverDaemon?: () => Promise<void>;\n\t/** Bound supervisor recovery before surfacing a fatal connection error. */\n\treconnectTimeoutMs?: number;\n\t/** Bound an incomplete streamed snapshot before failing the attach or resync. */\n\tsnapshotTimeoutMs?: number;\n\t/**\n\t * Send this client's allowlisted env (herdr pane identity) with attach so\n\t * an env-less session (e.g. cron-created) adopts it. Set only by the\n\t * primary interactive connection — the daemon adopts-if-absent, never\n\t * rebinds, so watchers must not send env at all.\n\t */\n\tsendClientEnv?: boolean;\n\t/** Advertise support for interactive extension dialogs. */\n\tsupportsExtensionUi?: boolean;\n\t/** Dispose the connection by stopping its hidden worker instead of detaching. */\n\townedSession?: boolean;\n\t/** Fresh runtime context used only if the owned worker must be relaunched. */\n\townedSessionRecoveryConfig?: AgentSessionRuntimeConfig;\n}\n\n/**\n * AgentConnection adapter for the local daemon JSONL socket transport.\n *\n * InteractiveMode depends only on AgentConnection; local socket ownership and\n * daemon command details stay inside this adapter.\n */\nexport function buildSessionTreeFromFlatNodes(\n\tflatNodes: readonly AgentConnectionSessionTreeFlatNode[],\n): AgentConnectionSessionTreeNode[] {\n\tconst byId = new Map<string, AgentConnectionSessionTreeNode>();\n\tconst roots: AgentConnectionSessionTreeNode[] = [];\n\tfor (const flatNode of flatNodes) {\n\t\tbyId.set(flatNode.entry.id, { ...flatNode, children: [] });\n\t}\n\tfor (const flatNode of flatNodes) {\n\t\tconst entry = flatNode.entry;\n\t\tconst node = byId.get(entry.id)!;\n\t\tconst parent = entry.parentId === null || entry.parentId === entry.id ? undefined : byId.get(entry.parentId);\n\t\tif (parent) parent.children.push(node);\n\t\telse roots.push(node);\n\t}\n\t// Match SessionManager.getTree() ordering without recursively walking deep\n\t// chains: every node is already indexed, so sort each sibling array directly.\n\tfor (const node of byId.values()) {\n\t\tnode.children.sort(\n\t\t\t(left, right) => new Date(left.entry.timestamp).getTime() - new Date(right.entry.timestamp).getTime(),\n\t\t);\n\t}\n\treturn roots;\n}\n\nexport class DaemonAgentConnection implements AgentConnection {\n\tprivate readonly listeners = new Set<AgentConnectionEventListener>();\n\tprivate readonly unsubscribeDaemonMessages: () => void;\n\tprivate readonly unsubscribeDaemonClose: () => void;\n\tprivate readonly clientId = `daemon-agent-connection:${randomUUID()}`;\n\tprivate readonly sessionInputPauses = new Map<string, Promise<AgentConnectionSessionInputPause>>();\n\tprivate sessionInputPauseGeneration = 0;\n\tprivate ownedSessionPromotionTail = Promise.resolve();\n\tprivate lastEventCursor: DaemonEventCursor | undefined;\n\tprivate readonly retiredEventGenerations = new Set<string>();\n\tprivate lastEventSequence: number | undefined;\n\tprivate childRosterSequence: number | undefined;\n\tprivate latestSnapshot: AgentConnectionSnapshot | undefined;\n\tprivate latestSnapshotIsFresh = false;\n\tprivate attachedSessionId: string | undefined;\n\tprivate attachedSessionFile: string | undefined;\n\tprivate daemonLogPath: string | undefined;\n\tprivate updateRestartPending = false;\n\tprivate updateReconnectFailed = false;\n\tprivate terminalCloseEmitted = false;\n\tprivate updateReconnectPromise?: Promise<void>;\n\tprivate readonly activeSideQuestionIds = new Set<string>();\n\tprivate readonly snapshotAssemblies = new Map<string, DaemonSnapshotAssembly>();\n\tprivate readonly completedSnapshots = new Map<string, DaemonSessionSnapshot>();\n\tprivate readonly pendingReattachActiveSessionIds = new Set<string>();\n\tprivate readonly snapshotRecoveryPromises = new Map<string, Promise<void>>();\n\tprivate readonly ignoredSnapshotIds = new Set<string>();\n\tprivate reconnectPromise?: Promise<void>;\n\tprivate readonly definitiveRequestErrors = new WeakSet<Error>();\n\tprivate disposing = false;\n\tprivate disposed = false;\n\n\tconstructor(\n\t\tprivate readonly client: DaemonClient,\n\t\tprivate activeSessionId: string,\n\t\tprivate readonly options: DaemonAgentConnectionOptions = {},\n\t) {\n\t\tif (options.recoverDaemon) {\n\t\t\tthis.client.enableRequestRecovery();\n\t\t}\n\t\tthis.unsubscribeDaemonMessages = this.client.onMessage((message) => {\n\t\t\tvoid this.handleDaemonMessage(message).catch((error: unknown) => {\n\t\t\t\ttry {\n\t\t\t\t\tappendRotatingLog(\n\t\t\t\t\t\tgetAgentLogPath(),\n\t\t\t\t\t\t`[${new Date().toISOString()}] daemon-message: ignored ${message.type} failure: ${String(error)}`,\n\t\t\t\t\t);\n\t\t\t\t} catch {\n\t\t\t\t\t// Logging failure must not turn an isolated message error into a connection failure.\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t\tthis.captureDaemonLogPath();\n\t\tthis.unsubscribeDaemonClose = this.client.onClose((error) => {\n\t\t\tconst invalidatedInputPause = this.sessionInputPauses.size > 0;\n\t\t\tthis.sessionInputPauses.clear();\n\t\t\tthis.sessionInputPauseGeneration++;\n\t\t\tthis.rejectSnapshotAssemblies(error);\n\t\t\tif (this.disposed || this.terminalCloseEmitted) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (invalidatedInputPause) {\n\t\t\t\tthis.terminalCloseEmitted = true;\n\t\t\t\tvoid this.emit({\n\t\t\t\t\ttype: \"closed\",\n\t\t\t\t\terror: \"Daemon connection closed while session input was paused; the fence was invalidated.\",\n\t\t\t\t});\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst closeReason = getDaemonSocketCloseReason(error);\n\t\t\tif (closeReason === \"shutdown\") {\n\t\t\t\tthis.terminalCloseEmitted = true;\n\t\t\t\tvoid this.emit({ type: \"closed\", error: this.formatDaemonSessionClosedError(\"shutdown\") });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif ((this.updateRestartPending || closeReason === \"update\") && !this.updateReconnectFailed) {\n\t\t\t\tthis.updateRestartPending = true;\n\t\t\t\tvoid this.reconnectAfterUpdate();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (this.options.recoverDaemon) {\n\t\t\t\tvoid this.reconnect(error);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.terminalCloseEmitted = true;\n\t\t\tvoid this.emit({ type: \"closed\", error: this.formatDaemonConnectionClosedError(error) });\n\t\t});\n\t}\n\n\tstatic async attach(\n\t\tclient: DaemonClient,\n\t\tactiveSessionId: string,\n\t\toptions?: DaemonAgentConnectionOptions,\n\t): Promise<DaemonAgentConnection> {\n\t\tconst connection = new DaemonAgentConnection(client, activeSessionId, options);\n\t\ttry {\n\t\t\tawait connection.attach();\n\t\t\treturn connection;\n\t\t} catch (error) {\n\t\t\tawait connection.dispose();\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync attach(): Promise<void> {\n\t\tconst supportsExtensionUi = this.options.supportsExtensionUi !== false;\n\t\tconst result = await this.requestData<SessionSummary | DaemonAttachResult>({\n\t\t\ttype: \"attach\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tsupportsExtensionUi,\n\t\t\tclientId: this.clientId,\n\t\t\tcapabilities: [\n\t\t\t\t\"attach_snapshot\",\n\t\t\t\t\"event_sequence\",\n\t\t\t\t...(supportsExtensionUi ? ([\"extension_ui\"] as const) : []),\n\t\t\t\t\"slim_attach\",\n\t\t\t\t\"chunked_snapshot\",\n\t\t\t\t...(this.options.ownedSession ? ([\"client_owned_sessions\"] as const) : []),\n\t\t\t],\n\t\t\tenv: this.options.sendClientEnv ? collectDaemonClientEnv() : undefined,\n\t\t\tlaunchEnv: this.options.ownedSession ? collectDaemonLaunchEnv() : undefined,\n\t\t\t...(this.options.ownedSession &&\n\t\t\tthis.options.ownedSessionRecoveryConfig &&\n\t\t\tthis.client.supportsServerCapability(\"owned_session_recovery_context\")\n\t\t\t\t? { recoveryConfig: this.options.ownedSessionRecoveryConfig }\n\t\t\t\t: {}),\n\t\t\tresumeCursor:\n\t\t\t\tthis.lastEventCursor === undefined\n\t\t\t\t\t? undefined\n\t\t\t\t\t: {\n\t\t\t\t\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\t\t\t\t\t...this.lastEventCursor,\n\t\t\t\t\t\t},\n\t\t});\n\t\tthis.activeSessionId = getAttachActiveSessionId(result);\n\t\tconst summary = \"snapshot\" in result ? result.snapshot.summary : result;\n\t\tthis.attachedSessionId = summary.sessionId;\n\t\tthis.attachedSessionFile =\n\t\t\tsummary.sessionFile ?? (\"snapshot\" in result ? result.snapshot.state.sessionFile : undefined);\n\t\tthis.captureDaemonLogPath();\n\t\tthis.updateReconnectFailed = false;\n\t\tthis.terminalCloseEmitted = false;\n\t\tconst attachCursor = getAttachLastEventCursor(result);\n\t\tif (attachCursor) {\n\t\t\tthis.observeEventCursor(attachCursor);\n\t\t}\n\t\tthis.lastEventSequence = maxEventSequence(this.lastEventSequence, getAttachLastEventSequence(result));\n\t\tif (\"snapshot\" in result) {\n\t\t\tconst snapshot = result.snapshotStream\n\t\t\t\t? await this.waitForSnapshot(result.snapshotStream.id)\n\t\t\t\t: result.snapshot;\n\t\t\tthis.latestSnapshot = mapDaemonSessionSnapshot(snapshot, result.replay);\n\t\t\tif (Array.isArray(snapshot.children)) this.childRosterSequence = snapshot.lastEventSequence;\n\t\t\tif (this.lastEventSequence !== undefined) {\n\t\t\t\tthis.latestSnapshot.lastEventSequence = this.lastEventSequence;\n\t\t\t}\n\t\t\tif (this.lastEventCursor) {\n\t\t\t\tthis.latestSnapshot.lastEventCursor = this.lastEventCursor;\n\t\t\t}\n\t\t\tthis.latestSnapshotIsFresh = true;\n\t\t} else {\n\t\t\tthis.latestSnapshot = undefined;\n\t\t\tthis.latestSnapshotIsFresh = false;\n\t\t}\n\t}\n\n\tsubscribe(listener: AgentConnectionEventListener): () => void {\n\t\tthis.listeners.add(listener);\n\t\treturn () => {\n\t\t\tthis.listeners.delete(listener);\n\t\t};\n\t}\n\n\tonBeforeSessionInvalidate(_listener: AgentConnectionBeforeSessionInvalidateListener): () => void {\n\t\treturn () => {};\n\t}\n\n\tasync getState(): Promise<AgentConnectionState> {\n\t\tif (this.latestSnapshotIsFresh && this.latestSnapshot) {\n\t\t\treturn this.latestSnapshot.state;\n\t\t}\n\t\treturn this.requestData<AgentConnectionState>({\n\t\t\ttype: \"get_connection_state\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t}\n\n\tasync getInitialSnapshot(): Promise<AgentConnectionSnapshot> {\n\t\tif (this.latestSnapshotIsFresh && this.latestSnapshot) {\n\t\t\treturn this.latestSnapshot;\n\t\t}\n\t\t// The session tree is intentionally not fetched here: it is large on long\n\t\t// sessions and only needed when the user opens the tree/branch selector.\n\t\t// getSessionTree() fetches it lazily via get_session_tree on first use.\n\t\tconst snapshotCursor = this.lastEventCursor;\n\t\tconst snapshotSequence = this.lastEventSequence;\n\t\tconst [state, messagesData, sessionContextData] = await Promise.all([\n\t\t\tthis.requestData<AgentConnectionState>({\n\t\t\t\ttype: \"get_connection_state\",\n\t\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\t}),\n\t\t\tthis.requestData<{ messages: AgentMessage[] }>({\n\t\t\t\ttype: \"get_messages\",\n\t\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\t}),\n\t\t\tthis.requestData<{ context: AgentConnectionSessionContext }>({\n\t\t\t\ttype: \"get_session_context\",\n\t\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\t}),\n\t\t]);\n\t\tconst children = this.latestSnapshot?.children;\n\t\tconst streamingMessage = this.latestSnapshot?.streamingMessage;\n\t\tthis.latestSnapshot = {\n\t\t\tstate,\n\t\t\tmessages: messagesData.messages,\n\t\t\tsessionContext: sessionContextData.context,\n\t\t\t...(children ? { children } : {}),\n\t\t\t...(streamingMessage ? { streamingMessage } : {}),\n\t\t};\n\t\tif (snapshotSequence !== undefined) {\n\t\t\tthis.latestSnapshot.lastEventSequence = snapshotSequence;\n\t\t}\n\t\tif (snapshotCursor) {\n\t\t\tthis.latestSnapshot.lastEventCursor = snapshotCursor;\n\t\t}\n\t\tthis.latestSnapshotIsFresh =\n\t\t\tsnapshotSequence === this.lastEventSequence &&\n\t\t\tsnapshotCursor?.generation === this.lastEventCursor?.generation &&\n\t\t\tsnapshotCursor?.sequence === this.lastEventCursor?.sequence;\n\t\treturn this.latestSnapshot;\n\t}\n\n\tasync getRlmChildSnapshots(): Promise<AgentConnectionRlmChildAgentSnapshot[]> {\n\t\tif (!this.client.supportsServerCapability(\"authoritative_child_roster\")) {\n\t\t\tthrow new DaemonCapabilityUnavailableError(\"get_rlm_children\", \"authoritative_child_roster\");\n\t\t}\n\t\tconst data = await this.requestData<{\n\t\t\tchildren: AgentConnectionRlmChildAgentSnapshot[];\n\t\t\teventSequence: number;\n\t\t}>({ type: \"get_rlm_children\", activeSessionId: this.activeSessionId });\n\t\tif (!Array.isArray(data.children) || !Number.isInteger(data.eventSequence)) {\n\t\t\tthrow new Error(\"Daemon returned an invalid child roster\");\n\t\t}\n\t\tif ((this.childRosterSequence ?? -1) > data.eventSequence) {\n\t\t\treturn this.latestSnapshot?.children ?? data.children;\n\t\t}\n\t\tthis.childRosterSequence = data.eventSequence;\n\t\tif (this.latestSnapshot) {\n\t\t\tthis.latestSnapshot = { ...this.latestSnapshot, children: data.children };\n\t\t}\n\t\treturn data.children;\n\t}\n\n\tasync getMessages(): Promise<AgentMessage[]> {\n\t\tif (this.latestSnapshotIsFresh && this.latestSnapshot) {\n\t\t\treturn this.latestSnapshot.messages;\n\t\t}\n\t\tconst data = await this.requestData<{ messages: AgentMessage[] }>({\n\t\t\ttype: \"get_messages\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t\treturn data.messages;\n\t}\n\n\tasync getSessionHeader(): Promise<AgentConnectionSessionHeader | undefined> {\n\t\tconst data = await this.requestData<{ header?: AgentConnectionSessionHeader | null }>({\n\t\t\ttype: \"get_session_header\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t\treturn data.header ?? undefined;\n\t}\n\n\tasync getCommands(): Promise<AgentConnectionSlashCommand[]> {\n\t\tconst data = await this.requestData<{ commands: AgentConnectionSlashCommand[] }>({\n\t\t\ttype: \"get_commands\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t\treturn data.commands;\n\t}\n\n\tasync getResourceSnapshot(): Promise<AgentConnectionResourceSnapshot> {\n\t\treturn this.requestData<AgentConnectionResourceSnapshot>({\n\t\t\ttype: \"get_resource_snapshot\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t}\n\n\tsupportsAcpMcpServers(): boolean {\n\t\treturn this.client.supportsServerCapability(\"acp_mcp_servers\");\n\t}\n\n\tasync replaceAcpMcpServers(servers: readonly AcpMcpServerConfig[], ownerId: string): Promise<void> {\n\t\tif (!this.supportsAcpMcpServers()) {\n\t\t\tthrow new DaemonCapabilityUnavailableError(\"replace_acp_mcp_servers\", \"acp_mcp_servers\");\n\t\t}\n\t\tawait this.requestOk({\n\t\t\ttype: \"replace_acp_mcp_servers\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\townerId,\n\t\t\tservers: [...servers],\n\t\t});\n\t}\n\n\tasync releaseAcpMcpServers(ownerId: string, _serverNames: readonly string[]): Promise<void> {\n\t\tawait this.replaceAcpMcpServers([], ownerId);\n\t}\n\n\tasync getAvailableModels(): Promise<AgentConnectionModel[]> {\n\t\tconst data = await this.requestData<{ models: AgentConnectionModel[] }>({\n\t\t\ttype: \"get_available_models\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t\treturn data.models;\n\t}\n\n\tasync getModelCatalog(): Promise<AgentConnectionModelCatalog> {\n\t\tif (!this.client.supportsServerCapability(\"model_catalog\")) {\n\t\t\tconst models = await this.getAvailableModels();\n\t\t\treturn {\n\t\t\t\tmodels,\n\t\t\t\tconfiguredProviders: [...new Set(models.map((model) => model.provider))],\n\t\t\t};\n\t\t}\n\t\treturn this.requestData<AgentConnectionModelCatalog>({\n\t\t\ttype: \"get_model_catalog\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t}\n\n\tasync getSessionStats(): Promise<SessionStats> {\n\t\treturn this.requestData<SessionStats>({\n\t\t\ttype: \"get_session_stats\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t}\n\n\tasync getContextTree(): Promise<ContextTreeNode> {\n\t\treturn this.requestData<ContextTreeNode>({\n\t\t\ttype: \"get_context_tree\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t}\n\n\tasync getSessionContext(): Promise<AgentConnectionSessionContext> {\n\t\tif (this.latestSnapshotIsFresh && this.latestSnapshot?.sessionContext) {\n\t\t\treturn this.latestSnapshot.sessionContext;\n\t\t}\n\t\tconst data = await this.requestData<{ context: AgentConnectionSessionContext }>({\n\t\t\ttype: \"get_session_context\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t\treturn data.context;\n\t}\n\n\tasync getSessionTree(): Promise<{ tree: AgentConnectionSessionTreeNode[]; leafId: string | null }> {\n\t\tif (this.latestSnapshotIsFresh && this.latestSnapshot?.sessionTree) {\n\t\t\treturn this.latestSnapshot.sessionTree;\n\t\t}\n\t\tconst data = await this.requestData<{\n\t\t\tflatNodes: AgentConnectionSessionTreeFlatNode[];\n\t\t\tleafId: string | null;\n\t\t}>({\n\t\t\ttype: \"get_session_tree\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t\treturn { tree: buildSessionTreeFromFlatNodes(data.flatNodes), leafId: data.leafId };\n\t}\n\n\tasync listSavedSessions(\n\t\tscope: AgentConnectionSavedSessionScope,\n\t\tcallbacks?: AgentConnectionSessionListCallbacks,\n\t): Promise<AgentConnectionSavedSessionInfo[]> {\n\t\treturn listDaemonSavedSessions(this.client, { activeSessionId: this.activeSessionId }, scope, callbacks);\n\t}\n\n\tasync getQueue(): Promise<AgentConnectionQueueState> {\n\t\treturn this.requestData<AgentConnectionQueueState>({\n\t\t\ttype: \"get_queue\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t}\n\n\tasync mutateQueuedMessage(\n\t\tlane: AgentConnectionQueuedMessageLane,\n\t\tindex: number,\n\t\texpectedText: string,\n\t\tmutation: AgentConnectionQueuedMessageMutation,\n\t): Promise<AgentConnectionQueuedMessageMutationStatus> {\n\t\tif (!this.client.supportsServerCapability(\"queue_message_mutation\")) return \"unsupported\";\n\t\tconst data = await this.requestData<{ status: AgentConnectionQueuedMessageMutationStatus }>({\n\t\t\ttype: \"mutate_queued_message\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tlane,\n\t\t\tindex,\n\t\t\texpectedText,\n\t\t\tmutation,\n\t\t});\n\t\treturn data.status;\n\t}\n\n\tasync clearQueue(): Promise<AgentConnectionQueueState> {\n\t\treturn this.requestData<AgentConnectionQueueState>({\n\t\t\ttype: \"clear_queue\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t}\n\n\tasync abortAndClearQueue(): Promise<AgentConnectionQueueState> {\n\t\ttry {\n\t\t\treturn await this.requestData<AgentConnectionQueueState>({\n\t\t\t\ttype: \"abort_and_clear_queue\",\n\t\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (isUnknownDaemonCommandError(error, \"abort_and_clear_queue\")) {\n\t\t\t\tthrow new Error(\"the daemon is running an older build; restart the daemon and try again\");\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync acquireSessionInputPause(leaseKey: string): Promise<AgentConnectionSessionInputPause> {\n\t\tif (this.terminalCloseEmitted) throw new Error(\"Daemon connection is closed; cannot acquire an input pause.\");\n\t\tconst activeSessionId = this.activeSessionId;\n\t\tconst generation = this.sessionInputPauseGeneration;\n\t\tconst acquisitionKey = JSON.stringify([activeSessionId, leaseKey]);\n\t\tconst existing = this.sessionInputPauses.get(acquisitionKey);\n\t\tif (existing) return existing;\n\t\tconst acquisition = (async (): Promise<AgentConnectionSessionInputPause> => {\n\t\t\tconst { pauseId } = await this.requestData<{ pauseId: string }>({\n\t\t\t\ttype: \"acquire_session_input_pause\",\n\t\t\t\tactiveSessionId,\n\t\t\t\tleaseKey,\n\t\t\t});\n\t\t\tif (generation !== this.sessionInputPauseGeneration || this.terminalCloseEmitted) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.requestData({\n\t\t\t\t\t\ttype: \"release_session_input_pause\",\n\t\t\t\t\t\tactiveSessionId,\n\t\t\t\t\t\tpauseId,\n\t\t\t\t\t});\n\t\t\t\t} catch {\n\t\t\t\t\tthis.client.close();\n\t\t\t\t}\n\t\t\t\tthrow new Error(\"Session input pause acquisition was invalidated by a daemon reconnect.\");\n\t\t\t}\n\t\t\tlet released = false;\n\t\t\treturn {\n\t\t\t\trelease: async () => {\n\t\t\t\t\tif (released) return;\n\t\t\t\t\tif (generation !== this.sessionInputPauseGeneration) {\n\t\t\t\t\t\tthrow new Error(\"Session input pause was invalidated by a daemon reconnect.\");\n\t\t\t\t\t}\n\t\t\t\t\tawait this.requestData({\n\t\t\t\t\t\ttype: \"release_session_input_pause\",\n\t\t\t\t\t\tactiveSessionId,\n\t\t\t\t\t\tpauseId,\n\t\t\t\t\t});\n\t\t\t\t\treleased = true;\n\t\t\t\t\tif (this.sessionInputPauses.get(acquisitionKey) === acquisition) {\n\t\t\t\t\t\tthis.sessionInputPauses.delete(acquisitionKey);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t};\n\t\t})();\n\t\tthis.sessionInputPauses.set(acquisitionKey, acquisition);\n\t\ttry {\n\t\t\treturn await acquisition;\n\t\t} catch (error) {\n\t\t\tif (this.sessionInputPauses.get(acquisitionKey) === acquisition)\n\t\t\t\tthis.sessionInputPauses.delete(acquisitionKey);\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync listCronJobs(options: { includeInactive?: boolean } = {}): Promise<AgentCronJob[]> {\n\t\tconst data = await this.requestData<{ jobs: AgentCronJob[] }>({\n\t\t\ttype: \"cron_list\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tincludeInactive: options.includeInactive,\n\t\t});\n\t\treturn data.jobs;\n\t}\n\n\tasync listHeartbeats(): Promise<AgentConnectionHeartbeat[]> {\n\t\treturn listDaemonHeartbeats(this.client, this.options.ownedSession ? this.activeSessionId : undefined);\n\t}\n\n\tasync manageHeartbeat(\n\t\tactiveSessionId: string,\n\t\tjobId: string,\n\t\taction: AgentHeartbeatManagementAction,\n\t): Promise<AgentCronJob> {\n\t\tif (!this.client.supportsServerCapability(\"heartbeat_management\")) {\n\t\t\tthrow new Error(\"Heartbeat management requires a newer ASM Agent daemon.\");\n\t\t}\n\t\ttry {\n\t\t\tconst data = await this.requestData<{ heartbeat: AgentCronJob }>({\n\t\t\t\ttype: \"heartbeat_manage\",\n\t\t\t\tactiveSessionId,\n\t\t\t\tjobId,\n\t\t\t\taction,\n\t\t\t});\n\t\t\treturn data.heartbeat;\n\t\t} catch (error) {\n\t\t\tif (isUnknownDaemonCommandError(error, \"heartbeat_manage\")) {\n\t\t\t\tthrow new Error(\"Heartbeat management requires a newer ASM Agent daemon.\");\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync addCronJob(schedule: string, prompt: string): Promise<AgentCronJob> {\n\t\treturn this.withOwnedSessionPromotion(async (promoteOwnedSession) => {\n\t\t\tconst data = await this.requestData<{ job: AgentCronJob }>({\n\t\t\t\ttype: \"cron_add\",\n\t\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\t\tschedule,\n\t\t\t\tprompt,\n\t\t\t\tpromoteOwnedSession,\n\t\t\t});\n\t\t\treturn data.job;\n\t\t});\n\t}\n\n\tasync cancelCronJob(jobId: string): Promise<AgentCronJob> {\n\t\tconst data = await this.requestData<{ job: AgentCronJob }>({\n\t\t\ttype: \"cron_cancel\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tjobId,\n\t\t});\n\t\treturn data.job;\n\t}\n\n\tasync getHeartbeat(): Promise<AgentCronJob | undefined> {\n\t\tconst data = await this.requestData<{ heartbeat?: AgentCronJob | null }>({\n\t\t\ttype: \"heartbeat_get\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t\treturn data.heartbeat ?? undefined;\n\t}\n\n\tasync setHeartbeat(\n\t\tschedule: string,\n\t\tinstruction: string,\n\t\tdeliveryMode?: AgentHeartbeatDeliveryMode,\n\t): Promise<AgentCronJob> {\n\t\treturn this.withOwnedSessionPromotion(async (promoteOwnedSession) => {\n\t\t\tconst data = await this.requestData<{ heartbeat: AgentCronJob }>({\n\t\t\t\ttype: \"heartbeat_set\",\n\t\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\t\tschedule,\n\t\t\t\tprompt: instruction,\n\t\t\t\t...(deliveryMode ? { deliveryMode } : {}),\n\t\t\t\tpromoteOwnedSession,\n\t\t\t});\n\t\t\treturn data.heartbeat;\n\t\t});\n\t}\n\n\tasync updateHeartbeat(action: AgentHeartbeatUpdateAction): Promise<AgentCronJob | undefined> {\n\t\tconst data = await this.requestData<{ heartbeat?: AgentCronJob | null }>({\n\t\t\ttype: \"heartbeat_update\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\taction,\n\t\t});\n\t\treturn data.heartbeat ?? undefined;\n\t}\n\n\tasync sendAgentMessage(targetActiveSessionId: string, message: string): Promise<AgentSessionMessageReceipt> {\n\t\treturn this.requestData<AgentSessionMessageReceipt>({\n\t\t\ttype: \"send_message\",\n\t\t\ttargetActiveSessionId,\n\t\t\tmessage,\n\t\t\tfromActiveSessionId: this.activeSessionId,\n\t\t});\n\t}\n\n\tasync getAgentMessageStatus(): Promise<AgentSessionMessageSafetyStatus> {\n\t\treturn this.requestData<AgentSessionMessageSafetyStatus>({\n\t\t\ttype: \"agent_messages_status\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t}\n\n\tasync pauseAgentMessages(): Promise<AgentSessionMessageSafetyStatus> {\n\t\treturn this.requestData<AgentSessionMessageSafetyStatus>({\n\t\t\ttype: \"agent_messages_pause\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t}\n\n\tasync resumeAgentMessages(): Promise<AgentSessionMessageSafetyStatus> {\n\t\treturn this.requestData<AgentSessionMessageSafetyStatus>({\n\t\t\ttype: \"agent_messages_resume\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t}\n\n\tasync clearAgentMessages(): Promise<number> {\n\t\treturn this.requestData<number>({\n\t\t\ttype: \"agent_messages_clear\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t}\n\n\tasync getUserMessagesForForking(): Promise<AgentConnectionUserMessage[]> {\n\t\tconst data = await this.requestData<{ messages: AgentConnectionUserMessage[] }>({\n\t\t\ttype: \"get_user_messages_for_forking\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t\treturn data.messages;\n\t}\n\n\tasync getLastAssistantText(): Promise<string | undefined> {\n\t\tconst data = await this.requestData<{ text?: string | null }>({\n\t\t\ttype: \"get_last_assistant_text\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t\treturn data.text ?? undefined;\n\t}\n\n\tasync getSystemPrompt(): Promise<string> {\n\t\tconst data = await this.requestData<{ systemPrompt: string }>({\n\t\t\ttype: \"get_system_prompt\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t\treturn data.systemPrompt;\n\t}\n\n\tasync getToolDefinition(name: string): Promise<AgentConnectionToolDefinition | undefined> {\n\t\tconst data = await this.requestData<{ toolDefinition?: AgentConnectionToolDefinition }>({\n\t\t\ttype: \"get_tool_definition\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tname,\n\t\t});\n\t\treturn data.toolDefinition;\n\t}\n\n\tasync setSessionEntryLabel(entryId: string, label: string | undefined): Promise<void> {\n\t\tawait this.requestOk({\n\t\t\ttype: \"set_session_entry_label\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tentryId,\n\t\t\tlabel,\n\t\t});\n\t}\n\n\tasync respondToExtensionUiRequest(requestId: string, response: AgentConnectionExtensionUiResponse): Promise<void> {\n\t\tawait this.requestOk({\n\t\t\ttype: \"extension_ui_response\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\trequestId,\n\t\t\tresponse,\n\t\t});\n\t}\n\n\tasync prompt(message: string, options?: AgentConnectionPromptOptions): Promise<void> {\n\t\tawait this.promptWithAdmissionCancellation(\"prompt\", message, options);\n\t}\n\n\tasync promptAndWait(message: string, options?: AgentConnectionPromptOptions): Promise<void> {\n\t\tawait this.promptWithAdmissionCancellation(\"prompt_and_wait\", message, options);\n\t}\n\n\tprivate async promptWithAdmissionCancellation(\n\t\ttype: \"prompt\" | \"prompt_and_wait\",\n\t\tmessage: string,\n\t\toptions?: AgentConnectionPromptOptions,\n\t): Promise<void> {\n\t\tconst signal = options?.signal;\n\t\tif (signal?.aborted) {\n\t\t\tthrow new AgentConnectionPromptAdmissionError(\"Prompt admission was cancelled.\", \"cancelled\");\n\t\t}\n\t\tif (!signal) {\n\t\t\tawait this.requestData<unknown>(\n\t\t\t\t{\n\t\t\t\t\ttype,\n\t\t\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\t\t\tmessage,\n\t\t\t\t\timages: options?.images,\n\t\t\t\t\tstreamingBehavior: options?.streamingBehavior,\n\t\t\t\t\tqueueIfBusy: options?.queueIfBusy,\n\t\t\t\t\tsource: options?.source,\n\t\t\t\t},\n\t\t\t\tDAEMON_LONG_RUNNING_REQUEST_TIMEOUT_MS,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tconst admissionId = `prompt-admission:${randomUUID()}`;\n\t\tlet resolveAbort = () => {};\n\t\tconst aborted = new Promise<\"abort\">((resolve) => {\n\t\t\tresolveAbort = () => resolve(\"abort\");\n\t\t});\n\t\tconst onAbort = () => resolveAbort();\n\t\tsignal.addEventListener(\"abort\", onAbort, { once: true });\n\t\t// Close the listener-registration race before issuing the first request.\n\t\tif (signal.aborted) {\n\t\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\t\tthrow new AgentConnectionPromptAdmissionError(\"Prompt admission was cancelled.\", \"cancelled\");\n\t\t}\n\t\tconst command = {\n\t\t\ttype,\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tmessage,\n\t\t\timages: options.images,\n\t\t\tstreamingBehavior: options.streamingBehavior,\n\t\t\tqueueIfBusy: options.queueIfBusy,\n\t\t\tsource: options.source,\n\t\t\tadmissionId,\n\t\t} as Extract<DaemonCommandBody, { type: typeof type }>;\n\t\tlet promptError: unknown;\n\t\tconst promptRequest = this.requestData<unknown>(command, DAEMON_LONG_RUNNING_REQUEST_TIMEOUT_MS).catch(\n\t\t\t(error: unknown) => {\n\t\t\t\tpromptError =\n\t\t\t\t\terror instanceof DaemonCapabilityUnavailableError && !error.afterReconnect\n\t\t\t\t\t\t? new AgentConnectionPromptAdmissionError(error.message, \"unsupported\", { cause: error })\n\t\t\t\t\t\t: error;\n\t\t\t\treturn \"failed\" as const;\n\t\t\t},\n\t\t);\n\t\ttry {\n\t\t\tconst first = await Promise.race([promptRequest.then(() => \"settled\" as const), aborted]);\n\t\t\tif (first === \"settled\" && promptError === undefined) return;\n\t\t\tif (first === \"settled\" && promptError instanceof AgentConnectionPromptAdmissionError) throw promptError;\n\t\t\tif (\n\t\t\t\tfirst === \"settled\" &&\n\t\t\t\t!signal.aborted &&\n\t\t\t\tpromptError instanceof Error &&\n\t\t\t\tthis.definitiveRequestErrors.has(promptError)\n\t\t\t) {\n\t\t\t\tthrow promptError;\n\t\t\t}\n\t\t\tlet status: \"cancelled\" | \"owned\" | \"unknown\" = \"unknown\";\n\t\t\ttry {\n\t\t\t\tconst result = await this.requestData<{ status: \"cancelled\" | \"owned\" | \"unknown\" }>({\n\t\t\t\t\ttype: \"cancel_prompt_admission\",\n\t\t\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\t\t\tadmissionId,\n\t\t\t\t\t...(this.client.supportsServerCapability(\"owned_prompt_cancellation\") ? { cancelOwned: true } : {}),\n\t\t\t\t});\n\t\t\t\tstatus = result.status;\n\t\t\t} catch {\n\t\t\t\t// Timeout/transport is indistinguishable from accepted ownership.\n\t\t\t}\n\t\t\tawait promptRequest;\n\t\t\tif (promptError instanceof AgentConnectionPromptAdmissionError) throw promptError;\n\t\t\tconst definitiveFailure = promptError instanceof Error && this.definitiveRequestErrors.has(promptError);\n\t\t\tif (promptError === undefined || (status === \"owned\" && type === \"prompt\" && !definitiveFailure)) return;\n\t\t\tthrow new AgentConnectionPromptAdmissionError(\n\t\t\t\tpromptError instanceof Error ? promptError.message : \"Prompt admission did not complete.\",\n\t\t\t\tstatus,\n\t\t\t\tpromptError === undefined ? undefined : { cause: promptError },\n\t\t\t);\n\t\t} finally {\n\t\t\tsignal.removeEventListener(\"abort\", onAbort);\n\t\t}\n\t}\n\n\tasync startSideQuestion(\n\t\tid: string,\n\t\tquestion: string,\n\t\tpreviousTurns?: AgentConnectionSideQuestionTurn[],\n\t): Promise<void> {\n\t\tif (previousTurns?.length && !this.client.supportsServerCapability(\"side_question_transcript\")) {\n\t\t\t// An older daemon would silently ignore previousTurns and answer the\n\t\t\t// follow-up without the side-conversation context; fail loudly instead.\n\t\t\tthrow new Error(\n\t\t\t\t\"the daemon is running an older build without side-conversation follow-ups; restart the daemon and try again\",\n\t\t\t);\n\t\t}\n\t\tthis.activeSideQuestionIds.add(id);\n\t\ttry {\n\t\t\tawait this.requestOk({\n\t\t\t\ttype: \"start_side_question\",\n\t\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\t\tsideQuestionId: id,\n\t\t\t\tquestion,\n\t\t\t\tpreviousTurns,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tthis.activeSideQuestionIds.delete(id);\n\t\t\tif (isUnknownDaemonCommandError(error, \"start_side_question\")) {\n\t\t\t\tthrow new Error(\"the daemon is running an older build; restart the daemon and try again\");\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync abortSideQuestion(id: string): Promise<boolean> {\n\t\tconst data = await this.requestData<{ aborted: boolean }>({\n\t\t\ttype: \"abort_side_question\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tsideQuestionId: id,\n\t\t});\n\t\tthis.activeSideQuestionIds.delete(id);\n\t\treturn data.aborted;\n\t}\n\n\tasync steer(message: string, images?: ImageContent[]): Promise<void> {\n\t\tawait this.requestOk({ type: \"steer\", activeSessionId: this.activeSessionId, message, images });\n\t}\n\n\tasync followUp(message: string, images?: ImageContent[]): Promise<void> {\n\t\tawait this.requestOk({ type: \"follow_up\", activeSessionId: this.activeSessionId, message, images });\n\t}\n\n\tasync abort(): Promise<void> {\n\t\tawait this.requestOk({ type: \"abort\", activeSessionId: this.activeSessionId });\n\t}\n\n\tasync cancelRlmChild(childId: string): Promise<boolean> {\n\t\ttry {\n\t\t\tconst result = await this.requestData<{ cancelled: boolean }>({\n\t\t\t\ttype: \"cancel_rlm_child\",\n\t\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\t\tchildId,\n\t\t\t});\n\t\t\treturn result.cancelled;\n\t\t} catch (error) {\n\t\t\tif (isUnknownDaemonCommandError(error, \"cancel_rlm_child\")) {\n\t\t\t\tthrow new Error(\"the daemon is running an older build; restart the daemon and try again\");\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync waitForIdle(): Promise<void> {\n\t\tawait this.requestData<unknown>(\n\t\t\t{ type: \"wait_for_idle\", activeSessionId: this.activeSessionId },\n\t\t\tDAEMON_LONG_RUNNING_REQUEST_TIMEOUT_MS,\n\t\t);\n\t}\n\n\tasync waitForHeadlessCompletion(options?: AgentConnectionHeadlessCompletionOptions): Promise<AgentAutonomousStatus> {\n\t\tif (options?.waitForRlmQuiescence && !this.client.supportsServerCapability(\"rlm_quiescence_barrier\")) {\n\t\t\tthrow new Error(\n\t\t\t\t\"the daemon is running an older build without RLM quiescence barriers; restart the daemon and try again\",\n\t\t\t);\n\t\t}\n\t\treturn this.requestData<AgentAutonomousStatus>(\n\t\t\t{\n\t\t\t\ttype: \"wait_for_headless_completion\",\n\t\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\t\t...(options?.waitForRlmQuiescence ? { waitForRlmQuiescence: true } : {}),\n\t\t\t},\n\t\t\tDAEMON_LONG_RUNNING_REQUEST_TIMEOUT_MS,\n\t\t);\n\t}\n\n\tasync executeBash(command: string, options?: AgentConnectionExecuteBashOptions): Promise<void> {\n\t\tif (options?.transient && !this.client.supportsServerCapability(\"transient_bash\")) {\n\t\t\t// An older daemon would record the run into the session, leaking the\n\t\t\t// side conversation into the main transcript; fail loudly instead.\n\t\t\tthrow new Error(\n\t\t\t\t\"the daemon is running an older build without side-conversation bash; restart the daemon and try again\",\n\t\t\t);\n\t\t}\n\t\ttry {\n\t\t\tawait this.requestOk({\n\t\t\t\ttype: \"execute_bash\",\n\t\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\t\tcommand,\n\t\t\t\texcludeFromContext: options?.excludeFromContext,\n\t\t\t\ttransient: options?.transient,\n\t\t\t\trunId: options?.runId,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (isUnknownDaemonCommandError(error, \"execute_bash\")) {\n\t\t\t\tthrow new Error(\"the daemon is running an older build; restart the daemon and try again\");\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync executeBashAndWait(command: string): Promise<BashResult> {\n\t\treturn this.requestData<BashResult>(\n\t\t\t{\n\t\t\t\ttype: \"execute_bash_and_wait\",\n\t\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\t\tcommand,\n\t\t\t},\n\t\t\tDAEMON_LONG_RUNNING_REQUEST_TIMEOUT_MS,\n\t\t);\n\t}\n\n\tasync abortBash(): Promise<void> {\n\t\ttry {\n\t\t\tawait this.requestOk({ type: \"abort_bash\", activeSessionId: this.activeSessionId });\n\t\t} catch (error) {\n\t\t\tif (isUnknownDaemonCommandError(error, \"abort_bash\")) {\n\t\t\t\tthrow new Error(\"the daemon is running an older build; restart the daemon and try again\");\n\t\t\t}\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tasync setModel(provider: string, modelId: string): Promise<AgentConnectionModel> {\n\t\treturn this.requestData<AgentConnectionModel>({\n\t\t\ttype: \"set_model\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tprovider,\n\t\t\tmodelId,\n\t\t});\n\t}\n\n\tasync cycleModel(direction?: \"forward\" | \"backward\"): Promise<AgentConnectionModelCycleResult | undefined> {\n\t\tconst result = await this.requestData<AgentConnectionModelCycleResult | null>({\n\t\t\ttype: \"cycle_model\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tdirection,\n\t\t});\n\t\treturn result ?? undefined;\n\t}\n\n\tasync setScopedModels(scopedModels: AgentConnectionScopedModel[]): Promise<void> {\n\t\tawait this.requestOk({\n\t\t\ttype: \"set_scoped_models\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tscopedModels,\n\t\t});\n\t}\n\n\tasync setThinkingLevel(level: ThinkingLevel): Promise<void> {\n\t\tawait this.requestOk({ type: \"set_thinking_level\", activeSessionId: this.activeSessionId, level });\n\t}\n\n\tasync setServiceTier(serviceTier: ServiceTier): Promise<void> {\n\t\tawait this.requestOk({ type: \"set_service_tier\", activeSessionId: this.activeSessionId, serviceTier });\n\t}\n\n\tasync cycleThinkingLevel(): Promise<ThinkingLevel | undefined> {\n\t\tconst result = await this.requestData<{ level: ThinkingLevel } | null>({\n\t\t\ttype: \"cycle_thinking_level\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t\treturn result?.level;\n\t}\n\n\tasync setTransport(transport: Transport): Promise<void> {\n\t\tawait this.requestOk({ type: \"set_transport\", activeSessionId: this.activeSessionId, transport });\n\t}\n\n\tasync setSteeringMode(mode: AgentConnectionQueueMode): Promise<void> {\n\t\tawait this.requestOk({ type: \"set_steering_mode\", activeSessionId: this.activeSessionId, mode });\n\t}\n\n\tasync setFollowUpMode(mode: AgentConnectionQueueMode): Promise<void> {\n\t\tawait this.requestOk({ type: \"set_follow_up_mode\", activeSessionId: this.activeSessionId, mode });\n\t}\n\n\tasync setAutoCompactionEnabled(enabled: boolean): Promise<void> {\n\t\tawait this.requestOk({ type: \"set_auto_compaction\", activeSessionId: this.activeSessionId, enabled });\n\t}\n\n\tasync setAutoRetryEnabled(enabled: boolean): Promise<void> {\n\t\tawait this.requestOk({ type: \"set_auto_retry\", activeSessionId: this.activeSessionId, enabled });\n\t}\n\n\tasync compact(customInstructions?: string): Promise<CompactionResult> {\n\t\treturn this.requestData<CompactionResult>({\n\t\t\ttype: \"compact\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tcustomInstructions,\n\t\t});\n\t}\n\n\tasync refine(\n\t\toptions: { instructions?: string; rollbackId?: string; global?: boolean } = {},\n\t): Promise<RefinementResult> {\n\t\tconst command: {\n\t\t\ttype: \"refine\";\n\t\t\tactiveSessionId: string;\n\t\t\tinstructions?: string;\n\t\t\trollbackId?: string;\n\t\t\tglobal?: boolean;\n\t\t} = {\n\t\t\ttype: \"refine\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tinstructions: options.instructions,\n\t\t\trollbackId: options.rollbackId,\n\t\t};\n\t\tif (options.global !== undefined) {\n\t\t\tcommand.global = options.global;\n\t\t}\n\t\treturn this.requestData<RefinementResult>(command, DAEMON_REFINE_REQUEST_TIMEOUT_MS);\n\t}\n\n\tasync abortCompaction(): Promise<void> {\n\t\tawait this.requestOk({ type: \"abort_compaction\", activeSessionId: this.activeSessionId });\n\t}\n\n\tasync abortBranchSummary(): Promise<void> {\n\t\tawait this.requestOk({ type: \"abort_branch_summary\", activeSessionId: this.activeSessionId });\n\t}\n\n\tasync abortRetry(): Promise<void> {\n\t\tawait this.requestOk({ type: \"abort_retry\", activeSessionId: this.activeSessionId });\n\t}\n\n\tasync reload(): Promise<void> {\n\t\tawait this.requestOk({ type: \"reload\", activeSessionId: this.activeSessionId });\n\t}\n\n\tasync newSession(options?: AgentConnectionNewSessionOptions): Promise<{ cancelled: boolean }> {\n\t\treturn this.requestData<{ cancelled: boolean }>({\n\t\t\ttype: \"new_session\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tparentSession: options?.parentSession,\n\t\t});\n\t}\n\n\tasync switchSession(\n\t\tsessionPath: string,\n\t\toptions?: AgentConnectionSwitchSessionOptions,\n\t): Promise<{ cancelled: boolean }> {\n\t\tconst sourceActiveSessionId = this.activeSessionId;\n\t\ttry {\n\t\t\treturn await this.requestData<{ cancelled: boolean }>({\n\t\t\t\ttype: \"switch_session\",\n\t\t\t\tactiveSessionId: sourceActiveSessionId,\n\t\t\t\tsessionPath,\n\t\t\t\tcwdOverride: options?.cwdOverride,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (!(error instanceof SessionAlreadyActiveError) || !error.activeSessionId) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tif (this.options.ownedSession) {\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t\tif (error.activeSessionId === sourceActiveSessionId) {\n\t\t\t\treturn { cancelled: false };\n\t\t\t}\n\t\t\treturn this.reattachSession(sourceActiveSessionId, error.activeSessionId);\n\t\t}\n\t}\n\n\tprivate async reattachSession(\n\t\tsourceActiveSessionId: string,\n\t\ttargetActiveSessionId: string,\n\t): Promise<{ cancelled: false }> {\n\t\tconst previousState = {\n\t\t\tlastEventCursor: this.lastEventCursor,\n\t\t\tlastEventSequence: this.lastEventSequence,\n\t\t\tlatestSnapshot: this.latestSnapshot,\n\t\t\tlatestSnapshotIsFresh: this.latestSnapshotIsFresh,\n\t\t\tretiredEventGenerations: new Set(this.retiredEventGenerations),\n\t\t};\n\t\tthis.activeSessionId = targetActiveSessionId;\n\t\tthis.lastEventCursor = undefined;\n\t\tthis.lastEventSequence = undefined;\n\t\tthis.latestSnapshot = undefined;\n\t\tthis.latestSnapshotIsFresh = false;\n\t\tthis.retiredEventGenerations.clear();\n\t\tthis.pendingReattachActiveSessionIds.add(targetActiveSessionId);\n\t\tlet reattached = false;\n\t\ttry {\n\t\t\tconst supportsExtensionUi = this.options.supportsExtensionUi !== false;\n\t\t\tconst result = await this.requestData<DaemonAttachResult>({\n\t\t\t\ttype: \"reattach\",\n\t\t\t\tactiveSessionId: sourceActiveSessionId,\n\t\t\t\ttargetActiveSessionId,\n\t\t\t\tsupportsExtensionUi,\n\t\t\t\tclientId: this.clientId,\n\t\t\t\tcapabilities: [\n\t\t\t\t\t\"attach_snapshot\",\n\t\t\t\t\t\"event_sequence\",\n\t\t\t\t\t...(supportsExtensionUi ? ([\"extension_ui\"] as const) : []),\n\t\t\t\t\t\"slim_attach\",\n\t\t\t\t\t\"chunked_snapshot\",\n\t\t\t\t\t...(this.options.ownedSession ? ([\"client_owned_sessions\"] as const) : []),\n\t\t\t\t],\n\t\t\t\tenv: this.options.sendClientEnv ? collectDaemonClientEnv() : undefined,\n\t\t\t\tlaunchEnv: this.options.ownedSession ? collectDaemonLaunchEnv() : undefined,\n\t\t\t});\n\t\t\treattached = true;\n\t\t\tthis.activeSessionId = result.activeSessionId;\n\t\t\tthis.activeSideQuestionIds.clear();\n\t\t\tif (result.snapshotStream) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.waitForSnapshot(result.snapshotStream.id);\n\t\t\t\t} catch (snapshotError) {\n\t\t\t\t\tawait this.snapshotRecoveryPromises.get(result.snapshotStream.id);\n\t\t\t\t\tif (!this.latestSnapshotIsFresh) {\n\t\t\t\t\t\tthrow snapshotError;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.applyReplacementSnapshot(result.snapshot, result.replay);\n\t\t\t\tawait this.emit({\n\t\t\t\t\ttype: \"session_replaced\",\n\t\t\t\t\tstate: result.snapshot.state,\n\t\t\t\t\tmessages: result.snapshot.messages,\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn { cancelled: false };\n\t\t} catch (error) {\n\t\t\tif (!reattached) {\n\t\t\t\tthis.activeSessionId = sourceActiveSessionId;\n\t\t\t\tthis.lastEventCursor = previousState.lastEventCursor;\n\t\t\t\tthis.lastEventSequence = previousState.lastEventSequence;\n\t\t\t\tthis.latestSnapshot = previousState.latestSnapshot;\n\t\t\t\tthis.latestSnapshotIsFresh = previousState.latestSnapshotIsFresh;\n\t\t\t\tthis.retiredEventGenerations.clear();\n\t\t\t\tfor (const generation of previousState.retiredEventGenerations) {\n\t\t\t\t\tthis.retiredEventGenerations.add(generation);\n\t\t\t\t}\n\t\t\t}\n\t\t\tthrow error;\n\t\t} finally {\n\t\t\tthis.pendingReattachActiveSessionIds.delete(targetActiveSessionId);\n\t\t}\n\t}\n\n\tasync fork(\n\t\tentryId: string,\n\t\toptions?: AgentConnectionForkOptions,\n\t): Promise<{ cancelled: boolean; selectedText?: string }> {\n\t\treturn this.requestData<{ cancelled: boolean; selectedText?: string }>({\n\t\t\ttype: \"fork\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tentryId,\n\t\t\tposition: options?.position,\n\t\t});\n\t}\n\n\tasync navigateTree(\n\t\ttargetId: string,\n\t\toptions?: AgentConnectionNavigateTreeOptions,\n\t): Promise<AgentConnectionNavigateTreeResult> {\n\t\treturn this.requestData<AgentConnectionNavigateTreeResult>({\n\t\t\ttype: \"navigate_tree\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\ttargetId,\n\t\t\tsummarize: options?.summarize,\n\t\t\tcustomInstructions: options?.customInstructions,\n\t\t\treplaceInstructions: options?.replaceInstructions,\n\t\t\tlabel: options?.label,\n\t\t});\n\t}\n\n\tasync importFromJsonl(inputPath: string, cwdOverride?: string): Promise<{ cancelled: boolean }> {\n\t\treturn this.requestData<{ cancelled: boolean }>({\n\t\t\ttype: \"import_jsonl\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tinputPath,\n\t\t\tcwdOverride,\n\t\t});\n\t}\n\n\tasync exportToHtml(outputPath?: string): Promise<string> {\n\t\tconst data = await this.requestData<{ path: string }>({\n\t\t\ttype: \"export_html\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\toutputPath,\n\t\t});\n\t\treturn data.path;\n\t}\n\n\tasync exportToJsonl(outputPath?: string): Promise<string> {\n\t\tconst data = await this.requestData<{ path: string }>({\n\t\t\ttype: \"export_jsonl\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\toutputPath,\n\t\t});\n\t\treturn data.path;\n\t}\n\n\tasync setSessionName(name: string): Promise<void> {\n\t\tawait this.requestOk({ type: \"set_session_name\", activeSessionId: this.activeSessionId, name });\n\t}\n\n\tasync getRlmMaxDepthStatus() {\n\t\treturn this.requestData<{ maxDepth: number; source: \"default\" | \"env\" | \"global\" | \"inherited\" | \"chat\" }>({\n\t\t\ttype: \"get_rlm_max_depth_status\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t});\n\t}\n\n\tasync setRlmMaxDepth(maxDepth: number, options?: { global?: boolean }) {\n\t\treturn this.requestData<{\n\t\t\tmaxDepth: number;\n\t\t\tsource: \"default\" | \"env\" | \"global\" | \"inherited\" | \"chat\";\n\t\t\tglobalSaved: boolean;\n\t\t\tglobalError?: string;\n\t\t}>({\n\t\t\ttype: \"set_rlm_max_depth\",\n\t\t\tactiveSessionId: this.activeSessionId,\n\t\t\tmaxDepth,\n\t\t\tglobal: options?.global,\n\t\t});\n\t}\n\n\tasync renameSavedSession(sessionPath: string, name: string): Promise<void> {\n\t\tawait renameDaemonSavedSession(this.client, { activeSessionId: this.activeSessionId }, sessionPath, name);\n\t}\n\n\tasync deleteSavedSession(sessionPath: string): Promise<DeleteSessionFileResult> {\n\t\treturn deleteDaemonSavedSession(this.client, { activeSessionId: this.activeSessionId }, sessionPath);\n\t}\n\n\tasync watchSession(activeSessionId: string): Promise<AgentConnectionSessionWatcher | undefined> {\n\t\t// A second connection on the shared client; each one filters to its own session id.\n\t\t// attach() rejects for an unknown/exited session — treat that as unreachable.\n\t\tlet connection: DaemonAgentConnection;\n\t\ttry {\n\t\t\tconnection = await DaemonAgentConnection.attach(this.client, activeSessionId, { closeClientOnDispose: false });\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t\treturn {\n\t\t\tgetMessages: () => connection.getMessages(),\n\t\t\tgetCommands: () => connection.getCommands(),\n\t\t\tsubscribe: (listener) => connection.subscribe(listener),\n\t\t\tgetToolDefinition: (name) => connection.getToolDefinition(name),\n\t\t\tclose: () => connection.dispose(),\n\t\t};\n\t}\n\n\tasync dispose(): Promise<void> {\n\t\tif (this.disposed || this.disposing) {\n\t\t\treturn;\n\t\t}\n\t\tthis.disposing = true;\n\t\tif (this.options.ownedSession && !this.client.isConnected && this.reconnectPromise) {\n\t\t\tawait Promise.race([this.reconnectPromise, delay(OWNED_SESSION_DISPOSE_RECONNECT_WAIT_MS)]).catch(\n\t\t\t\t() => undefined,\n\t\t\t);\n\t\t}\n\t\tthis.disposed = true;\n\t\tthis.updateRestartPending = false;\n\t\tawait Promise.allSettled([...this.activeSideQuestionIds].map((id) => this.abortSideQuestion(id)));\n\t\tthis.unsubscribeDaemonMessages();\n\t\tthis.unsubscribeDaemonClose();\n\t\tif (this.options.ownedSession) {\n\t\t\tawait this.requestOk({ type: \"complete_owned_session\", activeSessionId: this.activeSessionId }).catch(\n\t\t\t\t() => undefined,\n\t\t\t);\n\t\t} else {\n\t\t\tawait this.requestOk({ type: \"detach\", activeSessionId: this.activeSessionId }).catch(() => undefined);\n\t\t}\n\t\tif (this.options.closeClientOnDispose) {\n\t\t\tthis.client.close();\n\t\t}\n\t\tthis.rejectSnapshotAssemblies(new Error(\"Daemon connection disposed during snapshot transfer\"));\n\t}\n\n\tasync promoteToResident(): Promise<void> {\n\t\tawait this.withOwnedSessionPromotion(async (promoteOwnedSession) => {\n\t\t\tif (!promoteOwnedSession) return;\n\t\t\tawait this.requestOk({ type: \"promote_owned_session\", activeSessionId: this.activeSessionId });\n\t\t});\n\t}\n\n\tprivate withOwnedSessionPromotion<T>(operation: (promoteOwnedSession: boolean) => Promise<T>): Promise<T> {\n\t\tconst run = this.ownedSessionPromotionTail.then(async () => {\n\t\t\tconst promoteOwnedSession = this.options.ownedSession === true;\n\t\t\tconst result = await operation(promoteOwnedSession);\n\t\t\tif (promoteOwnedSession) {\n\t\t\t\tthis.options.ownedSession = false;\n\t\t\t}\n\t\t\treturn result;\n\t\t});\n\t\tthis.ownedSessionPromotionTail = run.then(\n\t\t\t() => undefined,\n\t\t\t() => undefined,\n\t\t);\n\t\treturn run;\n\t}\n\n\tprivate async reconnect(cause: Error): Promise<void> {\n\t\tif (this.reconnectPromise) {\n\t\t\treturn this.reconnectPromise;\n\t\t}\n\t\tthis.reconnectPromise = (async () => {\n\t\t\tvoid this.emit({ type: \"connection_status\", status: \"reconnecting\", error: cause.message });\n\t\t\tconst deadline = Date.now() + (this.options.reconnectTimeoutMs ?? DAEMON_RECONNECT_TIMEOUT_MS);\n\t\t\tlet attempt = 0;\n\t\t\tlet lastError: Error = cause;\n\t\t\twhile (!this.disposed && Date.now() < deadline) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.options.recoverDaemon?.();\n\t\t\t\t\tif (this.disposed) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tawait this.client.connect(1000);\n\t\t\t\t\tawait this.client.waitForHello(3000);\n\t\t\t\t\tawait this.attach();\n\t\t\t\t\tif (!this.disposed) {\n\t\t\t\t\t\tconst snapshot = await this.getInitialSnapshot();\n\t\t\t\t\t\tvoid this.emit({ type: \"session_resynced\", snapshot });\n\t\t\t\t\t\tvoid this.emit({ type: \"connection_status\", status: \"connected\" });\n\t\t\t\t\t}\n\t\t\t\t\treturn;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tlastError = error instanceof Error ? error : new Error(String(error));\n\t\t\t\t\tif (this.disposed) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthis.client.resetTransportForReconnect();\n\t\t\t\t\tconst remainingMs = deadline - Date.now();\n\t\t\t\t\tif (remainingMs <= 0) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tconst delayMs = Math.min(remainingMs, 2000, 100 * 2 ** Math.min(attempt, 5));\n\t\t\t\t\tattempt++;\n\t\t\t\t\tawait new Promise((resolveDelay) => setTimeout(resolveDelay, delayMs));\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!this.disposed) {\n\t\t\t\tthis.client.close();\n\t\t\t\tawait this.emit({ type: \"closed\", error: `Daemon reconnection failed: ${lastError.message}` });\n\t\t\t}\n\t\t})().finally(() => {\n\t\t\tthis.reconnectPromise = undefined;\n\t\t});\n\t\treturn this.reconnectPromise;\n\t}\n\n\tprivate async requestOk(command: DaemonCommandBody): Promise<void> {\n\t\tawait this.requestData<unknown>(command);\n\t}\n\n\tprivate async requestData<T>(\n\t\tcommand: DaemonCommandBody,\n\t\ttimeoutMs?: number,\n\t\toptions?: Parameters<DaemonClient[\"request\"]>[2],\n\t): Promise<T> {\n\t\tconst response = await this.client.request(command, timeoutMs, options);\n\t\tif (!response.success) {\n\t\t\tconst error = deserializeDaemonError(response);\n\t\t\tthis.definitiveRequestErrors.add(error);\n\t\t\tthrow error;\n\t\t}\n\t\tif (invalidatesCachedSnapshot(command.type)) {\n\t\t\tthis.latestSnapshotIsFresh = false;\n\t\t}\n\t\treturn response.data as T;\n\t}\n\n\tprivate async handleDaemonMessage(message: DaemonOutbound): Promise<void> {\n\t\tif (message.type === \"heartbeats_changed\") {\n\t\t\tawait this.emit({ type: \"heartbeats_changed\" });\n\t\t\treturn;\n\t\t}\n\t\tif (!this.isMessageForActiveSession(message)) {\n\t\t\treturn;\n\t\t}\n\t\tif (\"snapshotId\" in message && this.ignoredSnapshotIds.has(message.snapshotId)) {\n\t\t\tif (message.type === \"session_snapshot_end\" || message.type === \"session_snapshot_failed\") {\n\t\t\t\tthis.ignoredSnapshotIds.delete(message.snapshotId);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (message.type === \"session_snapshot_begin\") {\n\t\t\tconst assembly = this.getSnapshotAssembly(message.snapshotId);\n\t\t\tassembly.begin = message;\n\t\t\treturn;\n\t\t}\n\t\tif (message.type === \"session_snapshot_chunk\") {\n\t\t\tthis.getSnapshotAssembly(message.snapshotId).chunks.set(message.index, message.messages);\n\t\t\treturn;\n\t\t}\n\t\tif (message.type === \"session_snapshot_end\") {\n\t\t\tawait this.completeSnapshotAssembly(message);\n\t\t\treturn;\n\t\t}\n\t\tif (message.type === \"session_snapshot_failed\") {\n\t\t\tconst assembly = this.getSnapshotAssembly(message.snapshotId);\n\t\t\tconst purpose = assembly.begin?.purpose ?? \"attach\";\n\t\t\tconst snapshotError = new Error(message.error);\n\t\t\tconst recoveryPromise =\n\t\t\t\tpurpose === \"replacement\" || purpose === \"resync\"\n\t\t\t\t\t? this.recoverFailedSnapshot(purpose, snapshotError)\n\t\t\t\t\t: undefined;\n\t\t\tif (recoveryPromise) {\n\t\t\t\tthis.snapshotRecoveryPromises.set(message.snapshotId, recoveryPromise);\n\t\t\t}\n\t\t\tthis.rejectSnapshotAssembly(message.snapshotId, assembly, snapshotError);\n\t\t\tthis.ignoreSnapshotId(message.snapshotId);\n\t\t\tif (recoveryPromise) {\n\t\t\t\ttry {\n\t\t\t\t\tawait recoveryPromise;\n\t\t\t\t} finally {\n\t\t\t\t\tthis.snapshotRecoveryPromises.delete(message.snapshotId);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (this.isStaleSequencedMessage(message)) {\n\t\t\treturn;\n\t\t}\n\t\tthis.observeDaemonEventSequence(message);\n\n\t\tif (message.type === \"session_event\") {\n\t\t\tif (message.event.type !== \"refine_complete\" && message.event.type !== \"refine_failed\") {\n\t\t\t\tthis.observeStreamingMessage(message.event);\n\t\t\t}\n\t\t\tif (message.event.type === \"rlm_child_update\") {\n\t\t\t\tthis.childRosterSequence = maxEventSequence(this.childRosterSequence, getDaemonMessageSequence(message));\n\t\t\t\tthis.observeRlmChildUpdate(message.event.child);\n\t\t\t}\n\t\t\tthis.latestSnapshotIsFresh = false;\n\t\t\tawait this.emit({ type: \"session_event\", event: message.event });\n\t\t\treturn;\n\t\t}\n\t\tif (message.type === \"side_question_event\") {\n\t\t\tthis.observeSideQuestionEvent(message.event);\n\t\t\tawait this.emit({ type: \"side_question_event\", event: message.event });\n\t\t\treturn;\n\t\t}\n\t\tif (message.type === \"session_status\") {\n\t\t\t// Keep a cached snapshot's recap current so a later re-attach seeds it.\n\t\t\tif (this.latestSnapshot) {\n\t\t\t\tthis.latestSnapshot = {\n\t\t\t\t\t...this.latestSnapshot,\n\t\t\t\t\tstate: { ...this.latestSnapshot.state, recap: message.recap },\n\t\t\t\t};\n\t\t\t}\n\t\t\tawait this.emit({ type: \"session_status\", recap: message.recap });\n\t\t\treturn;\n\t\t}\n\t\tif (message.type === \"session_resynced\") {\n\t\t\tthis.attachedSessionId = message.snapshot.state.sessionId;\n\t\t\tthis.attachedSessionFile = message.snapshot.state.sessionFile;\n\t\t\tthis.latestSnapshot = mapDaemonSessionSnapshot(message.snapshot);\n\t\t\tif (Array.isArray(message.snapshot.children)) {\n\t\t\t\tthis.childRosterSequence = message.snapshot.lastEventSequence;\n\t\t\t}\n\t\t\tif (this.lastEventSequence !== undefined) {\n\t\t\t\tthis.latestSnapshot.lastEventSequence = this.lastEventSequence;\n\t\t\t}\n\t\t\tif (this.lastEventCursor) {\n\t\t\t\tthis.latestSnapshot.lastEventCursor = this.lastEventCursor;\n\t\t\t}\n\t\t\tthis.latestSnapshotIsFresh = true;\n\t\t\tawait this.emit({ type: \"session_resynced\", snapshot: this.latestSnapshot });\n\t\t\treturn;\n\t\t}\n\t\tif (message.type === \"session_replaced\") {\n\t\t\tthis.attachedSessionId = message.state.sessionId;\n\t\t\tthis.attachedSessionFile = message.state.sessionFile;\n\t\t\tif (message.snapshotFollows) {\n\t\t\t\tthis.latestSnapshotIsFresh = false;\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tconst latestSnapshot: AgentConnectionSnapshot = {\n\t\t\t\tstate: message.state,\n\t\t\t\tmessages: message.messages,\n\t\t\t};\n\t\t\tif (this.lastEventSequence !== undefined) {\n\t\t\t\tlatestSnapshot.lastEventSequence = this.lastEventSequence;\n\t\t\t}\n\t\t\tif (this.lastEventCursor) {\n\t\t\t\tlatestSnapshot.lastEventCursor = this.lastEventCursor;\n\t\t\t}\n\t\t\tthis.latestSnapshot = latestSnapshot;\n\t\t\tthis.childRosterSequence = undefined;\n\t\t\tthis.latestSnapshotIsFresh = true;\n\t\t\tawait this.emit({ type: \"session_replaced\", state: message.state, messages: message.messages });\n\t\t\treturn;\n\t\t}\n\t\tif (message.type === \"extension_ui_request\") {\n\t\t\tawait this.emit({\n\t\t\t\ttype: \"extension_ui_request\",\n\t\t\t\trequest: {\n\t\t\t\t\tid: message.id,\n\t\t\t\t\tmethod: message.method,\n\t\t\t\t\tpayload: message.payload,\n\t\t\t\t},\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tif (message.type === \"extension_error\") {\n\t\t\tawait this.emit({\n\t\t\t\ttype: \"extension_error\",\n\t\t\t\textensionPath: message.extensionPath,\n\t\t\t\tevent: message.event,\n\t\t\t\terror: message.error,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\t\tif (message.type === \"session_closed\") {\n\t\t\tif (message.reason === \"update\") {\n\t\t\t\tthis.captureDaemonLogPath();\n\t\t\t\tthis.updateRestartPending = true;\n\t\t\t\tvoid this.reconnectAfterUpdate();\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.terminalCloseEmitted = true;\n\t\t\tawait this.emit({ type: \"closed\", error: this.formatDaemonSessionClosedError(message.reason) });\n\t\t}\n\t}\n\n\tprivate captureDaemonLogPath(): void {\n\t\tconst socketPath = this.client.hello?.socketPath;\n\t\tif (socketPath) {\n\t\t\tthis.daemonLogPath = getDaemonLogPath(socketPath);\n\t\t}\n\t}\n\n\tprivate formatDaemonSessionClosedError(reason: DaemonSessionClosedReason): string {\n\t\tconst explanation: Record<DaemonSessionClosedReason, string> = {\n\t\t\tkilled:\n\t\t\t\t\"The daemon stopped this agent session. Its transcript remains saved and can be reopened from Agents View.\",\n\t\t\tshutdown:\n\t\t\t\t\"The ASM Agent daemon shut down while this window was attached. The session transcript remains saved; restart ASM Agent and reopen it from Agents View.\",\n\t\t\tcompleted:\n\t\t\t\t\"The daemon closed this agent session after it completed. Its transcript remains available from Agents View.\",\n\t\t\treplaced:\n\t\t\t\t\"The daemon replaced this agent session with another session. Reopen the current session from Agents View.\",\n\t\t\tupdate:\n\t\t\t\t\"The ASM Agent daemon restarted for an update, but this window did not restore automatically. The session transcript remains saved; restart ASM Agent and reopen it from Agents View.\",\n\t\t};\n\t\treturn `${explanation[reason]} ${this.formatDaemonDiagnosticContext()}`;\n\t}\n\n\tprivate formatDaemonConnectionClosedError(error: Error): string {\n\t\treturn `Lost connection to the ASM Agent daemon. Cause: ${formatErrorSentence(error)} The session transcript remains saved; restart ASM Agent or reopen the session from Agents View. ${this.formatDaemonDiagnosticContext()}`;\n\t}\n\n\tprivate formatUpdateReconnectError(error: unknown): string {\n\t\treturn `The ASM Agent daemon restarted for an update, but this window could not reconnect to its restored session before the recovery timeout expired. Last error: ${formatErrorSentence(error)} The session transcript remains saved; restart ASM Agent and reopen it from Agents View. ${this.formatDaemonDiagnosticContext()}`;\n\t}\n\n\tprivate formatDaemonDiagnosticContext(): string {\n\t\tconst details: string[] = [];\n\t\tif (this.attachedSessionId) {\n\t\t\tdetails.push(`Session ID: ${this.attachedSessionId}.`);\n\t\t}\n\t\tif (this.attachedSessionFile) {\n\t\t\tdetails.push(`Session file: ${this.attachedSessionFile}.`);\n\t\t}\n\t\tdetails.push(`Diagnostic log: ${this.daemonLogPath ?? getAgentLogPath()}.`);\n\t\treturn details.join(\" \");\n\t}\n\n\tprivate reconnectAfterUpdate(): Promise<void> {\n\t\tif (this.updateReconnectPromise) {\n\t\t\treturn this.updateReconnectPromise;\n\t\t}\n\t\tvoid this.emit({\n\t\t\ttype: \"connection_status\",\n\t\t\tstatus: \"reconnecting\",\n\t\t\terror: \"The ASM Agent daemon is restarting for an update.\",\n\t\t});\n\t\tconst reconnectPromise = reconnectDaemonTransportAfterUpdate(this.client)\n\t\t\t.then(() => this.restoreConnectionAfterUpdate())\n\t\t\t.then(() => {\n\t\t\t\tif (!this.disposed) {\n\t\t\t\t\tvoid this.emit({ type: \"connection_status\", status: \"connected\" });\n\t\t\t\t}\n\t\t\t})\n\t\t\t.catch(async (error: unknown) => {\n\t\t\t\tthis.updateRestartPending = false;\n\t\t\t\tthis.updateReconnectFailed = true;\n\t\t\t\tif (!this.disposed) {\n\t\t\t\t\tthis.terminalCloseEmitted = true;\n\t\t\t\t\tawait this.emit({\n\t\t\t\t\t\ttype: \"closed\",\n\t\t\t\t\t\terror: this.formatUpdateReconnectError(error),\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t})\n\t\t\t.finally(() => {\n\t\t\t\tif (this.updateReconnectPromise === reconnectPromise) {\n\t\t\t\t\tthis.updateReconnectPromise = undefined;\n\t\t\t\t}\n\t\t\t});\n\t\tthis.updateReconnectPromise = reconnectPromise;\n\t\treturn reconnectPromise;\n\t}\n\n\tprivate async restoreConnectionAfterUpdate(): Promise<void> {\n\t\tconst sessionId = this.attachedSessionId;\n\t\tconst sessionFile = this.attachedSessionFile;\n\t\tif (!sessionId && !sessionFile) {\n\t\t\tthrow new Error(\"the previous session identity is unavailable\");\n\t\t}\n\t\tconst deadline = Date.now() + UPDATE_RECONNECT_TIMEOUT_MS;\n\t\tlet lastError: unknown;\n\t\twhile (!this.disposed && Date.now() < deadline) {\n\t\t\ttry {\n\t\t\t\tawait this.client.reconnect(1000);\n\t\t\t\tif (this.disposed) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tconst response = await this.client.request({ type: \"list\" }, 30000);\n\t\t\t\tif (this.disposed) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tif (!response.success) {\n\t\t\t\t\tthrow deserializeDaemonError(response);\n\t\t\t\t}\n\t\t\t\tconst sessions = readSessionSummaries(response.data);\n\t\t\t\tconst restored = sessions.find(\n\t\t\t\t\t(summary) =>\n\t\t\t\t\t\tsummary.activeSessionId !== undefined &&\n\t\t\t\t\t\t((sessionFile !== undefined && summary.sessionFile === sessionFile) ||\n\t\t\t\t\t\t\t(sessionId !== undefined && summary.sessionId === sessionId)),\n\t\t\t\t);\n\t\t\t\tif (restored?.activeSessionId) {\n\t\t\t\t\tif (this.disposed) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthis.activeSessionId = restored.activeSessionId;\n\t\t\t\t\tthis.lastEventSequence = undefined;\n\t\t\t\t\tthis.lastEventCursor = undefined;\n\t\t\t\t\tthis.retiredEventGenerations.clear();\n\t\t\t\t\tawait this.attach();\n\t\t\t\t\tif (this.disposed) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tconst snapshot = await this.getInitialSnapshot();\n\t\t\t\t\tif (this.disposed) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tthis.updateRestartPending = false;\n\t\t\t\t\tvoid this.emit({ type: \"session_resynced\", snapshot });\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tlastError = error;\n\t\t\t}\n\t\t\tawait delay(UPDATE_RECONNECT_RETRY_MS);\n\t\t}\n\t\tif (this.disposed) {\n\t\t\treturn;\n\t\t}\n\t\tthrow lastError ?? new Error(\"the restored session did not become available\");\n\t}\n\n\tprivate getSnapshotAssembly(snapshotId: string): DaemonSnapshotAssembly {\n\t\tconst existing = this.snapshotAssemblies.get(snapshotId);\n\t\tif (existing) {\n\t\t\treturn existing;\n\t\t}\n\t\tlet resolveSnapshot!: (snapshot: DaemonSessionSnapshot) => void;\n\t\tlet rejectSnapshot!: (error: Error) => void;\n\t\tconst promise = new Promise<DaemonSessionSnapshot>((resolve, reject) => {\n\t\t\tresolveSnapshot = resolve;\n\t\t\trejectSnapshot = reject;\n\t\t});\n\t\tvoid promise.catch(() => undefined);\n\t\tconst timeout = setTimeout(() => {\n\t\t\tconst current = this.snapshotAssemblies.get(snapshotId);\n\t\t\tif (current) {\n\t\t\t\tcurrent.reject(new Error(`Timed out waiting for snapshot ${snapshotId}`));\n\t\t\t\tthis.snapshotAssemblies.delete(snapshotId);\n\t\t\t\tthis.ignoreSnapshotId(snapshotId);\n\t\t\t}\n\t\t}, this.options.snapshotTimeoutMs ?? DAEMON_SNAPSHOT_TIMEOUT_MS);\n\t\ttimeout.unref();\n\t\tconst assembly: DaemonSnapshotAssembly = {\n\t\t\tchunks: new Map(),\n\t\t\tpromise,\n\t\t\tresolve: resolveSnapshot,\n\t\t\treject: rejectSnapshot,\n\t\t\ttimeout,\n\t\t};\n\t\tthis.snapshotAssemblies.set(snapshotId, assembly);\n\t\treturn assembly;\n\t}\n\n\tprivate rejectSnapshotAssemblies(error: Error): void {\n\t\tfor (const assembly of this.snapshotAssemblies.values()) {\n\t\t\tclearTimeout(assembly.timeout);\n\t\t\tassembly.reject(error);\n\t\t}\n\t\tthis.snapshotAssemblies.clear();\n\t\tthis.completedSnapshots.clear();\n\t\tthis.snapshotRecoveryPromises.clear();\n\t\tthis.ignoredSnapshotIds.clear();\n\t}\n\n\tprivate ignoreSnapshotId(snapshotId: string): void {\n\t\tthis.ignoredSnapshotIds.add(snapshotId);\n\t\twhile (this.ignoredSnapshotIds.size > MAX_IGNORED_SNAPSHOT_IDS) {\n\t\t\tconst oldest = this.ignoredSnapshotIds.values().next().value;\n\t\t\tif (oldest === undefined) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tthis.ignoredSnapshotIds.delete(oldest);\n\t\t}\n\t}\n\n\tprivate rejectSnapshotAssembly(snapshotId: string, assembly: DaemonSnapshotAssembly, error: Error): void {\n\t\tassembly.reject(error);\n\t\tclearTimeout(assembly.timeout);\n\t\tif (assembly.begin?.purpose && assembly.begin.purpose !== \"attach\") {\n\t\t\tthis.snapshotAssemblies.delete(snapshotId);\n\t\t}\n\t}\n\n\tprivate async recoverFailedSnapshot(purpose: \"replacement\" | \"resync\", snapshotError: Error): Promise<void> {\n\t\tthis.latestSnapshotIsFresh = false;\n\t\tif (purpose === \"replacement\") {\n\t\t\tthis.latestSnapshot = undefined;\n\t\t}\n\t\ttry {\n\t\t\tconst snapshot = await this.getInitialSnapshot();\n\t\t\tif (this.disposed) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.attachedSessionId = snapshot.state.sessionId;\n\t\t\tthis.attachedSessionFile = snapshot.state.sessionFile;\n\t\t\tif (purpose === \"replacement\") {\n\t\t\t\tawait this.emit({ type: \"session_replaced\", state: snapshot.state, messages: snapshot.messages });\n\t\t\t} else {\n\t\t\t\tawait this.emit({ type: \"session_resynced\", snapshot });\n\t\t\t}\n\t\t} catch (recoveryError) {\n\t\t\tif (this.disposed) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.terminalCloseEmitted = true;\n\t\t\tawait this.emit({\n\t\t\t\ttype: \"closed\",\n\t\t\t\terror: `Failed to recover from a ${purpose} snapshot transfer. Snapshot error: ${formatErrorSentence(snapshotError)} Recovery error: ${formatErrorSentence(recoveryError)} ${this.formatDaemonDiagnosticContext()}`,\n\t\t\t});\n\t\t}\n\t}\n\n\tprivate async waitForSnapshot(snapshotId: string): Promise<DaemonSessionSnapshot> {\n\t\tconst completed = this.completedSnapshots.get(snapshotId);\n\t\tif (completed) {\n\t\t\tthis.completedSnapshots.delete(snapshotId);\n\t\t\treturn completed;\n\t\t}\n\t\tconst assembly = this.getSnapshotAssembly(snapshotId);\n\t\ttry {\n\t\t\treturn await assembly.promise;\n\t\t} finally {\n\t\t\tclearTimeout(assembly.timeout);\n\t\t\tthis.snapshotAssemblies.delete(snapshotId);\n\t\t\tthis.completedSnapshots.delete(snapshotId);\n\t\t}\n\t}\n\n\tprivate applyReplacementSnapshot(snapshot: DaemonSessionSnapshot, replay?: DaemonReplayInfo): void {\n\t\tif (snapshot.lastEventCursor) {\n\t\t\tthis.observeEventCursor(snapshot.lastEventCursor);\n\t\t}\n\t\tthis.lastEventSequence = maxEventSequence(this.lastEventSequence, snapshot.lastEventSequence);\n\t\tthis.attachedSessionId = snapshot.state.sessionId;\n\t\tthis.attachedSessionFile = snapshot.state.sessionFile;\n\t\tthis.latestSnapshot = mapDaemonSessionSnapshot(snapshot, replay);\n\t\tthis.childRosterSequence = Array.isArray(snapshot.children) ? snapshot.lastEventSequence : undefined;\n\t\tthis.latestSnapshotIsFresh = true;\n\t}\n\n\tprivate async completeSnapshotAssembly(\n\t\tmessage: Extract<DaemonOutbound, { type: \"session_snapshot_end\" }>,\n\t): Promise<void> {\n\t\tconst assembly = this.getSnapshotAssembly(message.snapshotId);\n\t\tif (!assembly.begin) {\n\t\t\tthis.rejectSnapshotAssembly(\n\t\t\t\tmessage.snapshotId,\n\t\t\t\tassembly,\n\t\t\t\tnew Error(`Snapshot ${message.snapshotId} ended before it began`),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tif (assembly.chunks.size !== message.chunkCount) {\n\t\t\tthis.rejectSnapshotAssembly(\n\t\t\t\tmessage.snapshotId,\n\t\t\t\tassembly,\n\t\t\t\tnew Error(\n\t\t\t\t\t`Snapshot ${message.snapshotId} ended with ${assembly.chunks.size} of ${message.chunkCount} chunks`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tconst messages: AgentMessage[] = [];\n\t\tfor (let index = 0; index < message.chunkCount; index++) {\n\t\t\tconst chunk = assembly.chunks.get(index);\n\t\t\tif (!chunk) {\n\t\t\t\tthis.rejectSnapshotAssembly(\n\t\t\t\t\tmessage.snapshotId,\n\t\t\t\t\tassembly,\n\t\t\t\t\tnew Error(`Snapshot ${message.snapshotId} is missing chunk ${index}`),\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tmessages.push(...chunk);\n\t\t}\n\t\tif (messages.length !== assembly.begin.messageCount) {\n\t\t\tthis.rejectSnapshotAssembly(\n\t\t\t\tmessage.snapshotId,\n\t\t\t\tassembly,\n\t\t\t\tnew Error(\n\t\t\t\t\t`Snapshot ${message.snapshotId} contained ${messages.length} of ${assembly.begin.messageCount} messages`,\n\t\t\t\t),\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tconst snapshot: DaemonSessionSnapshot = {\n\t\t\t...assembly.begin.snapshot,\n\t\t\tmessages,\n\t\t\tlastEventSequence: message.lastEventSequence,\n\t\t\tlastEventCursor: message.lastEventCursor,\n\t\t};\n\t\tif (message.lastEventCursor) {\n\t\t\tthis.observeEventCursor(message.lastEventCursor);\n\t\t}\n\t\tthis.lastEventSequence = maxEventSequence(this.lastEventSequence, message.lastEventSequence);\n\t\tthis.attachedSessionId = snapshot.state.sessionId;\n\t\tthis.attachedSessionFile = snapshot.state.sessionFile;\n\t\tthis.latestSnapshot = mapDaemonSessionSnapshot(snapshot);\n\t\tthis.latestSnapshotIsFresh = true;\n\t\tassembly.resolve(snapshot);\n\t\tconst purpose = assembly.begin.purpose ?? \"attach\";\n\t\tclearTimeout(assembly.timeout);\n\t\tif (purpose !== \"attach\") {\n\t\t\tthis.snapshotAssemblies.delete(message.snapshotId);\n\t\t\tif (this.pendingReattachActiveSessionIds.has(message.activeSessionId)) {\n\t\t\t\tthis.completedSnapshots.set(message.snapshotId, snapshot);\n\t\t\t\twhile (this.completedSnapshots.size > MAX_COMPLETED_SNAPSHOTS) {\n\t\t\t\t\tconst oldest = this.completedSnapshots.keys().next().value;\n\t\t\t\t\tif (oldest === undefined) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tthis.completedSnapshots.delete(oldest);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (purpose === \"replacement\") {\n\t\t\tawait this.emit({ type: \"session_replaced\", state: snapshot.state, messages });\n\t\t} else if (purpose === \"resync\") {\n\t\t\tawait this.emit({ type: \"session_resynced\", snapshot: this.latestSnapshot });\n\t\t}\n\t}\n\n\tprivate observeRlmChildUpdate(child: AgentConnectionRlmChildAgentSnapshot): void {\n\t\tif (!this.latestSnapshot) return;\n\t\tconst children = this.latestSnapshot.children ?? [];\n\t\tconst index = children.findIndex((candidate) => candidate.id === child.id);\n\t\tconst updatedChildren = [...children];\n\t\tif (index === -1) {\n\t\t\tupdatedChildren.push(child);\n\t\t} else {\n\t\t\tupdatedChildren[index] = child;\n\t\t}\n\t\tthis.latestSnapshot = { ...this.latestSnapshot, children: updatedChildren };\n\t}\n\n\tprivate observeStreamingMessage(event: AgentSessionEvent): void {\n\t\tif (!this.latestSnapshot) {\n\t\t\treturn;\n\t\t}\n\t\tif ((event.type === \"message_start\" || event.type === \"message_update\") && event.message.role === \"assistant\") {\n\t\t\tthis.latestSnapshot = { ...this.latestSnapshot, streamingMessage: event.message };\n\t\t\treturn;\n\t\t}\n\t\tif ((event.type === \"message_end\" && event.message.role === \"assistant\") || event.type === \"agent_end\") {\n\t\t\tconst { streamingMessage: _streamingMessage, ...snapshot } = this.latestSnapshot;\n\t\t\tthis.latestSnapshot = snapshot;\n\t\t}\n\t}\n\n\tprivate isMessageForActiveSession(message: DaemonOutbound): boolean {\n\t\tif (!(\"activeSessionId\" in message)) {\n\t\t\treturn false;\n\t\t}\n\t\treturn message.activeSessionId === this.activeSessionId;\n\t}\n\n\tprivate isStaleSequencedMessage(message: DaemonOutbound): boolean {\n\t\tconst cursor = getDaemonMessageCursor(message);\n\t\tif (cursor) {\n\t\t\tif (this.retiredEventGenerations.has(cursor.generation)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t\treturn (\n\t\t\t\tthis.lastEventCursor?.generation === cursor.generation && cursor.sequence <= this.lastEventCursor.sequence\n\t\t\t);\n\t\t}\n\t\tconst sequence = getDaemonMessageSequence(message);\n\t\treturn sequence !== undefined && this.lastEventSequence !== undefined && sequence <= this.lastEventSequence;\n\t}\n\n\tprivate observeDaemonEventSequence(message: DaemonOutbound): void {\n\t\tconst cursor = getDaemonMessageCursor(message);\n\t\tif (cursor) {\n\t\t\tthis.observeEventCursor(cursor);\n\t\t\tthis.lastEventSequence = cursor.sequence;\n\t\t\treturn;\n\t\t}\n\t\tconst sequence = getDaemonMessageSequence(message);\n\t\tif (sequence === undefined) {\n\t\t\treturn;\n\t\t}\n\t\tthis.lastEventSequence =\n\t\t\tthis.lastEventSequence === undefined ? sequence : Math.max(this.lastEventSequence, sequence);\n\t\tif (this.lastEventCursor) {\n\t\t\tthis.lastEventCursor = {\n\t\t\t\t...this.lastEventCursor,\n\t\t\t\tsequence: Math.max(this.lastEventCursor.sequence, sequence),\n\t\t\t};\n\t\t}\n\t}\n\n\tprivate observeEventCursor(cursor: DaemonEventCursor): void {\n\t\tconst current = this.lastEventCursor;\n\t\tif (current && current.generation !== cursor.generation) {\n\t\t\tthis.retiredEventGenerations.add(current.generation);\n\t\t}\n\t\tif (!current || current.generation !== cursor.generation || cursor.sequence > current.sequence) {\n\t\t\tthis.lastEventCursor = cursor;\n\t\t}\n\t}\n\n\tprivate async emit(event: AgentConnectionEvent): Promise<void> {\n\t\tconst deliveries: Promise<void>[] = [];\n\t\tfor (const listener of [...this.listeners]) {\n\t\t\ttry {\n\t\t\t\tdeliveries.push(Promise.resolve(listener(event)));\n\t\t\t} catch {\n\t\t\t\t// One attachment must not interrupt delivery or transport recovery for the others.\n\t\t\t}\n\t\t}\n\t\tawait Promise.allSettled(deliveries);\n\t}\n\n\tprivate observeSideQuestionEvent(event: AgentConnectionSideQuestionEvent): void {\n\t\tif (event.status !== \"running\") {\n\t\t\tthis.activeSideQuestionIds.delete(event.id);\n\t\t}\n\t}\n}\n\nfunction readSessionSummaries(value: unknown): SessionSummary[] {\n\tif (!value || typeof value !== \"object\" || !Array.isArray((value as { sessions?: unknown }).sessions)) {\n\t\tthrow new Error(\"Daemon returned an invalid session list response\");\n\t}\n\treturn (value as { sessions: SessionSummary[] }).sessions;\n}\n\nfunction getAttachActiveSessionId(result: SessionSummary | DaemonAttachResult): string {\n\tif (\"snapshot\" in result) {\n\t\treturn result.activeSessionId;\n\t}\n\treturn result.activeSessionId ?? result.id;\n}\n\nfunction getAttachLastEventSequence(result: SessionSummary | DaemonAttachResult): number | undefined {\n\tif (\"lastEventSequence\" in result) {\n\t\treturn result.lastEventSequence;\n\t}\n\treturn undefined;\n}\n\nfunction getAttachLastEventCursor(result: SessionSummary | DaemonAttachResult): DaemonEventCursor | undefined {\n\tif (\"lastEventCursor\" in result) {\n\t\treturn result.lastEventCursor;\n\t}\n\treturn undefined;\n}\n\nfunction maxEventSequence(current: number | undefined, observed: number | undefined): number | undefined {\n\tif (current === undefined) {\n\t\treturn observed;\n\t}\n\tif (observed === undefined) {\n\t\treturn current;\n\t}\n\treturn Math.max(current, observed);\n}\n\nfunction mapDaemonSessionSnapshot(snapshot: DaemonSessionSnapshot, replay?: DaemonReplayInfo): AgentConnectionSnapshot {\n\tconst connectionSnapshot: AgentConnectionSnapshot = {\n\t\tstate: snapshot.state,\n\t\tmessages: snapshot.messages,\n\t\t...(snapshot.summary.streamingMessage ? { streamingMessage: snapshot.summary.streamingMessage } : {}),\n\t\tlastEventSequence: snapshot.lastEventSequence,\n\t\tlastEventCursor: snapshot.lastEventCursor,\n\t};\n\tif (snapshot.sessionContext) {\n\t\tconnectionSnapshot.sessionContext = snapshot.sessionContext;\n\t}\n\tif (snapshot.sessionTree) {\n\t\tconnectionSnapshot.sessionTree = snapshot.sessionTree;\n\t}\n\tif (snapshot.parent) {\n\t\tconnectionSnapshot.parent = snapshot.parent;\n\t}\n\tif (snapshot.children) {\n\t\tconnectionSnapshot.children = snapshot.children;\n\t}\n\tif (replay) {\n\t\tconnectionSnapshot.replay = replay;\n\t}\n\treturn connectionSnapshot;\n}\n\nfunction getDaemonMessageSequence(message: DaemonOutbound): number | undefined {\n\tif (!(\"meta\" in message)) {\n\t\treturn undefined;\n\t}\n\treturn message.meta?.sequence;\n}\n\nfunction getDaemonMessageCursor(message: DaemonOutbound): DaemonEventCursor | undefined {\n\tif (!(\"meta\" in message)) {\n\t\treturn undefined;\n\t}\n\treturn message.meta?.cursor;\n}\n\nfunction invalidatesCachedSnapshot(commandType: DaemonCommandBody[\"type\"]): boolean {\n\tswitch (commandType) {\n\t\tcase \"attach\":\n\t\tcase \"reattach\":\n\t\tcase \"detach\":\n\t\tcase \"list\":\n\t\tcase \"list_saved_sessions\":\n\t\tcase \"wait_for_idle\":\n\t\tcase \"get_state\":\n\t\tcase \"get_connection_state\":\n\t\tcase \"get_messages\":\n\t\tcase \"get_session_stats\":\n\t\tcase \"get_commands\":\n\t\tcase \"get_resource_snapshot\":\n\t\tcase \"get_model_catalog\":\n\t\tcase \"get_available_models\":\n\t\tcase \"get_queue\":\n\t\tcase \"cron_list\":\n\t\tcase \"heartbeats_list\":\n\t\tcase \"get_session_context\":\n\t\tcase \"get_session_tree\":\n\t\tcase \"get_user_messages_for_forking\":\n\t\tcase \"get_last_assistant_text\":\n\t\tcase \"get_system_prompt\":\n\t\tcase \"get_tool_definition\":\n\t\tcase \"start_side_question\":\n\t\tcase \"abort_side_question\":\n\t\tcase \"export_html\":\n\t\tcase \"export_jsonl\":\n\t\t\treturn false;\n\t\tdefault:\n\t\t\treturn true;\n\t}\n}\n"]}
@@ -205,7 +205,6 @@ export class DaemonAgentConnection {
205
205
  this.client.supportsServerCapability("owned_session_recovery_context")
206
206
  ? { recoveryConfig: this.options.ownedSessionRecoveryConfig }
207
207
  : {}),
208
- telemetryDisabled: this.options.telemetryDisabled,
209
208
  resumeCursor: this.lastEventCursor === undefined
210
209
  ? undefined
211
210
  : {
@@ -1028,7 +1027,6 @@ export class DaemonAgentConnection {
1028
1027
  ],
1029
1028
  env: this.options.sendClientEnv ? collectDaemonClientEnv() : undefined,
1030
1029
  launchEnv: this.options.ownedSession ? collectDaemonLaunchEnv() : undefined,
1031
- telemetryDisabled: this.options.telemetryDisabled,
1032
1030
  });
1033
1031
  reattached = true;
1034
1032
  this.activeSessionId = result.activeSessionId;