@code-yeongyu/senpi 2026.9.17-2 → 2026.9.17-4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +49 -0
- package/dist/bundle/chunks/{app-server-command-XSPV6BRF.js → app-server-command-RTISWAJY.js} +1 -1
- package/dist/bundle/chunks/{chunk-PLUQUK3T.js → chunk-IM4UIHPI.js} +15 -15
- package/dist/bundle/chunks/{chunk-ESZHT7IE.js → chunk-IMTGM3RJ.js} +1 -1
- package/dist/bundle/chunks/chunk-OQGI752B.js +2 -0
- package/dist/bundle/chunks/{chunk-Z56RXBL6.js → chunk-QDR3GME3.js} +2 -2
- package/dist/bundle/chunks/{chunk-ZPO5FWHM.js → chunk-QILSJ5PQ.js} +2 -2
- package/dist/bundle/chunks/{chunk-IGKWKAMN.js → chunk-XHTF6VKZ.js} +4 -3
- package/dist/bundle/chunks/chunk-YD5QZXAK.js +8 -0
- package/dist/bundle/chunks/{cli-main-L7WQP5V6.js → cli-main-TO3O4TUE.js} +1 -1
- package/dist/bundle/chunks/{help-fast-path-O6MBSNMK.js → help-fast-path-LFGHCIWO.js} +1 -1
- package/dist/bundle/chunks/{host-lifecycle-AI7NH6ZO.js → host-lifecycle-YPVGQSGS.js} +1 -1
- package/dist/bundle/chunks/{interactive-host-runtime-DKJKH5DU.js → interactive-host-runtime-KZLF3AZD.js} +1 -1
- package/dist/bundle/chunks/{interactive-mode-FUW5LNKL.js → interactive-mode-ARGRH6QZ.js} +1 -1
- package/dist/bundle/chunks/multi-session-host-HIZZTSYU.js +20 -0
- package/dist/bundle/chunks/{package-manager-cli-J26DB6GM.js → package-manager-cli-544JIWNJ.js} +1 -1
- package/dist/bundle/chunks/rotation-stream-FSZVBG2T.js +2 -0
- package/dist/bundle/chunks/{rpc-mode-A3U63XX7.js → rpc-mode-S3IEBFEB.js} +1 -1
- package/dist/bundle/chunks/session-worker.js +71 -68
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/cli/args.d.ts +19 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +27 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts +14 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/auth-storage.js +2 -2
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/credential-pool/rotation-stream.d.ts.map +1 -1
- package/dist/core/credential-pool/rotation-stream.js +10 -5
- package/dist/core/credential-pool/rotation-stream.js.map +1 -1
- package/dist/core/extensions/builtin/mcp/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/mcp/index.js +11 -0
- package/dist/core/extensions/builtin/mcp/index.js.map +1 -1
- package/dist/core/extensions/builtin/mcp/service.d.ts +9 -0
- package/dist/core/extensions/builtin/mcp/service.d.ts.map +1 -1
- package/dist/core/extensions/builtin/mcp/service.js +14 -1
- package/dist/core/extensions/builtin/mcp/service.js.map +1 -1
- package/dist/core/extensions/builtin/mcp/startup-race.d.ts +20 -0
- package/dist/core/extensions/builtin/mcp/startup-race.d.ts.map +1 -1
- package/dist/core/extensions/builtin/mcp/startup-race.js +38 -1
- package/dist/core/extensions/builtin/mcp/startup-race.js.map +1 -1
- package/dist/core/extensions/index.d.ts +2 -2
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts +9 -4
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +20 -9
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/types.d.ts +37 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js +8 -0
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +2 -1
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +21 -35
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +3 -2
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-runtime.d.ts +4 -2
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +9 -5
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/provider-api-key-auth.js +3 -3
- package/dist/core/provider-api-key-auth.js.map +1 -1
- package/dist/core/provider-composer.d.ts +9 -3
- package/dist/core/provider-composer.d.ts.map +1 -1
- package/dist/core/provider-composer.js +7 -4
- package/dist/core/provider-composer.js.map +1 -1
- package/dist/core/resolve-config-command.d.ts +10 -0
- package/dist/core/resolve-config-command.d.ts.map +1 -0
- package/dist/core/resolve-config-command.js +106 -0
- package/dist/core/resolve-config-command.js.map +1 -0
- package/dist/core/resolve-config-value.d.ts +4 -8
- package/dist/core/resolve-config-value.d.ts.map +1 -1
- package/dist/core/resolve-config-value.js +16 -105
- package/dist/core/resolve-config-value.js.map +1 -1
- package/dist/core/resource-loader.d.ts +7 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +13 -9
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/main.d.ts +5 -3
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +25 -11
- package/dist/main.js.map +1 -1
- package/dist/modes/rpc/child-reaper-syscalls.d.ts +18 -0
- package/dist/modes/rpc/child-reaper-syscalls.d.ts.map +1 -0
- package/dist/modes/rpc/child-reaper-syscalls.js +136 -0
- package/dist/modes/rpc/child-reaper-syscalls.js.map +1 -0
- package/dist/modes/rpc/child-reaper.d.ts +56 -0
- package/dist/modes/rpc/child-reaper.d.ts.map +1 -0
- package/dist/modes/rpc/child-reaper.js +140 -0
- package/dist/modes/rpc/child-reaper.js.map +1 -0
- package/dist/modes/rpc/custom-capability.d.ts +16 -0
- package/dist/modes/rpc/custom-capability.d.ts.map +1 -1
- package/dist/modes/rpc/custom-capability.js +16 -0
- package/dist/modes/rpc/custom-capability.js.map +1 -1
- package/dist/modes/rpc/host-memory-sampler.d.ts +48 -0
- package/dist/modes/rpc/host-memory-sampler.d.ts.map +1 -0
- package/dist/modes/rpc/host-memory-sampler.js +72 -0
- package/dist/modes/rpc/host-memory-sampler.js.map +1 -0
- package/dist/modes/rpc/loop-lag-watchdog.d.ts +51 -0
- package/dist/modes/rpc/loop-lag-watchdog.d.ts.map +1 -0
- package/dist/modes/rpc/loop-lag-watchdog.js +78 -0
- package/dist/modes/rpc/loop-lag-watchdog.js.map +1 -0
- package/dist/modes/rpc/multi-session-host.d.ts.map +1 -1
- package/dist/modes/rpc/multi-session-host.js +34 -0
- package/dist/modes/rpc/multi-session-host.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +4 -2
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +2 -1
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-input-validation.d.ts +28 -0
- package/dist/modes/rpc/rpc-input-validation.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-input-validation.js +63 -0
- package/dist/modes/rpc/rpc-input-validation.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts +18 -5
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +18 -5
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +79 -2
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js +6 -0
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/modes/rpc/session-attribution.d.ts +57 -0
- package/dist/modes/rpc/session-attribution.d.ts.map +1 -0
- package/dist/modes/rpc/session-attribution.js +132 -0
- package/dist/modes/rpc/session-attribution.js.map +1 -0
- package/dist/modes/rpc/session-binding.d.ts.map +1 -1
- package/dist/modes/rpc/session-binding.js +19 -8
- package/dist/modes/rpc/session-binding.js.map +1 -1
- package/dist/modes/rpc/session-command-router.d.ts +26 -3
- package/dist/modes/rpc/session-command-router.d.ts.map +1 -1
- package/dist/modes/rpc/session-command-router.js +95 -19
- package/dist/modes/rpc/session-command-router.js.map +1 -1
- package/dist/modes/rpc/session-event-fanout.d.ts +2 -0
- package/dist/modes/rpc/session-event-fanout.d.ts.map +1 -1
- package/dist/modes/rpc/session-event-fanout.js +6 -0
- package/dist/modes/rpc/session-event-fanout.js.map +1 -1
- package/dist/modes/rpc/session-event-writer.d.ts +29 -0
- package/dist/modes/rpc/session-event-writer.d.ts.map +1 -1
- package/dist/modes/rpc/session-event-writer.js +57 -0
- package/dist/modes/rpc/session-event-writer.js.map +1 -1
- package/dist/modes/rpc/session-registry.d.ts +42 -9
- package/dist/modes/rpc/session-registry.d.ts.map +1 -1
- package/dist/modes/rpc/session-registry.js +49 -3
- package/dist/modes/rpc/session-registry.js.map +1 -1
- package/dist/modes/rpc/worker-session-registry.d.ts +2 -10
- package/dist/modes/rpc/worker-session-registry.d.ts.map +1 -1
- package/dist/modes/rpc/worker-session-registry.js +6 -2
- package/dist/modes/rpc/worker-session-registry.js.map +1 -1
- package/docs/rpc.md +126 -20
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +24 -0
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +4 -4
- package/node_modules/@earendil-works/pi-agent-core/assets/tree-sitter/javascript.wasm +0 -0
- package/node_modules/@earendil-works/pi-agent-core/assets/tree-sitter/provenance.json +22 -0
- package/node_modules/@earendil-works/pi-agent-core/assets/tree-sitter/web-tree-sitter.wasm +0 -0
- package/node_modules/@earendil-works/pi-agent-core/package.json +3 -3
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/.manifest.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/cloudflare-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/zai-coding-cn.json +1 -1
- package/node_modules/@earendil-works/pi-ai/package.json +2 -2
- package/node_modules/@earendil-works/pi-pty/package.json +1 -1
- package/node_modules/@earendil-works/pi-telemetry/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/package.json +7 -7
- package/dist/bundle/chunks/chunk-3Q5PD4KW.js +0 -8
- package/dist/bundle/chunks/chunk-YLYLKL7X.js +0 -2
- package/dist/bundle/chunks/multi-session-host-SMNZXFPT.js +0 -18
- package/dist/bundle/chunks/rotation-stream-SCVFIQ2O.js +0 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-command-router.js","sourceRoot":"","sources":["../../../src/modes/rpc/session-command-router.ts"],"names":[],"mappings":"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","sourcesContent":["import { VERSION } from \"../../config.ts\";\nimport { buildRpcSessionState } from \"./connection-handler.ts\";\nimport {\n\tAUTO_TITLE_SESSIONS_CAPABILITY,\n\tMEDIA_PLACEHOLDERS_CAPABILITY,\n\tRETAIN_ON_DISCONNECT_CAPABILITY,\n} from \"./custom-capability.ts\";\nimport type { RpcCommand, RpcResponse } from \"./rpc-types.ts\";\nimport {\n\tRPC_ERROR_MISSING_SESSION_ID,\n\tRPC_ERROR_OPEN_FAILED,\n\tRPC_ERROR_SESSION_CLOSING,\n\tRPC_ERROR_UNKNOWN_SESSION,\n} from \"./rpc-types.ts\";\nimport { createRpcSessionBinding, type RpcSessionBinding } from \"./session-binding.ts\";\nimport type { SessionEventWriter } from \"./session-event-writer.ts\";\nimport type { OpenRpcSession, RpcSessionLaunchProfile, RpcSessionRegistry } from \"./session-registry.ts\";\nimport { RpcSessionRegistryError } from \"./session-registry.ts\";\n\nconst controls = new Set([\"get_protocol_info\", \"open_session\", \"close_session\", \"list_sessions\"]);\n\n/** Binding factory seam, injectable so host wiring is testable without a full runtime stack. */\nexport type RpcBindingFactory = typeof createRpcSessionBinding;\n\n/**\n * Occupancy policy for the shared multi-session host. All fields are opt-in:\n * a router constructed without a policy keeps today's behavior (sessions live\n * until close_session; the host never self-exits).\n */\nexport interface RpcSessionIdlePolicy {\n\t/** Injectable clock (defaults to Date.now) for deterministic tests. */\n\tnow?: () => number;\n\t/** Evict open sessions whose last routed command or session-owned work settled longer ago than this. */\n\tidleEvictionMs?: number;\n\t/** Invoke onEmptyExit once the registry has stayed empty for this long. */\n\temptyExitMs?: number;\n\t/** Host shutdown hook fired by the empty-exit window; called at most once. */\n\tonEmptyExit?: () => void;\n\t/**\n\t * Consulted every tick before the empty-exit window advances. Returning false\n\t * both blocks the exit and resets the window, so a host with a connected but\n\t * sessionless client stays up instead of exiting under its supervisor.\n\t */\n\tcanExitWhenEmpty?: () => boolean;\n}\n\n/**\n * How one caller claims a close. `detach` (a client going away) is the only mode a\n * retained session may answer by staying open, so it is unrepresentable together\n * with `drainAttachments` - draining ENDS the session and must always reach zero.\n */\ntype CloseClaimOptions = { drainAttachments: true; detach?: never } | { drainAttachments: false; detach?: boolean };\n\nfunction error(id: string | undefined, command: string, code: string): RpcResponse {\n\treturn { id, type: \"response\", command, success: false, error: code };\n}\n\n/** Routes control messages and enforces a routing handle for every session command. */\nexport class SessionCommandRouter {\n\tprivate readonly bindings = new Map<string, RpcSessionBinding>();\n\t/** Session handles opened by each connection, with one count per attachment. */\n\tprivate readonly sessionsByConnection = new Map<string, Map<string, number>>();\n\t/** Opens currently awaiting runtime/binding setup, keyed by connection. */\n\tprivate readonly opensByConnection = new Map<string, Set<Promise<void>>>();\n\t/** Connections whose socket has already been detached. */\n\tprivate readonly releasedConnections = new Set<string>();\n\tprivate readonly registry: Pick<\n\t\tRpcSessionRegistry,\n\t\t\"openSession\" | \"peek\" | \"getForCommand\" | \"beginClose\" | \"close\" | \"closeMarked\" | \"list\" | \"size\"\n\t>;\n\tprivate readonly writer: SessionEventWriter;\n\tprivate readonly defaults: Pick<\n\t\tRpcSessionLaunchProfile,\n\t\t\"cwd\" | \"permissionPreset\" | \"creationModel\" | \"initialThinkingLevel\"\n\t>;\n\tprivate readonly createBinding: typeof createRpcSessionBinding;\n\tprivate readonly connectionOptions: Parameters<typeof createRpcSessionBinding>[4];\n\tprivate readonly widths = new Map<string, Map<string, number>>();\n\tprivate readonly pendingCapabilities = new Map<string, string[]>();\n\tprivate readonly finalizations = new Map<string, { promise: Promise<void>; resolve: () => void }>();\n\tprivate readonly idleNow: () => number;\n\tprivate readonly idleEvictionMs: number;\n\tprivate readonly emptyExitMs: number;\n\tprivate readonly onEmptyExit?: () => void;\n\tprivate readonly canExitWhenEmpty?: () => boolean;\n\tprivate sweepTimer: ReturnType<typeof setInterval> | undefined;\n\tprivate emptySince: number | undefined;\n\n\tconstructor(\n\t\tregistry: Pick<\n\t\t\tRpcSessionRegistry,\n\t\t\t\"openSession\" | \"peek\" | \"getForCommand\" | \"beginClose\" | \"close\" | \"closeMarked\" | \"list\" | \"size\"\n\t\t>,\n\t\twriter: SessionEventWriter,\n\t\tdefaults: Pick<RpcSessionLaunchProfile, \"cwd\" | \"permissionPreset\" | \"creationModel\" | \"initialThinkingLevel\">,\n\t\tcreateBinding: typeof createRpcSessionBinding = createRpcSessionBinding,\n\t\tconnectionOptions: Parameters<typeof createRpcSessionBinding>[4] = {},\n\t\tidle?: RpcSessionIdlePolicy,\n\t) {\n\t\tthis.registry = registry;\n\t\tthis.writer = writer;\n\t\tthis.defaults = defaults;\n\t\tthis.createBinding = createBinding;\n\t\tthis.connectionOptions = connectionOptions;\n\t\tthis.idleNow = idle?.now ?? Date.now;\n\t\tthis.idleEvictionMs = idle?.idleEvictionMs ?? Number.POSITIVE_INFINITY;\n\t\tthis.emptyExitMs = idle?.emptyExitMs ?? Number.POSITIVE_INFINITY;\n\t\tthis.onEmptyExit = idle?.onEmptyExit;\n\t\tthis.canExitWhenEmpty = idle?.canExitWhenEmpty;\n\t\tif (Number.isFinite(this.idleEvictionMs) || Number.isFinite(this.emptyExitMs)) {\n\t\t\t// Unref'd: occupancy hygiene must never be the reason the event loop stays open.\n\t\t\tconst tickMs = Math.max(20, Math.min(5_000, Math.min(this.idleEvictionMs, this.emptyExitMs) / 4));\n\t\t\tthis.sweepTimer = setInterval(() => this.sweepIdleSessions(), tickMs);\n\t\t\tthis.sweepTimer.unref?.();\n\t\t}\n\t}\n\n\tasync handle(command: RpcCommand): Promise<RpcResponse | undefined> {\n\t\tif (command.type === \"get_protocol_info\") {\n\t\t\tconst capabilities = new Set([\n\t\t\t\t\"multi_session\",\n\t\t\t\tAUTO_TITLE_SESSIONS_CAPABILITY,\n\t\t\t\tMEDIA_PLACEHOLDERS_CAPABILITY,\n\t\t\t\t// Host capability, not a client opt-in: only a multi-session host owns the\n\t\t\t\t// attachment refcount `open_session.retain_on_disconnect` detaches from.\n\t\t\t\tRETAIN_ON_DISCONNECT_CAPABILITY,\n\t\t\t\t...(this.connectionOptions?.capabilities ?? []),\n\t\t\t]);\n\t\t\treturn {\n\t\t\t\tid: command.id,\n\t\t\t\ttype: \"response\",\n\t\t\t\tcommand: \"get_protocol_info\",\n\t\t\t\tsuccess: true,\n\t\t\t\tdata: {\n\t\t\t\t\tprotocolVersion: 1,\n\t\t\t\t\tserverVersion: VERSION,\n\t\t\t\t\tcapabilities: [...capabilities],\n\t\t\t\t\tmode: \"multi\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tif (command.type === \"list_sessions\")\n\t\t\treturn {\n\t\t\t\tid: command.id,\n\t\t\t\ttype: \"response\",\n\t\t\t\tcommand: \"list_sessions\",\n\t\t\t\tsuccess: true,\n\t\t\t\tdata: { sessions: this.registry.list() },\n\t\t\t};\n\t\tif (command.type === \"open_session\") return this.openWithBarrier(command);\n\t\tif (command.type === \"close_session\") return this.close(command);\n\t\tif (command.type === \"set_client_info\" && !command.sessionId) {\n\t\t\tconst connection = this.writer.currentConnection();\n\t\t\tif (connection !== undefined) {\n\t\t\t\tthis.pendingCapabilities.set(connection, command.capabilities ?? []);\n\t\t\t\tthis.writer.setConnectionCapabilities(connection, command.capabilities ?? []);\n\t\t\t}\n\t\t\treturn { id: command.id, type: \"response\", command: \"set_client_info\", success: true } as RpcResponse;\n\t\t}\n\t\tif (controls.has(command.type)) return undefined;\n\t\tif (!command.sessionId) return error(command.id, command.type, RPC_ERROR_MISSING_SESSION_ID);\n\t\ttry {\n\t\t\tthis.registry.getForCommand(command.sessionId, command.type);\n\t\t\tconst binding = this.bindings.get(command.sessionId);\n\t\t\tif (!binding) return error(command.id, command.type, RPC_ERROR_UNKNOWN_SESSION);\n\t\t\tawait binding.handle(command);\n\t\t\treturn undefined;\n\t\t} catch (cause) {\n\t\t\treturn error(command.id, command.type, this.code(cause));\n\t\t}\n\t}\n\n\tasync dispose(): Promise<void> {\n\t\tthis.stopSweep();\n\t\tawait Promise.all(\n\t\t\t[...this.bindings.entries()].map(async ([sessionId, binding]) => {\n\t\t\t\tconst claim = this.tryClaimClose(sessionId, { drainAttachments: true });\n\t\t\t\tif (!claim) return;\n\t\t\t\tif (claim.finalizer) await this.finalizeClose(sessionId, binding);\n\t\t\t\telse await this.finalizations.get(sessionId)?.promise;\n\t\t\t}),\n\t\t);\n\t\tthis.bindings.clear();\n\t}\n\n\t/**\n\t * One occupancy sweep. Evicts open sessions idle longer than idleEvictionMs,\n\t * where \"idle\" is the COMPLETE session-owned activity contract\n\t * (`AgentSession.isSessionBusy`: agent run, bash, background terminal jobs and\n\t * other published wake sources, compaction, barrier-held session work) - busy\n\t * sessions restart their idle clock instead, so work that outlives a turn is\n\t * never killed. Fires onEmptyExit once the registry has STAYED empty for\n\t * emptyExitMs with the exit permitted; any live session or connected client\n\t * resets that window. Runs on an unref'd interval and is safe to call directly.\n\t */\n\tsweepIdleSessions(): void {\n\t\tconst now = this.idleNow();\n\t\tif (Number.isFinite(this.idleEvictionMs)) {\n\t\t\tfor (const { sessionId, status } of this.registry.list()) {\n\t\t\t\tif (status !== \"open\") continue;\n\t\t\t\tconst entry = this.registry.peek(sessionId);\n\t\t\t\tif (!entry) continue;\n\t\t\t\tif (entry.worker?.busy || entry.runtime?.session.isSessionBusy) {\n\t\t\t\t\t// Session-owned work defers eviction; the window restarts when it settles.\n\t\t\t\t\tentry.lastCommandAt = now;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (now - entry.lastCommandAt >= this.idleEvictionMs) void this.evictIdleSession(sessionId);\n\t\t\t}\n\t\t}\n\t\tif (Number.isFinite(this.emptyExitMs)) {\n\t\t\tif (this.registry.size === 0 && (this.canExitWhenEmpty?.() ?? true)) {\n\t\t\t\tif (this.emptySince === undefined) this.emptySince = now;\n\t\t\t\telse if (now - this.emptySince >= this.emptyExitMs) {\n\t\t\t\t\tthis.stopSweep();\n\t\t\t\t\tthis.onEmptyExit?.();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.emptySince = undefined;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Idle-session eviction: the same refcounted close sequence as an explicit\n\t * close_session, draining every attachment because eviction ends the shared\n\t * session, not one client's claim. Races with concurrent lifecycle paths are\n\t * tolerated the same way releaseOwnedSession tolerates them.\n\t */\n\tprivate async evictIdleSession(sessionId: string): Promise<void> {\n\t\t// A failed claim means an explicit close raced us and owns the entry now.\n\t\tconst claim = this.tryClaimClose(sessionId, { drainAttachments: true });\n\t\tif (!claim) return;\n\t\tconst binding = this.bindings.get(sessionId);\n\t\tbinding?.cancelPendingExtensionUiRequests?.();\n\t\tthis.forgetSessionOwnership(sessionId);\n\t\tif (claim.finalizer) {\n\t\t\tawait this.finalizeClose(sessionId, binding, () =>\n\t\t\t\tthis.writer.closeSession(sessionId, {\n\t\t\t\t\ttype: \"response\",\n\t\t\t\t\tcommand: \"close_session\",\n\t\t\t\t\tsuccess: true,\n\t\t\t\t\tdata: {},\n\t\t\t\t}),\n\t\t\t);\n\t\t} else {\n\t\t\tawait this.finalizations.get(sessionId)?.promise;\n\t\t}\n\t\t// The runtime is disposed and routing handles are unique per process\n\t\t// epoch, so nothing can emit under this id again: drop the writer's\n\t\t// per-session bookkeeping instead of retaining it for the host's life.\n\t\tthis.writer.forgetSession(sessionId);\n\t}\n\n\t/** Drops per-connection records for a handle the host closed on its own. */\n\tprivate forgetSessionOwnership(sessionId: string): void {\n\t\tfor (const [connection, owned] of this.sessionsByConnection) {\n\t\t\towned.delete(sessionId);\n\t\t\tif (owned.size === 0) this.sessionsByConnection.delete(connection);\n\t\t}\n\t\tthis.widths.delete(sessionId);\n\t}\n\n\tprivate stopSweep(): void {\n\t\tif (this.sweepTimer === undefined) return;\n\t\tclearInterval(this.sweepTimer);\n\t\tthis.sweepTimer = undefined;\n\t}\n\n\tprivate openWithBarrier(command: Extract<RpcCommand, { type: \"open_session\" }>): Promise<RpcResponse | undefined> {\n\t\tconst owner = this.writer.currentConnection();\n\t\tif (owner === undefined) return this.open(command);\n\t\tlet resolveBarrier!: () => void;\n\t\tconst barrier = new Promise<void>((resolve) => {\n\t\t\tresolveBarrier = resolve;\n\t\t});\n\t\tconst opens = this.opensByConnection.get(owner) ?? new Set<Promise<void>>();\n\t\topens.add(barrier);\n\t\tthis.opensByConnection.set(owner, opens);\n\t\treturn this.open(command, owner).finally(() => {\n\t\t\tresolveBarrier();\n\t\t\topens.delete(barrier);\n\t\t\tif (opens.size === 0) this.opensByConnection.delete(owner);\n\t\t});\n\t}\n\n\tprivate async open(\n\t\tcommand: Extract<RpcCommand, { type: \"open_session\" }>,\n\t\towner?: string,\n\t): Promise<RpcResponse | undefined> {\n\t\tlet opened: OpenRpcSession | undefined;\n\t\ttry {\n\t\t\topened = await this.registry.openSession(\n\t\t\t\t{\n\t\t\t\t\tcwd: command.cwd ?? this.defaults.cwd,\n\t\t\t\t\tsessionPath: command.sessionPath,\n\t\t\t\t\tpermissionPreset: command.permissionPreset ?? this.defaults.permissionPreset,\n\t\t\t\t\tcreationModel:\n\t\t\t\t\t\tcommand.provider && command.modelId\n\t\t\t\t\t\t\t? { provider: command.provider, modelId: command.modelId }\n\t\t\t\t\t\t\t: this.defaults.creationModel,\n\t\t\t\t\tinitialThinkingLevel: command.thinkingLevel ?? this.defaults.initialThinkingLevel,\n\t\t\t\t},\n\t\t\t\t// Host lifecycle policy, deliberately outside the immutable launch profile.\n\t\t\t\t{ retainOnDisconnect: command.retain_on_disconnect === true },\n\t\t\t);\n\t\t\tconst openedSession = opened;\n\t\t\tconst entry = this.registry.getForCommand(openedSession.sessionId, \"open_session\");\n\t\t\tif (owner !== undefined) {\n\t\t\t\tif (!this.writer.hasRegisteredConnectionCapabilities(owner))\n\t\t\t\t\tthis.writer.setConnectionCapabilities(\n\t\t\t\t\t\towner,\n\t\t\t\t\t\tthis.pendingCapabilities.get(owner) ?? this.connectionOptions?.capabilities ?? [],\n\t\t\t\t\t);\n\t\t\t\tthis.writer.attachConnectionToSession(owner, openedSession.sessionId);\n\t\t\t}\n\t\t\t// A client that dies without close_session (terminal closed, SIGKILL, dropped\n\t\t\t// SSH) still holds this handle's attachment and its path reservation. Remember\n\t\t\t// which connection owns it so releaseConnection() can close exactly that.\n\t\t\tif (owner !== undefined) {\n\t\t\t\tconst owned = this.sessionsByConnection.get(owner) ?? new Map<string, number>();\n\t\t\t\towned.set(openedSession.sessionId, (owned.get(openedSession.sessionId) ?? 0) + 1);\n\t\t\t\tthis.sessionsByConnection.set(owner, owned);\n\t\t\t}\n\t\t\tif (!this.bindings.has(openedSession.sessionId)) {\n\t\t\t\tthis.bindings.set(\n\t\t\t\t\topenedSession.sessionId,\n\t\t\t\t\tawait this.createBinding(\n\t\t\t\t\t\topenedSession.sessionId,\n\t\t\t\t\t\tentry,\n\t\t\t\t\t\tthis.writer,\n\t\t\t\t\t\t() => void this.close({ type: \"close_session\", sessionId: openedSession.sessionId }),\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t...this.connectionOptions,\n\t\t\t\t\t\t\tcapabilities:\n\t\t\t\t\t\t\t\towner !== undefined\n\t\t\t\t\t\t\t\t\t? (this.pendingCapabilities.get(owner) ?? this.connectionOptions?.capabilities ?? [])\n\t\t\t\t\t\t\t\t\t: this.connectionOptions?.capabilities,\n\t\t\t\t\t\t\tsharedWidth: {\n\t\t\t\t\t\t\t\tgetWidth: () => {\n\t\t\t\t\t\t\t\t\tconst widths = this.widths.get(openedSession.sessionId);\n\t\t\t\t\t\t\t\t\treturn widths?.size ? Math.min(...widths.values()) : 80;\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tsetWidth: (connectionId, width) => {\n\t\t\t\t\t\t\t\t\tif (connectionId !== undefined) {\n\t\t\t\t\t\t\t\t\t\tconst widths = this.widths.get(openedSession.sessionId) ?? new Map<string, number>();\n\t\t\t\t\t\t\t\t\t\twidths.set(connectionId, width);\n\t\t\t\t\t\t\t\t\t\tthis.widths.set(openedSession.sessionId, widths);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tclearWidth: (connectionId) => {\n\t\t\t\t\t\t\t\t\tconst widths = this.widths.get(openedSession.sessionId);\n\t\t\t\t\t\t\t\t\tif (connectionId !== undefined) widths?.delete(connectionId);\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tsetCapabilities: (connectionId, capabilities) => {\n\t\t\t\t\t\t\t\t\tif (connectionId !== undefined) {\n\t\t\t\t\t\t\t\t\t\tthis.writer.setConnectionCapabilities(connectionId, capabilities);\n\t\t\t\t\t\t\t\t\t\tthis.pendingCapabilities.set(connectionId, [...capabilities]);\n\t\t\t\t\t\t\t\t\t\tfor (const binding of this.bindings.values()) binding.rerenderComponents?.();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\thasRenderedComponents: (sessionId) => this.writer.hasCapableConnection(sessionId),\n\n\t\t\t\t\t\t\t\tconnectionId: () => this.writer.currentConnection(),\n\t\t\t\t\t\t\t\tonChange: () => {\n\t\t\t\t\t\t\t\t\tfor (const binding of this.bindings.values()) binding.rerenderComponents?.();\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tif (entry.worker) entry.worker.bindingReady = true;\n\t\t\t\tif (entry.worker)\n\t\t\t\t\tvoid entry.worker.exited.then(async () => {\n\t\t\t\t\t\tawait this.finalizations.get(openedSession.sessionId)?.promise;\n\t\t\t\t\t\tthis.bindings.delete(openedSession.sessionId);\n\t\t\t\t\t\tthis.forgetSessionOwnership(openedSession.sessionId);\n\t\t\t\t\t\tthis.writer.forgetSession(openedSession.sessionId);\n\t\t\t\t\t});\n\t\t\t}\n\t\t\tif (owner !== undefined && this.releasedConnections.has(owner)) {\n\t\t\t\tthis.releaseOwnerAttachment(owner, openedSession.sessionId);\n\t\t\t\tawait this.releaseOwnedSession(openedSession.sessionId);\n\t\t\t}\n\t\t\tconst state =\n\t\t\t\tentry.worker?.snapshot?.state ?? (entry.runtime ? buildRpcSessionState(entry.runtime.session) : undefined);\n\t\t\tif (!state) throw new Error(\"Session state was not created\");\n\t\t\tthis.writer.enqueue(opened.sessionId, {\n\t\t\t\tid: command.id,\n\t\t\t\ttype: \"response\",\n\t\t\t\tcommand: \"open_session\",\n\t\t\t\tsuccess: true,\n\t\t\t\tdata: {\n\t\t\t\t\tsessionId: opened.sessionId,\n\t\t\t\t\tstate,\n\t\t\t\t\t...(opened.attached ? { attached: true } : {}),\n\t\t\t\t},\n\t\t\t});\n\t\t\treturn undefined;\n\t\t} catch (cause) {\n\t\t\tif (opened) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.registry.close(opened.sessionId);\n\t\t\t\t} catch {\n\t\t\t\t\t/* The open rollback has already removed the entry. */\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn error(command.id, \"open_session\", this.code(cause));\n\t\t}\n\t}\n\n\t/**\n\t * Releases every session a dropped connection still owned. Each handle goes through\n\t * the same refcounted close as an explicit close_session, so a session another\n\t * connection is still attached to keeps running and only the last owner tears it down.\n\t */\n\tasync releaseConnection(connectionId: string): Promise<void> {\n\t\tthis.releasedConnections.add(connectionId);\n\t\tthis.writer.clearConnectionCapabilities(connectionId);\n\t\tfor (const sessionId of this.sessionsByConnection.get(connectionId)?.keys() ?? [])\n\t\t\tthis.writer.detachConnectionFromSession(connectionId, sessionId);\n\t\tfor (const widths of this.widths.values()) widths.delete(connectionId);\n\t\tfor (const binding of this.bindings.values()) binding.rerenderComponents?.();\n\t\tconst opens = this.opensByConnection.get(connectionId);\n\t\tconst owned = this.sessionsByConnection.get(connectionId);\n\t\tthis.sessionsByConnection.delete(connectionId);\n\t\tif (owned === undefined) {\n\t\t\tif (opens) await Promise.all([...opens]);\n\t\t\tthis.releasedConnections.delete(connectionId);\n\t\t\treturn;\n\t\t}\n\t\tawait Promise.all(\n\t\t\t[...owned].map(async ([sessionId, count]) => {\n\t\t\t\tfor (let attachment = 0; attachment < count; attachment++) {\n\t\t\t\t\t// Headless completion contract: a turn survives its client's death and\n\t\t\t\t\t// runs to settlement (the host lifecycle keeps the process alive on\n\t\t\t\t\t// active turns even with zero connections). Releasing mid-turn aborts\n\t\t\t\t\t// the run and seals the session before agent_settled reaches the\n\t\t\t\t\t// lifecycle observer, leaking the busy counter so the host never\n\t\t\t\t\t// idle-exits. Defer - never skip - the release until the turn settles,\n\t\t\t\t\t// so the dropped owner's reservation still frees afterwards.\n\t\t\t\t\t//\n\t\t\t\t\t// A retained session is never closed by a drop, so it has nothing to defer:\n\t\t\t\t\t// release the attachment now - the client is already gone and must not keep\n\t\t\t\t\t// counting - and let the turn run to settlement on its own.\n\t\t\t\t\tconst live = this.registry.peek(sessionId);\n\t\t\t\t\tconst retained = live?.retainOnDisconnect === true;\n\t\t\t\t\tconst session = live?.state === \"open\" ? live.runtime?.session : undefined;\n\t\t\t\t\tif (!retained && live?.state === \"open\" && live.worker?.snapshot?.streaming) {\n\t\t\t\t\t\tconst unsubscribe = live.worker.subscribeSettled(() => {\n\t\t\t\t\t\t\tunsubscribe();\n\t\t\t\t\t\t\tvoid this.releaseOwnedSession(sessionId).catch((cause: unknown) => {\n\t\t\t\t\t\t\t\tprocess.stderr.write(\n\t\t\t\t\t\t\t\t\t`senpi rpc deferred worker release ${sessionId} failed: ${String(cause)}\\n`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (!retained && session?.isStreaming) {\n\t\t\t\t\t\tlet released = false;\n\t\t\t\t\t\tconst unsubscribe = session.subscribe((event) => {\n\t\t\t\t\t\t\tif (event.type !== \"agent_settled\" && event.type !== \"agent_idle\") return;\n\t\t\t\t\t\t\tif (released) return;\n\t\t\t\t\t\t\treleased = true;\n\t\t\t\t\t\t\tunsubscribe();\n\t\t\t\t\t\t\tvoid this.releaseOwnedSession(sessionId).catch((cause) => {\n\t\t\t\t\t\t\t\tprocess.stderr.write(\n\t\t\t\t\t\t\t\t\t`senpi rpc deferred release for session ${sessionId} failed: ${String(cause)}\\n`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tawait this.releaseOwnedSession(sessionId);\n\t\t\t\t}\n\t\t\t}),\n\t\t);\n\t\tif (opens) await Promise.all([...opens]);\n\t\tthis.releasedConnections.delete(connectionId);\n\t}\n\n\t/**\n\t * One owned handle's refcounted close: the same sequence as an explicit\n\t * close_session, tolerant of races with other lifecycle paths (an entry\n\t * already closed or claimed elsewhere is simply skipped), except that it claims\n\t * a DETACH: a retained entry keeps running at zero attachments instead of\n\t * closing, so this path releases the client's claim without ending the session.\n\t * Disposal, pending\n\t * extension-UI cancellation and binding removal happen only when this was the\n\t * LAST attachment (the entry transitioned to \"closing\"): surviving\n\t * attachments keep the shared binding and their event stream.\n\t */\n\tprivate async releaseOwnedSession(sessionId: string): Promise<void> {\n\t\t// A failed claim means the entry is already closed or owned by another path.\n\t\t// A retained entry answers the detach by staying open: no finalizer, nothing to join.\n\t\tconst claim = this.tryClaimClose(sessionId, { drainAttachments: false, detach: true });\n\t\tif (!claim) return;\n\t\tif (!claim.finalizer) {\n\t\t\tawait this.finalizations.get(sessionId)?.promise;\n\t\t\treturn;\n\t\t}\n\t\tconst binding = this.bindings.get(sessionId);\n\t\t// Pending UI requests are session-owned, not connection-owned: a question\n\t\t// asked through one connection stays answerable by every other attachment.\n\t\t// Cancel them only here, where the refcount has already decided the session\n\t\t// is being torn down, never on any owner drop.\n\t\tbinding?.cancelPendingExtensionUiRequests?.();\n\t\tawait this.finalizeClose(sessionId, binding);\n\t}\n\n\t/**\n\t * Releases one attachment (or every attachment when draining) and reports\n\t * whether this caller became the finalizer. The join token is installed inside\n\t * the registry callback, before any await, so a close that lands between the\n\t * claim and finalizeClose() always finds a token to wait on instead of\n\t * answering ahead of the terminal records.\n\t */\n\tprivate claimClose(sessionId: string, options: CloseClaimOptions): { finalizer: boolean } {\n\t\tlet finalizer = true;\n\t\tconst onRole = (isFinalizer: boolean): void => {\n\t\t\tfinalizer = isFinalizer;\n\t\t\tif (isFinalizer && !this.finalizations.has(sessionId))\n\t\t\t\tthis.finalizations.set(sessionId, this.createFinalization());\n\t\t};\n\t\tlet entry = this.registry.beginClose(sessionId, onRole, { detach: options.detach });\n\t\twhile (options.drainAttachments && entry.state === \"open\") entry = this.registry.beginClose(sessionId, onRole);\n\t\treturn { finalizer: finalizer && entry.state === \"closing\" };\n\t}\n\n\t/** claimClose() for lifecycle paths that treat a lost race as \"nothing to do\". */\n\tprivate tryClaimClose(sessionId: string, options: CloseClaimOptions): { finalizer: boolean } | undefined {\n\t\ttry {\n\t\t\treturn this.claimClose(sessionId, options);\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tprivate async close(command: Extract<RpcCommand, { type: \"close_session\" }>): Promise<RpcResponse | undefined> {\n\t\tconst response = {\n\t\t\tid: command.id,\n\t\t\ttype: \"response\" as const,\n\t\t\tcommand: \"close_session\" as const,\n\t\t\tsuccess: true as const,\n\t\t\tdata: {},\n\t\t};\n\t\tconst reply = this.writer.reserveCloseResponse(command.sessionId, response);\n\t\tif (!reply) return undefined;\n\t\t// Admission and claiming are synchronous, before any teardown await. A\n\t\t// saturated requester neither releases an attachment nor joins a promise.\n\t\tlet claim: { finalizer: boolean };\n\t\ttry {\n\t\t\tclaim = this.claimClose(command.sessionId, { drainAttachments: false });\n\t\t} catch (cause) {\n\t\t\treply.release();\n\t\t\treturn error(command.id, \"close_session\", this.code(cause));\n\t\t}\n\t\ttry {\n\t\t\tconst owner = this.writer.currentConnection();\n\t\t\tif (owner !== undefined) this.releaseOwnerAttachment(owner, command.sessionId);\n\t\t\tif (claim.finalizer) {\n\t\t\t\tawait this.finalizeClose(command.sessionId, this.bindings.get(command.sessionId), () =>\n\t\t\t\t\treply.complete(true),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tawait this.finalizations.get(command.sessionId)?.promise;\n\t\t\t\treply.complete(false);\n\t\t\t}\n\t\t\treturn undefined;\n\t\t} finally {\n\t\t\treply.release();\n\t\t}\n\t}\n\n\t/** Detaches the closing connection's UI/width state; a rerender failure must not abort the close. */\n\tprivate releaseOwnerAttachment(owner: string, sessionId: string): void {\n\t\tthis.widths.get(sessionId)?.delete(owner);\n\t\tthis.writer.detachConnectionFromSession(owner, sessionId);\n\t\tfor (const binding of this.bindings.values()) {\n\t\t\ttry {\n\t\t\t\tbinding.rerenderComponents?.();\n\t\t\t} catch (cause) {\n\t\t\t\tprocess.stderr.write(`senpi rpc rerender after close of session ${sessionId} failed: ${String(cause)}\\n`);\n\t\t\t}\n\t\t}\n\t\tconst owned = this.sessionsByConnection.get(owner);\n\t\tconst count = owned?.get(sessionId);\n\t\tif (!owned || count === undefined) return;\n\t\tif (count === 1) owned.delete(sessionId);\n\t\telse owned.set(sessionId, count - 1);\n\t\tif (owned.size === 0) this.sessionsByConnection.delete(owner);\n\t}\n\n\t/**\n\t * Runs the finalizer side of a close for a handle whose beginClose() made this\n\t * caller the owner: dispose the binding, complete the registry teardown, emit\n\t * the terminal records, then release joiners. Every step is guarded so the join\n\t * token always resolves and a failing binding yields one logged line, never a\n\t * second response or an escaped rejection.\n\t */\n\tprivate async finalizeClose(\n\t\tsessionId: string,\n\t\tbinding: RpcSessionBinding | undefined,\n\t\tterminal?: () => void,\n\t): Promise<void> {\n\t\tconst finalization = this.finalizations.get(sessionId) ?? this.createFinalization();\n\t\tthis.finalizations.set(sessionId, finalization);\n\t\ttry {\n\t\t\ttry {\n\t\t\t\tawait binding?.dispose();\n\t\t\t} catch (cause) {\n\t\t\t\tprocess.stderr.write(`senpi rpc binding dispose for session ${sessionId} failed: ${String(cause)}\\n`);\n\t\t\t}\n\t\t\tthis.bindings.delete(sessionId);\n\t\t\ttry {\n\t\t\t\tawait this.registry.closeMarked(sessionId);\n\t\t\t} catch (cause) {\n\t\t\t\tprocess.stderr.write(`senpi rpc close for session ${sessionId} failed: ${String(cause)}\\n`);\n\t\t\t}\n\t\t\t// closeMarked may return at the grace deadline while ownership remains;\n\t\t\t// terminal records must still observe the exit callback's registry removal.\n\t\t\tawait this.registry.peek(sessionId)?.closeCompletion;\n\t\t\tterminal?.();\n\t\t} finally {\n\t\t\tfinalization.resolve();\n\t\t\tthis.finalizations.delete(sessionId);\n\t\t}\n\t}\n\n\tprivate createFinalization(): { promise: Promise<void>; resolve: () => void } {\n\t\tlet resolveFinalization: (() => void) | undefined;\n\t\tconst promise = new Promise<void>((resolve) => {\n\t\t\tresolveFinalization = resolve;\n\t\t});\n\t\treturn { promise, resolve: () => resolveFinalization?.() };\n\t}\n\n\tprivate code(cause: unknown): string {\n\t\tif (cause instanceof RpcSessionRegistryError) {\n\t\t\treturn cause.code === RPC_ERROR_OPEN_FAILED ? cause.message : cause.code;\n\t\t}\n\t\tif (cause instanceof Error && [RPC_ERROR_UNKNOWN_SESSION, RPC_ERROR_SESSION_CLOSING].includes(cause.message)) {\n\t\t\treturn cause.message;\n\t\t}\n\t\treturn cause instanceof Error && cause.message\n\t\t\t? `${RPC_ERROR_OPEN_FAILED}: ${cause.message}`\n\t\t\t: RPC_ERROR_UNKNOWN_SESSION;\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"session-command-router.js","sourceRoot":"","sources":["../../../src/modes/rpc/session-command-router.ts"],"names":[],"mappings":"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","sourcesContent":["import { VERSION } from \"../../config.ts\";\nimport { buildRpcSessionState } from \"./connection-handler.ts\";\nimport {\n\tAUTO_TITLE_PER_SESSION_CAPABILITY,\n\tAUTO_TITLE_SESSIONS_CAPABILITY,\n\tMEDIA_PLACEHOLDERS_CAPABILITY,\n\tRETAIN_ON_DISCONNECT_CAPABILITY,\n\tSESSION_CONTEXT_CAPABILITY,\n\tSESSION_KIND_CAPABILITY,\n} from \"./custom-capability.ts\";\nimport { sessionAutoTitleError, sessionContextError, sessionKindError } from \"./rpc-input-validation.ts\";\nimport type { RpcCommand, RpcResponse } from \"./rpc-types.ts\";\nimport {\n\tRPC_ERROR_INVALID_LAUNCH_PROFILE,\n\tRPC_ERROR_INVALID_SESSION_CONTEXT,\n\tRPC_ERROR_INVALID_SESSION_KIND,\n\tRPC_ERROR_MISSING_SESSION_ID,\n\tRPC_ERROR_OPEN_FAILED,\n\tRPC_ERROR_SESSION_CLOSING,\n\tRPC_ERROR_UNKNOWN_SESSION,\n} from \"./rpc-types.ts\";\nimport { runWithSessionAttribution } from \"./session-attribution.ts\";\nimport { createRpcSessionBinding, type RpcSessionBinding } from \"./session-binding.ts\";\nimport type { SessionEventWriter } from \"./session-event-writer.ts\";\nimport type { OpenRpcSession, RpcSessionLaunchProfile, RpcSessionRegistry } from \"./session-registry.ts\";\nimport { RpcSessionRegistryError } from \"./session-registry.ts\";\n\nconst controls = new Set([\"get_protocol_info\", \"open_session\", \"close_session\", \"list_sessions\"]);\n\n/** Binding factory seam, injectable so host wiring is testable without a full runtime stack. */\nexport type RpcBindingFactory = typeof createRpcSessionBinding;\n\n/**\n * Occupancy policy for the shared multi-session host. All fields are opt-in:\n * a router constructed without a policy keeps today's behavior (sessions live\n * until close_session; the host never self-exits).\n */\nexport interface RpcSessionIdlePolicy {\n\t/** Injectable clock (defaults to Date.now) for deterministic tests. */\n\tnow?: () => number;\n\t/** Evict open sessions whose last routed command or session-owned work settled longer ago than this. */\n\tidleEvictionMs?: number;\n\t/** Invoke onEmptyExit once the registry has stayed empty for this long. */\n\temptyExitMs?: number;\n\t/** Host shutdown hook fired by the empty-exit window; called at most once. */\n\tonEmptyExit?: () => void;\n\t/**\n\t * Consulted every tick before the empty-exit window advances. Returning false\n\t * both blocks the exit and resets the window, so a host with a connected but\n\t * sessionless client stays up instead of exiting under its supervisor.\n\t */\n\tcanExitWhenEmpty?: () => boolean;\n}\n\n/**\n * How one caller claims a close. `detach` (a client going away) is the only mode a\n * retained session may answer by staying open, so it is unrepresentable together\n * with `drainAttachments` - draining ENDS the session and must always reach zero.\n */\ntype CloseClaimOptions = { drainAttachments: true; detach?: never } | { drainAttachments: false; detach?: boolean };\n\nfunction error(id: string | undefined, command: string, code: string): RpcResponse {\n\treturn { id, type: \"response\", command, success: false, error: code };\n}\n\n/** Routes control messages and enforces a routing handle for every session command. */\nexport class SessionCommandRouter {\n\tprivate readonly bindings = new Map<string, RpcSessionBinding>();\n\t/** Session handles opened by each connection, with one count per attachment. */\n\tprivate readonly sessionsByConnection = new Map<string, Map<string, number>>();\n\t/** Opens currently awaiting runtime/binding setup, keyed by connection. */\n\tprivate readonly opensByConnection = new Map<string, Set<Promise<void>>>();\n\t/** Connections whose socket has already been detached. */\n\tprivate readonly releasedConnections = new Set<string>();\n\tprivate readonly registry: Pick<\n\t\tRpcSessionRegistry,\n\t\t\"openSession\" | \"peek\" | \"getForCommand\" | \"beginClose\" | \"close\" | \"closeMarked\" | \"list\" | \"size\"\n\t>;\n\tprivate readonly writer: SessionEventWriter;\n\tprivate readonly defaults: Pick<\n\t\tRpcSessionLaunchProfile,\n\t\t\"cwd\" | \"permissionPreset\" | \"creationModel\" | \"initialThinkingLevel\"\n\t>;\n\tprivate readonly createBinding: typeof createRpcSessionBinding;\n\tprivate readonly connectionOptions: Parameters<typeof createRpcSessionBinding>[4];\n\tprivate readonly widths = new Map<string, Map<string, number>>();\n\tprivate readonly pendingCapabilities = new Map<string, string[]>();\n\tprivate readonly finalizations = new Map<string, { promise: Promise<void>; resolve: () => void }>();\n\tprivate readonly idleNow: () => number;\n\tprivate readonly idleEvictionMs: number;\n\tprivate readonly emptyExitMs: number;\n\tprivate readonly onEmptyExit?: () => void;\n\tprivate readonly canExitWhenEmpty?: () => boolean;\n\tprivate sweepTimer: ReturnType<typeof setInterval> | undefined;\n\tprivate emptySince: number | undefined;\n\t/** Halves the idle window while the host reports memory pressure; never refuses work. */\n\tprivate memoryPressure = false;\n\n\tconstructor(\n\t\tregistry: Pick<\n\t\t\tRpcSessionRegistry,\n\t\t\t\"openSession\" | \"peek\" | \"getForCommand\" | \"beginClose\" | \"close\" | \"closeMarked\" | \"list\" | \"size\"\n\t\t>,\n\t\twriter: SessionEventWriter,\n\t\tdefaults: Pick<RpcSessionLaunchProfile, \"cwd\" | \"permissionPreset\" | \"creationModel\" | \"initialThinkingLevel\">,\n\t\tcreateBinding: typeof createRpcSessionBinding = createRpcSessionBinding,\n\t\tconnectionOptions: Parameters<typeof createRpcSessionBinding>[4] = {},\n\t\tidle?: RpcSessionIdlePolicy,\n\t) {\n\t\tthis.registry = registry;\n\t\tthis.writer = writer;\n\t\tthis.defaults = defaults;\n\t\tthis.createBinding = createBinding;\n\t\tthis.connectionOptions = connectionOptions;\n\t\tthis.idleNow = idle?.now ?? Date.now;\n\t\tthis.idleEvictionMs = idle?.idleEvictionMs ?? Number.POSITIVE_INFINITY;\n\t\tthis.emptyExitMs = idle?.emptyExitMs ?? Number.POSITIVE_INFINITY;\n\t\tthis.onEmptyExit = idle?.onEmptyExit;\n\t\tthis.canExitWhenEmpty = idle?.canExitWhenEmpty;\n\t\tif (Number.isFinite(this.idleEvictionMs) || Number.isFinite(this.emptyExitMs)) {\n\t\t\t// Unref'd: occupancy hygiene must never be the reason the event loop stays open.\n\t\t\tconst tickMs = Math.max(20, Math.min(5_000, Math.min(this.idleEvictionMs, this.emptyExitMs) / 4));\n\t\t\tthis.sweepTimer = setInterval(() => this.sweepIdleSessions(), tickMs);\n\t\t\tthis.sweepTimer.unref?.();\n\t\t}\n\t}\n\n\t/** Live sessions the host holds, including ones opening or closing. */\n\tget sessionCount(): number {\n\t\treturn this.registry.size;\n\t}\n\n\t/**\n\t * Raised by the host's memory sampler. Under pressure idle sessions are parked at\n\t * HALF the configured window, which returns their memory to the process sooner.\n\t * Deliberately the only lever: the host never refuses or kills a session for memory.\n\t */\n\tsetMemoryPressure(pressure: boolean): void {\n\t\tthis.memoryPressure = pressure;\n\t}\n\n\t/**\n\t * Every routed command runs inside its session's attribution scope, so a stall the\n\t * loop-lag watchdog observes right after this dispatch can name the session that\n\t * caused it - and anything the command starts inherits the attribution.\n\t */\n\thandle(command: RpcCommand): Promise<RpcResponse | undefined> {\n\t\tconst sessionId = \"sessionId\" in command ? command.sessionId : undefined;\n\t\treturn runWithSessionAttribution({ sessionId }, () => this.dispatch(command));\n\t}\n\n\tprivate async dispatch(command: RpcCommand): Promise<RpcResponse | undefined> {\n\t\tif (command.type === \"get_protocol_info\") {\n\t\t\tconst capabilities = new Set([\n\t\t\t\t\"multi_session\",\n\t\t\t\tAUTO_TITLE_SESSIONS_CAPABILITY,\n\t\t\t\tMEDIA_PLACEHOLDERS_CAPABILITY,\n\t\t\t\t// Host capabilities, not client opt-ins: only a multi-session host owns the\n\t\t\t\t// attachment refcount `open_session.retain_on_disconnect` detaches from, the\n\t\t\t\t// per-session launch profile `context`/`auto_title` travel on, and the session\n\t\t\t\t// listing `kind` filters.\n\t\t\t\tRETAIN_ON_DISCONNECT_CAPABILITY,\n\t\t\t\tSESSION_CONTEXT_CAPABILITY,\n\t\t\t\tSESSION_KIND_CAPABILITY,\n\t\t\t\tAUTO_TITLE_PER_SESSION_CAPABILITY,\n\t\t\t\t...(this.connectionOptions?.capabilities ?? []),\n\t\t\t]);\n\t\t\treturn {\n\t\t\t\tid: command.id,\n\t\t\t\ttype: \"response\",\n\t\t\t\tcommand: \"get_protocol_info\",\n\t\t\t\tsuccess: true,\n\t\t\t\tdata: {\n\t\t\t\t\tprotocolVersion: 1,\n\t\t\t\t\tserverVersion: VERSION,\n\t\t\t\t\tcapabilities: [...capabilities],\n\t\t\t\t\tmode: \"multi\",\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\t\tif (command.type === \"list_sessions\") {\n\t\t\t// Worker sessions are machine-driven work: a client sees them only by asking, and\n\t\t\t// the opaque context blob travels only on that listing, never to every connection.\n\t\t\tconst rows = this.registry.list();\n\t\t\tconst sessions =\n\t\t\t\tcommand.include_workers === true\n\t\t\t\t\t? rows\n\t\t\t\t\t: rows.filter((row) => row.kind !== \"worker\").map(({ context: _context, ...row }) => row);\n\t\t\treturn {\n\t\t\t\tid: command.id,\n\t\t\t\ttype: \"response\",\n\t\t\t\tcommand: \"list_sessions\",\n\t\t\t\tsuccess: true,\n\t\t\t\tdata: { sessions },\n\t\t\t};\n\t\t}\n\t\tif (command.type === \"open_session\") return this.openWithBarrier(command);\n\t\tif (command.type === \"close_session\") return this.close(command);\n\t\tif (command.type === \"set_client_info\" && !command.sessionId) {\n\t\t\tconst connection = this.writer.currentConnection();\n\t\t\tif (connection !== undefined) {\n\t\t\t\tthis.pendingCapabilities.set(connection, command.capabilities ?? []);\n\t\t\t\tthis.writer.setConnectionCapabilities(connection, command.capabilities ?? []);\n\t\t\t}\n\t\t\treturn { id: command.id, type: \"response\", command: \"set_client_info\", success: true } as RpcResponse;\n\t\t}\n\t\tif (controls.has(command.type)) return undefined;\n\t\tif (!command.sessionId) return error(command.id, command.type, RPC_ERROR_MISSING_SESSION_ID);\n\t\ttry {\n\t\t\tthis.registry.getForCommand(command.sessionId, command.type);\n\t\t\tconst binding = this.bindings.get(command.sessionId);\n\t\t\tif (!binding) return error(command.id, command.type, RPC_ERROR_UNKNOWN_SESSION);\n\t\t\tawait binding.handle(command);\n\t\t\treturn undefined;\n\t\t} catch (cause) {\n\t\t\treturn error(command.id, command.type, this.code(cause));\n\t\t}\n\t}\n\n\tasync dispose(): Promise<void> {\n\t\tthis.stopSweep();\n\t\tawait Promise.all(\n\t\t\t[...this.bindings.entries()].map(async ([sessionId, binding]) => {\n\t\t\t\tconst claim = this.tryClaimClose(sessionId, { drainAttachments: true });\n\t\t\t\tif (!claim) return;\n\t\t\t\tif (claim.finalizer) await this.finalizeClose(sessionId, binding);\n\t\t\t\telse await this.finalizations.get(sessionId)?.promise;\n\t\t\t}),\n\t\t);\n\t\tthis.bindings.clear();\n\t}\n\n\t/**\n\t * One occupancy sweep. Evicts open sessions idle longer than idleEvictionMs,\n\t * where \"idle\" is the COMPLETE session-owned activity contract\n\t * (`AgentSession.isSessionBusy`: agent run, bash, background terminal jobs and\n\t * other published wake sources, compaction, barrier-held session work) - busy\n\t * sessions restart their idle clock instead, so work that outlives a turn is\n\t * never killed. While the host reports memory pressure the window is HALVED, so an\n\t * idle session's memory returns to the process sooner. Fires onEmptyExit once the\n\t * registry has STAYED empty for emptyExitMs with the exit permitted; any live session\n\t * or connected client resets that window. Runs on an unref'd interval and is safe to\n\t * call directly.\n\t */\n\tsweepIdleSessions(): void {\n\t\tconst now = this.idleNow();\n\t\tconst idleEvictionMs = this.memoryPressure ? this.idleEvictionMs / 2 : this.idleEvictionMs;\n\t\tif (Number.isFinite(idleEvictionMs)) {\n\t\t\tfor (const { sessionId, status } of this.registry.list()) {\n\t\t\t\tif (status !== \"open\") continue;\n\t\t\t\tconst entry = this.registry.peek(sessionId);\n\t\t\t\tif (!entry) continue;\n\t\t\t\tif (entry.worker?.busy || entry.runtime?.session.isSessionBusy) {\n\t\t\t\t\t// Session-owned work defers eviction; the window restarts when it settles.\n\t\t\t\t\tentry.lastCommandAt = now;\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tif (now - entry.lastCommandAt >= idleEvictionMs) void this.evictIdleSession(sessionId);\n\t\t\t}\n\t\t}\n\t\tif (Number.isFinite(this.emptyExitMs)) {\n\t\t\tif (this.registry.size === 0 && (this.canExitWhenEmpty?.() ?? true)) {\n\t\t\t\tif (this.emptySince === undefined) this.emptySince = now;\n\t\t\t\telse if (now - this.emptySince >= this.emptyExitMs) {\n\t\t\t\t\tthis.stopSweep();\n\t\t\t\t\tthis.onEmptyExit?.();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.emptySince = undefined;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Idle-session eviction: the same refcounted close sequence as an explicit\n\t * close_session, draining every attachment because eviction ends the shared\n\t * session, not one client's claim. Races with concurrent lifecycle paths are\n\t * tolerated the same way releaseOwnedSession tolerates them.\n\t *\n\t * Evicting a RETAINED session is a PARK, not a close: that session was opened to\n\t * outlive its clients, so the terminal record names the file it reopens by\n\t * (`session_parked`) instead of reporting a close nobody requested. The teardown\n\t * itself is identical - retention never outlives the idle window.\n\t */\n\tprivate async evictIdleSession(sessionId: string): Promise<void> {\n\t\t// Read before the claim: the entry is gone once the teardown completes, and a park\n\t\t// record without the session's path would not be actionable (so a retained session\n\t\t// with no file to reopen by ends as an ordinary close).\n\t\tconst retained = this.registry.peek(sessionId);\n\t\tconst parkedPath = retained?.retainOnDisconnect === true ? retained.sessionPath : undefined;\n\t\t// A failed claim means an explicit close raced us and owns the entry now.\n\t\tconst claim = this.tryClaimClose(sessionId, { drainAttachments: true });\n\t\tif (!claim) return;\n\t\tconst binding = this.bindings.get(sessionId);\n\t\tbinding?.cancelPendingExtensionUiRequests?.();\n\t\tthis.forgetSessionOwnership(sessionId);\n\t\tif (claim.finalizer) {\n\t\t\tawait this.finalizeClose(sessionId, binding, () =>\n\t\t\t\tparkedPath === undefined\n\t\t\t\t\t? this.writer.closeSession(sessionId, {\n\t\t\t\t\t\t\ttype: \"response\",\n\t\t\t\t\t\t\tcommand: \"close_session\",\n\t\t\t\t\t\t\tsuccess: true,\n\t\t\t\t\t\t\tdata: {},\n\t\t\t\t\t\t})\n\t\t\t\t\t: this.writer.parkSession(sessionId, parkedPath),\n\t\t\t);\n\t\t} else {\n\t\t\tawait this.finalizations.get(sessionId)?.promise;\n\t\t}\n\t\t// The runtime is disposed and routing handles are unique per process\n\t\t// epoch, so nothing can emit under this id again: drop the writer's\n\t\t// per-session bookkeeping instead of retaining it for the host's life.\n\t\tthis.writer.forgetSession(sessionId);\n\t}\n\n\t/** Drops per-connection records for a handle the host closed on its own. */\n\tprivate forgetSessionOwnership(sessionId: string): void {\n\t\tfor (const [connection, owned] of this.sessionsByConnection) {\n\t\t\towned.delete(sessionId);\n\t\t\tif (owned.size === 0) this.sessionsByConnection.delete(connection);\n\t\t}\n\t\tthis.widths.delete(sessionId);\n\t}\n\n\tprivate stopSweep(): void {\n\t\tif (this.sweepTimer === undefined) return;\n\t\tclearInterval(this.sweepTimer);\n\t\tthis.sweepTimer = undefined;\n\t}\n\n\tprivate openWithBarrier(command: Extract<RpcCommand, { type: \"open_session\" }>): Promise<RpcResponse | undefined> {\n\t\tconst owner = this.writer.currentConnection();\n\t\tif (owner === undefined) return this.open(command);\n\t\tlet resolveBarrier!: () => void;\n\t\tconst barrier = new Promise<void>((resolve) => {\n\t\t\tresolveBarrier = resolve;\n\t\t});\n\t\tconst opens = this.opensByConnection.get(owner) ?? new Set<Promise<void>>();\n\t\topens.add(barrier);\n\t\tthis.opensByConnection.set(owner, opens);\n\t\treturn this.open(command, owner).finally(() => {\n\t\t\tresolveBarrier();\n\t\t\topens.delete(barrier);\n\t\t\tif (opens.size === 0) this.opensByConnection.delete(owner);\n\t\t});\n\t}\n\n\tprivate async open(\n\t\tcommand: Extract<RpcCommand, { type: \"open_session\" }>,\n\t\towner?: string,\n\t): Promise<RpcResponse | undefined> {\n\t\t// The opaque per-session inputs are parsed HERE, at the wire boundary, so the\n\t\t// registry, the runtime and the extensions downstream receive values already\n\t\t// proven to satisfy every documented cap.\n\t\tconst kindError = sessionKindError(command.kind);\n\t\tif (kindError) return error(command.id, \"open_session\", `${RPC_ERROR_INVALID_SESSION_KIND}: ${kindError}`);\n\t\tconst contextError = sessionContextError(command.context);\n\t\tif (contextError)\n\t\t\treturn error(command.id, \"open_session\", `${RPC_ERROR_INVALID_SESSION_CONTEXT}: ${contextError}`);\n\t\tconst autoTitleError = sessionAutoTitleError(command.auto_title);\n\t\tif (autoTitleError)\n\t\t\treturn error(command.id, \"open_session\", `${RPC_ERROR_INVALID_LAUNCH_PROFILE}: ${autoTitleError}`);\n\t\tlet opened: OpenRpcSession | undefined;\n\t\ttry {\n\t\t\topened = await this.registry.openSession(\n\t\t\t\t{\n\t\t\t\t\tcwd: command.cwd ?? this.defaults.cwd,\n\t\t\t\t\tsessionPath: command.sessionPath,\n\t\t\t\t\tpermissionPreset: command.permissionPreset ?? this.defaults.permissionPreset,\n\t\t\t\t\tcreationModel:\n\t\t\t\t\t\tcommand.provider && command.modelId\n\t\t\t\t\t\t\t? { provider: command.provider, modelId: command.modelId }\n\t\t\t\t\t\t\t: this.defaults.creationModel,\n\t\t\t\t\tinitialThinkingLevel: command.thinkingLevel ?? this.defaults.initialThinkingLevel,\n\t\t\t\t\tsessionKind: command.kind,\n\t\t\t\t\tsessionContext: command.context,\n\t\t\t\t\t...(typeof command.auto_title === \"boolean\" ? { autoTitle: command.auto_title } : {}),\n\t\t\t\t},\n\t\t\t\t// Host lifecycle policy, deliberately outside the immutable launch profile.\n\t\t\t\t{ retainOnDisconnect: command.retain_on_disconnect === true },\n\t\t\t);\n\t\t\tconst openedSession = opened;\n\t\t\tconst entry = this.registry.getForCommand(openedSession.sessionId, \"open_session\");\n\t\t\tthis.writer.setSessionKind(openedSession.sessionId, entry.kind);\n\t\t\tif (owner !== undefined) {\n\t\t\t\tif (!this.writer.hasRegisteredConnectionCapabilities(owner))\n\t\t\t\t\tthis.writer.setConnectionCapabilities(\n\t\t\t\t\t\towner,\n\t\t\t\t\t\tthis.pendingCapabilities.get(owner) ?? this.connectionOptions?.capabilities ?? [],\n\t\t\t\t\t);\n\t\t\t\tthis.writer.attachConnectionToSession(owner, openedSession.sessionId);\n\t\t\t}\n\t\t\t// A client that dies without close_session (terminal closed, SIGKILL, dropped\n\t\t\t// SSH) still holds this handle's attachment and its path reservation. Remember\n\t\t\t// which connection owns it so releaseConnection() can close exactly that.\n\t\t\tif (owner !== undefined) {\n\t\t\t\tconst owned = this.sessionsByConnection.get(owner) ?? new Map<string, number>();\n\t\t\t\towned.set(openedSession.sessionId, (owned.get(openedSession.sessionId) ?? 0) + 1);\n\t\t\t\tthis.sessionsByConnection.set(owner, owned);\n\t\t\t}\n\t\t\tif (!this.bindings.has(openedSession.sessionId)) {\n\t\t\t\tthis.bindings.set(\n\t\t\t\t\topenedSession.sessionId,\n\t\t\t\t\tawait this.createBinding(\n\t\t\t\t\t\topenedSession.sessionId,\n\t\t\t\t\t\tentry,\n\t\t\t\t\t\tthis.writer,\n\t\t\t\t\t\t() => void this.close({ type: \"close_session\", sessionId: openedSession.sessionId }),\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t...this.connectionOptions,\n\t\t\t\t\t\t\tcapabilities:\n\t\t\t\t\t\t\t\towner !== undefined\n\t\t\t\t\t\t\t\t\t? (this.pendingCapabilities.get(owner) ?? this.connectionOptions?.capabilities ?? [])\n\t\t\t\t\t\t\t\t\t: this.connectionOptions?.capabilities,\n\t\t\t\t\t\t\tsharedWidth: {\n\t\t\t\t\t\t\t\tgetWidth: () => {\n\t\t\t\t\t\t\t\t\tconst widths = this.widths.get(openedSession.sessionId);\n\t\t\t\t\t\t\t\t\treturn widths?.size ? Math.min(...widths.values()) : 80;\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tsetWidth: (connectionId, width) => {\n\t\t\t\t\t\t\t\t\tif (connectionId !== undefined) {\n\t\t\t\t\t\t\t\t\t\tconst widths = this.widths.get(openedSession.sessionId) ?? new Map<string, number>();\n\t\t\t\t\t\t\t\t\t\twidths.set(connectionId, width);\n\t\t\t\t\t\t\t\t\t\tthis.widths.set(openedSession.sessionId, widths);\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tclearWidth: (connectionId) => {\n\t\t\t\t\t\t\t\t\tconst widths = this.widths.get(openedSession.sessionId);\n\t\t\t\t\t\t\t\t\tif (connectionId !== undefined) widths?.delete(connectionId);\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tsetCapabilities: (connectionId, capabilities) => {\n\t\t\t\t\t\t\t\t\tif (connectionId !== undefined) {\n\t\t\t\t\t\t\t\t\t\tthis.writer.setConnectionCapabilities(connectionId, capabilities);\n\t\t\t\t\t\t\t\t\t\tthis.pendingCapabilities.set(connectionId, [...capabilities]);\n\t\t\t\t\t\t\t\t\t\tfor (const binding of this.bindings.values()) binding.rerenderComponents?.();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\thasRenderedComponents: (sessionId) => this.writer.hasCapableConnection(sessionId),\n\n\t\t\t\t\t\t\t\tconnectionId: () => this.writer.currentConnection(),\n\t\t\t\t\t\t\t\tonChange: () => {\n\t\t\t\t\t\t\t\t\tfor (const binding of this.bindings.values()) binding.rerenderComponents?.();\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\tif (entry.worker) entry.worker.bindingReady = true;\n\t\t\t\tif (entry.worker)\n\t\t\t\t\tvoid entry.worker.exited.then(async () => {\n\t\t\t\t\t\tawait this.finalizations.get(openedSession.sessionId)?.promise;\n\t\t\t\t\t\tthis.bindings.delete(openedSession.sessionId);\n\t\t\t\t\t\tthis.forgetSessionOwnership(openedSession.sessionId);\n\t\t\t\t\t\tthis.writer.forgetSession(openedSession.sessionId);\n\t\t\t\t\t});\n\t\t\t}\n\t\t\tif (owner !== undefined && this.releasedConnections.has(owner)) {\n\t\t\t\tthis.releaseOwnerAttachment(owner, openedSession.sessionId);\n\t\t\t\tawait this.releaseOwnedSession(openedSession.sessionId);\n\t\t\t}\n\t\t\tconst state =\n\t\t\t\tentry.worker?.snapshot?.state ?? (entry.runtime ? buildRpcSessionState(entry.runtime.session) : undefined);\n\t\t\tif (!state) throw new Error(\"Session state was not created\");\n\t\t\tthis.writer.enqueue(opened.sessionId, {\n\t\t\t\tid: command.id,\n\t\t\t\ttype: \"response\",\n\t\t\t\tcommand: \"open_session\",\n\t\t\t\tsuccess: true,\n\t\t\t\tdata: {\n\t\t\t\t\tsessionId: opened.sessionId,\n\t\t\t\t\tstate,\n\t\t\t\t\t...(opened.attached ? { attached: true } : {}),\n\t\t\t\t},\n\t\t\t});\n\t\t\treturn undefined;\n\t\t} catch (cause) {\n\t\t\tif (opened) {\n\t\t\t\ttry {\n\t\t\t\t\tawait this.registry.close(opened.sessionId);\n\t\t\t\t} catch {\n\t\t\t\t\t/* The open rollback has already removed the entry. */\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn error(command.id, \"open_session\", this.code(cause));\n\t\t}\n\t}\n\n\t/**\n\t * Releases every session a dropped connection still owned. Each handle goes through\n\t * the same refcounted close as an explicit close_session, so a session another\n\t * connection is still attached to keeps running and only the last owner tears it down.\n\t */\n\tasync releaseConnection(connectionId: string): Promise<void> {\n\t\tthis.releasedConnections.add(connectionId);\n\t\tthis.writer.clearConnectionCapabilities(connectionId);\n\t\tfor (const sessionId of this.sessionsByConnection.get(connectionId)?.keys() ?? [])\n\t\t\tthis.writer.detachConnectionFromSession(connectionId, sessionId);\n\t\tfor (const widths of this.widths.values()) widths.delete(connectionId);\n\t\tfor (const binding of this.bindings.values()) binding.rerenderComponents?.();\n\t\tconst opens = this.opensByConnection.get(connectionId);\n\t\tconst owned = this.sessionsByConnection.get(connectionId);\n\t\tthis.sessionsByConnection.delete(connectionId);\n\t\tif (owned === undefined) {\n\t\t\tif (opens) await Promise.all([...opens]);\n\t\t\tthis.releasedConnections.delete(connectionId);\n\t\t\treturn;\n\t\t}\n\t\tawait Promise.all(\n\t\t\t[...owned].map(async ([sessionId, count]) => {\n\t\t\t\tfor (let attachment = 0; attachment < count; attachment++) {\n\t\t\t\t\t// Headless completion contract: a turn survives its client's death and\n\t\t\t\t\t// runs to settlement (the host lifecycle keeps the process alive on\n\t\t\t\t\t// active turns even with zero connections). Releasing mid-turn aborts\n\t\t\t\t\t// the run and seals the session before agent_settled reaches the\n\t\t\t\t\t// lifecycle observer, leaking the busy counter so the host never\n\t\t\t\t\t// idle-exits. Defer - never skip - the release until the turn settles,\n\t\t\t\t\t// so the dropped owner's reservation still frees afterwards.\n\t\t\t\t\t//\n\t\t\t\t\t// A retained session is never closed by a drop, so it has nothing to defer:\n\t\t\t\t\t// release the attachment now - the client is already gone and must not keep\n\t\t\t\t\t// counting - and let the turn run to settlement on its own.\n\t\t\t\t\tconst live = this.registry.peek(sessionId);\n\t\t\t\t\tconst retained = live?.retainOnDisconnect === true;\n\t\t\t\t\tconst session = live?.state === \"open\" ? live.runtime?.session : undefined;\n\t\t\t\t\tif (!retained && live?.state === \"open\" && live.worker?.snapshot?.streaming) {\n\t\t\t\t\t\tconst unsubscribe = live.worker.subscribeSettled(() => {\n\t\t\t\t\t\t\tunsubscribe();\n\t\t\t\t\t\t\tvoid this.releaseOwnedSession(sessionId).catch((cause: unknown) => {\n\t\t\t\t\t\t\t\tprocess.stderr.write(\n\t\t\t\t\t\t\t\t\t`senpi rpc deferred worker release ${sessionId} failed: ${String(cause)}\\n`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif (!retained && session?.isStreaming) {\n\t\t\t\t\t\tlet released = false;\n\t\t\t\t\t\tconst unsubscribe = session.subscribe((event) => {\n\t\t\t\t\t\t\tif (event.type !== \"agent_settled\" && event.type !== \"agent_idle\") return;\n\t\t\t\t\t\t\tif (released) return;\n\t\t\t\t\t\t\treleased = true;\n\t\t\t\t\t\t\tunsubscribe();\n\t\t\t\t\t\t\tvoid this.releaseOwnedSession(sessionId).catch((cause) => {\n\t\t\t\t\t\t\t\tprocess.stderr.write(\n\t\t\t\t\t\t\t\t\t`senpi rpc deferred release for session ${sessionId} failed: ${String(cause)}\\n`,\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tawait this.releaseOwnedSession(sessionId);\n\t\t\t\t}\n\t\t\t}),\n\t\t);\n\t\tif (opens) await Promise.all([...opens]);\n\t\tthis.releasedConnections.delete(connectionId);\n\t}\n\n\t/**\n\t * One owned handle's refcounted close: the same sequence as an explicit\n\t * close_session, tolerant of races with other lifecycle paths (an entry\n\t * already closed or claimed elsewhere is simply skipped), except that it claims\n\t * a DETACH: a retained entry keeps running at zero attachments instead of\n\t * closing, so this path releases the client's claim without ending the session.\n\t * Disposal, pending\n\t * extension-UI cancellation and binding removal happen only when this was the\n\t * LAST attachment (the entry transitioned to \"closing\"): surviving\n\t * attachments keep the shared binding and their event stream.\n\t */\n\tprivate async releaseOwnedSession(sessionId: string): Promise<void> {\n\t\t// A failed claim means the entry is already closed or owned by another path.\n\t\t// A retained entry answers the detach by staying open: no finalizer, nothing to join.\n\t\tconst claim = this.tryClaimClose(sessionId, { drainAttachments: false, detach: true });\n\t\tif (!claim) return;\n\t\tif (!claim.finalizer) {\n\t\t\tawait this.finalizations.get(sessionId)?.promise;\n\t\t\treturn;\n\t\t}\n\t\tconst binding = this.bindings.get(sessionId);\n\t\t// Pending UI requests are session-owned, not connection-owned: a question\n\t\t// asked through one connection stays answerable by every other attachment.\n\t\t// Cancel them only here, where the refcount has already decided the session\n\t\t// is being torn down, never on any owner drop.\n\t\tbinding?.cancelPendingExtensionUiRequests?.();\n\t\tawait this.finalizeClose(sessionId, binding);\n\t}\n\n\t/**\n\t * Releases one attachment (or every attachment when draining) and reports\n\t * whether this caller became the finalizer. The join token is installed inside\n\t * the registry callback, before any await, so a close that lands between the\n\t * claim and finalizeClose() always finds a token to wait on instead of\n\t * answering ahead of the terminal records.\n\t */\n\tprivate claimClose(sessionId: string, options: CloseClaimOptions): { finalizer: boolean } {\n\t\tlet finalizer = true;\n\t\tconst onRole = (isFinalizer: boolean): void => {\n\t\t\tfinalizer = isFinalizer;\n\t\t\tif (isFinalizer && !this.finalizations.has(sessionId))\n\t\t\t\tthis.finalizations.set(sessionId, this.createFinalization());\n\t\t};\n\t\tlet entry = this.registry.beginClose(sessionId, onRole, { detach: options.detach });\n\t\twhile (options.drainAttachments && entry.state === \"open\") entry = this.registry.beginClose(sessionId, onRole);\n\t\treturn { finalizer: finalizer && entry.state === \"closing\" };\n\t}\n\n\t/** claimClose() for lifecycle paths that treat a lost race as \"nothing to do\". */\n\tprivate tryClaimClose(sessionId: string, options: CloseClaimOptions): { finalizer: boolean } | undefined {\n\t\ttry {\n\t\t\treturn this.claimClose(sessionId, options);\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t}\n\n\tprivate async close(command: Extract<RpcCommand, { type: \"close_session\" }>): Promise<RpcResponse | undefined> {\n\t\tconst response = {\n\t\t\tid: command.id,\n\t\t\ttype: \"response\" as const,\n\t\t\tcommand: \"close_session\" as const,\n\t\t\tsuccess: true as const,\n\t\t\tdata: {},\n\t\t};\n\t\t// A close releases the CALLER's attachment, and routing handles are public on a\n\t\t// shared host (`list_sessions` publishes every one of them), so ownership - not\n\t\t// knowledge of the handle - authorizes it: a connection that never attached holds\n\t\t// no attachment, and answering it would release another client's claim and could\n\t\t// tear down a session it never opened. A host with no per-connection identity\n\t\t// (stdio) has no ownership to check and keeps answering every close as before.\n\t\tconst owner = this.writer.currentConnection();\n\t\tif (owner !== undefined && this.sessionsByConnection.get(owner)?.has(command.sessionId) !== true)\n\t\t\treturn error(command.id, \"close_session\", RPC_ERROR_UNKNOWN_SESSION);\n\t\tconst reply = this.writer.reserveCloseResponse(command.sessionId, response);\n\t\tif (!reply) return undefined;\n\t\t// Admission and claiming are synchronous, before any teardown await. A\n\t\t// saturated requester neither releases an attachment nor joins a promise.\n\t\tlet claim: { finalizer: boolean };\n\t\ttry {\n\t\t\tclaim = this.claimClose(command.sessionId, { drainAttachments: false });\n\t\t} catch (cause) {\n\t\t\treply.release();\n\t\t\treturn error(command.id, \"close_session\", this.code(cause));\n\t\t}\n\t\ttry {\n\t\t\tif (owner !== undefined) this.releaseOwnerAttachment(owner, command.sessionId);\n\t\t\tif (claim.finalizer) {\n\t\t\t\tawait this.finalizeClose(command.sessionId, this.bindings.get(command.sessionId), () =>\n\t\t\t\t\treply.complete(true),\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tawait this.finalizations.get(command.sessionId)?.promise;\n\t\t\t\treply.complete(false);\n\t\t\t}\n\t\t\treturn undefined;\n\t\t} finally {\n\t\t\treply.release();\n\t\t}\n\t}\n\n\t/** Detaches the closing connection's UI/width state; a rerender failure must not abort the close. */\n\tprivate releaseOwnerAttachment(owner: string, sessionId: string): void {\n\t\tthis.widths.get(sessionId)?.delete(owner);\n\t\tthis.writer.detachConnectionFromSession(owner, sessionId);\n\t\tfor (const binding of this.bindings.values()) {\n\t\t\ttry {\n\t\t\t\tbinding.rerenderComponents?.();\n\t\t\t} catch (cause) {\n\t\t\t\tprocess.stderr.write(`senpi rpc rerender after close of session ${sessionId} failed: ${String(cause)}\\n`);\n\t\t\t}\n\t\t}\n\t\tconst owned = this.sessionsByConnection.get(owner);\n\t\tconst count = owned?.get(sessionId);\n\t\tif (!owned || count === undefined) return;\n\t\tif (count === 1) owned.delete(sessionId);\n\t\telse owned.set(sessionId, count - 1);\n\t\tif (owned.size === 0) this.sessionsByConnection.delete(owner);\n\t}\n\n\t/**\n\t * Runs the finalizer side of a close for a handle whose beginClose() made this\n\t * caller the owner: dispose the binding, complete the registry teardown, emit\n\t * the terminal records, then release joiners. Every step is guarded so the join\n\t * token always resolves and a failing binding yields one logged line, never a\n\t * second response or an escaped rejection.\n\t */\n\tprivate async finalizeClose(\n\t\tsessionId: string,\n\t\tbinding: RpcSessionBinding | undefined,\n\t\tterminal?: () => void,\n\t): Promise<void> {\n\t\tconst finalization = this.finalizations.get(sessionId) ?? this.createFinalization();\n\t\tthis.finalizations.set(sessionId, finalization);\n\t\ttry {\n\t\t\ttry {\n\t\t\t\tawait binding?.dispose();\n\t\t\t} catch (cause) {\n\t\t\t\tprocess.stderr.write(`senpi rpc binding dispose for session ${sessionId} failed: ${String(cause)}\\n`);\n\t\t\t}\n\t\t\tthis.bindings.delete(sessionId);\n\t\t\ttry {\n\t\t\t\tawait this.registry.closeMarked(sessionId);\n\t\t\t} catch (cause) {\n\t\t\t\tprocess.stderr.write(`senpi rpc close for session ${sessionId} failed: ${String(cause)}\\n`);\n\t\t\t}\n\t\t\t// closeMarked may return at the grace deadline while ownership remains;\n\t\t\t// terminal records must still observe the exit callback's registry removal.\n\t\t\tawait this.registry.peek(sessionId)?.closeCompletion;\n\t\t\tterminal?.();\n\t\t} finally {\n\t\t\tfinalization.resolve();\n\t\t\tthis.finalizations.delete(sessionId);\n\t\t}\n\t}\n\n\tprivate createFinalization(): { promise: Promise<void>; resolve: () => void } {\n\t\tlet resolveFinalization: (() => void) | undefined;\n\t\tconst promise = new Promise<void>((resolve) => {\n\t\t\tresolveFinalization = resolve;\n\t\t});\n\t\treturn { promise, resolve: () => resolveFinalization?.() };\n\t}\n\n\tprivate code(cause: unknown): string {\n\t\tif (cause instanceof RpcSessionRegistryError) {\n\t\t\treturn cause.code === RPC_ERROR_OPEN_FAILED ? cause.message : cause.code;\n\t\t}\n\t\tif (cause instanceof Error && [RPC_ERROR_UNKNOWN_SESSION, RPC_ERROR_SESSION_CLOSING].includes(cause.message)) {\n\t\t\treturn cause.message;\n\t\t}\n\t\treturn cause instanceof Error && cause.message\n\t\t\t? `${RPC_ERROR_OPEN_FAILED}: ${cause.message}`\n\t\t\t: RPC_ERROR_UNKNOWN_SESSION;\n\t}\n}\n"]}
|
|
@@ -44,6 +44,8 @@ export declare class SessionEventFanout {
|
|
|
44
44
|
/** True when no socket connection is registered, i.e. records must fall back to the stdio lane. */
|
|
45
45
|
isEmpty(): boolean;
|
|
46
46
|
broadcast(line: string): void;
|
|
47
|
+
/** Deliver one line to the connections attached to a session, never to the rest of the fanout. */
|
|
48
|
+
deliverToSession(sessionId: string, line: string): void;
|
|
47
49
|
rememberSnapshot(sessionId: string, value: Record<string, unknown>, line: string, placeholderLine?: string, source?: Record<string, unknown>): void;
|
|
48
50
|
forgetSession(sessionId: string): void;
|
|
49
51
|
private replaySnapshot;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-event-fanout.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/session-event-fanout.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"session-event-fanout.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/session-event-fanout.ts"],"names":[],"mappings":"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"}
|
|
@@ -135,6 +135,12 @@ export class SessionEventFanout {
|
|
|
135
135
|
for (const { actor } of this.connections.values())
|
|
136
136
|
actor.enqueue(line);
|
|
137
137
|
}
|
|
138
|
+
/** Deliver one line to the connections attached to a session, never to the rest of the fanout. */
|
|
139
|
+
deliverToSession(sessionId, line) {
|
|
140
|
+
for (const [id, { actor }] of this.connections)
|
|
141
|
+
if (this.connectionSessions.get(id)?.has(sessionId))
|
|
142
|
+
actor.enqueue(line);
|
|
143
|
+
}
|
|
138
144
|
rememberSnapshot(sessionId, value, line, placeholderLine, source) {
|
|
139
145
|
if (value.type === "extension_ui_request" && value.method === "question" && typeof value.id === "string") {
|
|
140
146
|
const pending = this.pendingQuestions.get(sessionId) ?? new Map();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-event-fanout.js","sourceRoot":"","sources":["../../../src/modes/rpc/session-event-fanout.ts"],"names":[],"mappings":"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","sourcesContent":["import { MEDIA_PLACEHOLDERS_CAPABILITY, RENDERED_COMPONENTS_CAPABILITY } from \"./custom-capability.ts\";\nimport { serializeJsonLine } from \"./jsonl.ts\";\nimport { omitInlineMedia } from \"./media-placeholders.ts\";\nimport { SocketEventSinkActor } from \"./socket-event-fanout.ts\";\n\nexport type RawWriter = (chunk: string) => void;\nexport type BackpressureWaiter = () => Promise<void>;\n\nexport interface SessionEventWriterConnection {\n\treadonly writeRaw: RawWriter;\n\treadonly waitForBackpressure: BackpressureWaiter;\n\t/**\n\t * Tears the transport down. Called when this connection's event queue fails\n\t * (overflow, write error): the actor has already stopped delivering records\n\t * AND command responses, so a socket left open would strand the client on a\n\t * connection that can never answer again. Closing it lets the client resync.\n\t */\n\treadonly close?: () => void;\n}\n\nexport const RENDERED_COMPONENT_RECORD = \"__senpiRenderedComponent\";\n\nconst BROADCAST_LIFECYCLE_RECORDS = new Set([\n\t\"agent_start\",\n\t\"agent_settled\",\n\t\"agent_idle\",\n\t\"session_opened\",\n\t\"session_closed\",\n]);\n\ntype RegisteredConnection = {\n\treadonly connection: SessionEventWriterConnection;\n\treadonly actor: SocketEventSinkActor;\n};\n\n/**\n * A replayable snapshot line.\n *\n * `placeholderLine` is the `media_placeholders` variant. The writer supplies it only when\n * a capable connection was already attached when the record was emitted; a connection that\n * attaches later still needs it, so `source` carries the wire record and the variant is\n * derived once, on the first capable replay, then memoized. Records with no media resolve\n * `placeholderLine` to `line`, so replay stays O(1) and never re-serializes twice.\n */\ntype SnapshotRecord = {\n\treadonly line: string;\n\tplaceholderLine?: string;\n\treadonly source?: Record<string, unknown>;\n\treadonly rendered: boolean;\n};\n\n/** The placeholder variant of a remembered record, derived and memoized on first use. */\nfunction snapshotPlaceholderLine(record: SnapshotRecord): string {\n\tif (record.placeholderLine !== undefined) return record.placeholderLine;\n\tconst redacted = record.source === undefined ? undefined : omitInlineMedia(record.source);\n\trecord.placeholderLine =\n\t\tredacted === undefined || redacted === record.source ? record.line : serializeJsonLine(redacted);\n\treturn record.placeholderLine;\n}\n\nexport class SessionEventFanout {\n\tprivate readonly connections = new Map<string, RegisteredConnection>();\n\tprivate readonly sessionSnapshots = new Map<string, SnapshotRecord[]>();\n\tprivate readonly pendingQuestions = new Map<string, Map<string, Record<string, unknown>>>();\n\tprivate readonly connectionCapabilities = new Map<string, Set<string>>();\n\tprivate readonly connectionSessions = new Map<string, Set<string>>();\n\tprivate readonly registeredCapabilityConnections = new Set<string>();\n\n\tregisterConnection(\n\t\tid: string,\n\t\tconnection: SessionEventWriterConnection,\n\t\toptions: { readonly maxQueueBytes?: number; readonly stallMs?: number } = {},\n\t): void {\n\t\tconst actor = new SocketEventSinkActor(\n\t\t\tconnection,\n\t\t\t(cause) => {\n\t\t\t\tif (this.connections.get(id)?.actor === actor) {\n\t\t\t\t\tthis.connections.delete(id);\n\t\t\t\t\tthis.connectionCapabilities.delete(id);\n\t\t\t\t\tthis.connectionSessions.delete(id);\n\t\t\t\t\tthis.registeredCapabilityConnections.delete(id);\n\t\t\t\t}\n\t\t\t\tprocess.stderr.write(\n\t\t\t\t\t`senpi rpc connection ${id} event queue failed; closing: ${cause instanceof Error ? cause.message : String(cause)}\\n`,\n\t\t\t\t);\n\t\t\t\tconnection.close?.();\n\t\t\t},\n\t\t\toptions.maxQueueBytes,\n\t\t\toptions.stallMs,\n\t\t);\n\t\tthis.connections.set(id, { connection, actor });\n\t\tthis.connectionCapabilities.set(id, new Set());\n\t\tthis.connectionSessions.set(id, new Set());\n\t}\n\n\tunregisterConnection(id: string): void {\n\t\tconst registered = this.connections.get(id);\n\t\tif (!registered) return;\n\t\tregistered.actor.close();\n\t\tthis.connections.delete(id);\n\t\tthis.connectionCapabilities.delete(id);\n\t\tthis.connectionSessions.delete(id);\n\t\tthis.registeredCapabilityConnections.delete(id);\n\t}\n\n\tattachConnectionToSession(id: string, sessionId: string): void {\n\t\tif (!this.connections.has(id)) return;\n\t\tconst sessions = this.connectionSessions.get(id) ?? new Set<string>();\n\t\tif (sessions.has(sessionId)) return;\n\t\tsessions.add(sessionId);\n\t\tthis.connectionSessions.set(id, sessions);\n\t\tthis.replaySnapshot(id, sessionId);\n\t\tfor (const frame of this.pendingQuestions.get(sessionId)?.values() ?? []) {\n\t\t\tthis.connections.get(id)?.actor.enqueue(\n\t\t\t\tserializeJsonLine({\n\t\t\t\t\t...frame,\n\t\t\t\t\tremainingMs: typeof frame.deadlineAtMs === \"number\" ? Math.max(0, frame.deadlineAtMs - Date.now()) : 0,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t}\n\n\tdetachConnectionFromSession(id: string, sessionId: string): void {\n\t\tthis.connectionSessions.get(id)?.delete(sessionId);\n\t}\n\n\tsetConnectionCapabilities(id: string, capabilities: readonly string[]): void {\n\t\tconst registered = this.connections.get(id);\n\t\tif (!registered) return;\n\t\tconst wasCapable = this.connectionCapabilities.get(id)?.has(RENDERED_COMPONENTS_CAPABILITY) ?? false;\n\t\tthis.connectionCapabilities.set(id, new Set(capabilities));\n\t\tthis.registeredCapabilityConnections.add(id);\n\t\tif (!wasCapable && capabilities.includes(RENDERED_COMPONENTS_CAPABILITY))\n\t\t\tfor (const sessionId of this.connectionSessions.get(id) ?? []) this.replayRendered(id, sessionId);\n\t}\n\n\tclearConnectionCapabilities(id: string): void {\n\t\tif (this.connections.has(id)) {\n\t\t\tthis.connectionCapabilities.set(id, new Set());\n\t\t\tthis.registeredCapabilityConnections.delete(id);\n\t\t}\n\t}\n\n\thasRegisteredConnectionCapabilities(id: string): boolean {\n\t\treturn this.registeredCapabilityConnections.has(id);\n\t}\n\n\tgetConnectionCapabilities(id: string): readonly string[] | undefined {\n\t\tif (!this.registeredCapabilityConnections.has(id)) return undefined;\n\t\treturn [...(this.connectionCapabilities.get(id) ?? [])];\n\t}\n\n\thasCapableConnection(sessionId: string): boolean {\n\t\tfor (const id of this.connectionCapabilities.keys())\n\t\t\tif (this.connectionHas(id, RENDERED_COMPONENTS_CAPABILITY) && this.connectionSessions.get(id)?.has(sessionId))\n\t\t\t\treturn true;\n\t\treturn false;\n\t}\n\n\t/** Whether a connection advertised a capability. The only capability lookup in this file. */\n\tconnectionHas(id: string | undefined, capability: string): boolean {\n\t\treturn id === undefined ? false : (this.connectionCapabilities.get(id)?.has(capability) ?? false);\n\t}\n\n\ttargets(\n\t\tsessionId: string,\n\t\ttargetId: string | undefined,\n\t\tisTargeted: boolean,\n\t\trendered: boolean,\n\t\trecordType: unknown,\n\t): readonly (string | undefined)[] {\n\t\tif (isTargeted) return [targetId];\n\t\tif (typeof recordType === \"string\" && BROADCAST_LIFECYCLE_RECORDS.has(recordType))\n\t\t\treturn this.connections.size > 0 ? [...this.connections.keys()] : [undefined];\n\t\tif (rendered)\n\t\t\treturn this.connections.size > 0\n\t\t\t\t? [...this.connections.keys()].filter(\n\t\t\t\t\t\t(id) =>\n\t\t\t\t\t\t\tthis.connectionHas(id, RENDERED_COMPONENTS_CAPABILITY) &&\n\t\t\t\t\t\t\tthis.connectionSessions.get(id)?.has(sessionId),\n\t\t\t\t\t)\n\t\t\t\t: [undefined];\n\t\treturn this.connections.size > 0\n\t\t\t? [...this.connections.keys()].filter((id) => this.connectionSessions.get(id)?.has(sessionId))\n\t\t\t: [undefined];\n\t}\n\n\tget(id: string): RegisteredConnection | undefined {\n\t\treturn this.connections.get(id);\n\t}\n\n\tvalues(): IterableIterator<RegisteredConnection> {\n\t\treturn this.connections.values();\n\t}\n\n\t/** True when no socket connection is registered, i.e. records must fall back to the stdio lane. */\n\tisEmpty(): boolean {\n\t\treturn this.connections.size === 0;\n\t}\n\n\tbroadcast(line: string): void {\n\t\tfor (const { actor } of this.connections.values()) actor.enqueue(line);\n\t}\n\n\trememberSnapshot(\n\t\tsessionId: string,\n\t\tvalue: Record<string, unknown>,\n\t\tline: string,\n\t\tplaceholderLine?: string,\n\t\tsource?: Record<string, unknown>,\n\t): void {\n\t\tif (value.type === \"extension_ui_request\" && value.method === \"question\" && typeof value.id === \"string\") {\n\t\t\tconst pending = this.pendingQuestions.get(sessionId) ?? new Map<string, Record<string, unknown>>();\n\t\t\tpending.set(value.id, { ...value });\n\t\t\tthis.pendingQuestions.set(sessionId, pending);\n\t\t\treturn;\n\t\t}\n\t\tif (value.type === \"question_resolved\" && typeof value.id === \"string\") {\n\t\t\tthis.pendingQuestions.get(sessionId)?.delete(value.id);\n\t\t\treturn;\n\t\t}\n\t\tif (value.type === \"question_updated\" && typeof value.id === \"string\") {\n\t\t\tconst frame = this.pendingQuestions.get(sessionId)?.get(value.id);\n\t\t\tif (frame) Object.assign(frame, { deadlineAtMs: value.deadlineAtMs, remainingMs: value.remainingMs });\n\t\t\treturn;\n\t\t}\n\t\tconst event = value.assistantMessageEvent as Record<string, unknown> | undefined;\n\t\tconst record: SnapshotRecord = {\n\t\t\tline,\n\t\t\tplaceholderLine,\n\t\t\tsource,\n\t\t\trendered: value[RENDERED_COMPONENT_RECORD] === true,\n\t\t};\n\t\tif (value.type === \"message_start\" || (value.type === \"message_update\" && event?.type === \"text_start\")) {\n\t\t\tthis.sessionSnapshots.set(sessionId, [record]);\n\t\t} else if (this.sessionSnapshots.has(sessionId)) {\n\t\t\tthis.sessionSnapshots.get(sessionId)?.push(record);\n\t\t}\n\t\tif (value.type === \"message_end\") this.sessionSnapshots.delete(sessionId);\n\t}\n\n\tforgetSession(sessionId: string): void {\n\t\tthis.pendingQuestions.delete(sessionId);\n\t\tthis.sessionSnapshots.delete(sessionId);\n\t}\n\n\tprivate replaySnapshot(id: string, sessionId: string): void {\n\t\tconst actor = this.connections.get(id)?.actor;\n\t\tif (!actor) return;\n\t\tconst capable = this.connectionHas(id, RENDERED_COMPONENTS_CAPABILITY);\n\t\tconst placeholders = this.connectionHas(id, MEDIA_PLACEHOLDERS_CAPABILITY);\n\t\tfor (const record of this.sessionSnapshots.get(sessionId) ?? [])\n\t\t\tif (!record.rendered || capable) actor.enqueue(placeholders ? snapshotPlaceholderLine(record) : record.line);\n\t}\n\n\tprivate replayRendered(id: string, sessionId: string): void {\n\t\tconst actor = this.connections.get(id)?.actor;\n\t\tif (!actor) return;\n\t\tfor (const record of this.sessionSnapshots.get(sessionId) ?? []) if (record.rendered) actor.enqueue(record.line);\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"session-event-fanout.js","sourceRoot":"","sources":["../../../src/modes/rpc/session-event-fanout.ts"],"names":[],"mappings":"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","sourcesContent":["import { MEDIA_PLACEHOLDERS_CAPABILITY, RENDERED_COMPONENTS_CAPABILITY } from \"./custom-capability.ts\";\nimport { serializeJsonLine } from \"./jsonl.ts\";\nimport { omitInlineMedia } from \"./media-placeholders.ts\";\nimport { SocketEventSinkActor } from \"./socket-event-fanout.ts\";\n\nexport type RawWriter = (chunk: string) => void;\nexport type BackpressureWaiter = () => Promise<void>;\n\nexport interface SessionEventWriterConnection {\n\treadonly writeRaw: RawWriter;\n\treadonly waitForBackpressure: BackpressureWaiter;\n\t/**\n\t * Tears the transport down. Called when this connection's event queue fails\n\t * (overflow, write error): the actor has already stopped delivering records\n\t * AND command responses, so a socket left open would strand the client on a\n\t * connection that can never answer again. Closing it lets the client resync.\n\t */\n\treadonly close?: () => void;\n}\n\nexport const RENDERED_COMPONENT_RECORD = \"__senpiRenderedComponent\";\n\nconst BROADCAST_LIFECYCLE_RECORDS = new Set([\n\t\"agent_start\",\n\t\"agent_settled\",\n\t\"agent_idle\",\n\t\"session_opened\",\n\t\"session_closed\",\n]);\n\ntype RegisteredConnection = {\n\treadonly connection: SessionEventWriterConnection;\n\treadonly actor: SocketEventSinkActor;\n};\n\n/**\n * A replayable snapshot line.\n *\n * `placeholderLine` is the `media_placeholders` variant. The writer supplies it only when\n * a capable connection was already attached when the record was emitted; a connection that\n * attaches later still needs it, so `source` carries the wire record and the variant is\n * derived once, on the first capable replay, then memoized. Records with no media resolve\n * `placeholderLine` to `line`, so replay stays O(1) and never re-serializes twice.\n */\ntype SnapshotRecord = {\n\treadonly line: string;\n\tplaceholderLine?: string;\n\treadonly source?: Record<string, unknown>;\n\treadonly rendered: boolean;\n};\n\n/** The placeholder variant of a remembered record, derived and memoized on first use. */\nfunction snapshotPlaceholderLine(record: SnapshotRecord): string {\n\tif (record.placeholderLine !== undefined) return record.placeholderLine;\n\tconst redacted = record.source === undefined ? undefined : omitInlineMedia(record.source);\n\trecord.placeholderLine =\n\t\tredacted === undefined || redacted === record.source ? record.line : serializeJsonLine(redacted);\n\treturn record.placeholderLine;\n}\n\nexport class SessionEventFanout {\n\tprivate readonly connections = new Map<string, RegisteredConnection>();\n\tprivate readonly sessionSnapshots = new Map<string, SnapshotRecord[]>();\n\tprivate readonly pendingQuestions = new Map<string, Map<string, Record<string, unknown>>>();\n\tprivate readonly connectionCapabilities = new Map<string, Set<string>>();\n\tprivate readonly connectionSessions = new Map<string, Set<string>>();\n\tprivate readonly registeredCapabilityConnections = new Set<string>();\n\n\tregisterConnection(\n\t\tid: string,\n\t\tconnection: SessionEventWriterConnection,\n\t\toptions: { readonly maxQueueBytes?: number; readonly stallMs?: number } = {},\n\t): void {\n\t\tconst actor = new SocketEventSinkActor(\n\t\t\tconnection,\n\t\t\t(cause) => {\n\t\t\t\tif (this.connections.get(id)?.actor === actor) {\n\t\t\t\t\tthis.connections.delete(id);\n\t\t\t\t\tthis.connectionCapabilities.delete(id);\n\t\t\t\t\tthis.connectionSessions.delete(id);\n\t\t\t\t\tthis.registeredCapabilityConnections.delete(id);\n\t\t\t\t}\n\t\t\t\tprocess.stderr.write(\n\t\t\t\t\t`senpi rpc connection ${id} event queue failed; closing: ${cause instanceof Error ? cause.message : String(cause)}\\n`,\n\t\t\t\t);\n\t\t\t\tconnection.close?.();\n\t\t\t},\n\t\t\toptions.maxQueueBytes,\n\t\t\toptions.stallMs,\n\t\t);\n\t\tthis.connections.set(id, { connection, actor });\n\t\tthis.connectionCapabilities.set(id, new Set());\n\t\tthis.connectionSessions.set(id, new Set());\n\t}\n\n\tunregisterConnection(id: string): void {\n\t\tconst registered = this.connections.get(id);\n\t\tif (!registered) return;\n\t\tregistered.actor.close();\n\t\tthis.connections.delete(id);\n\t\tthis.connectionCapabilities.delete(id);\n\t\tthis.connectionSessions.delete(id);\n\t\tthis.registeredCapabilityConnections.delete(id);\n\t}\n\n\tattachConnectionToSession(id: string, sessionId: string): void {\n\t\tif (!this.connections.has(id)) return;\n\t\tconst sessions = this.connectionSessions.get(id) ?? new Set<string>();\n\t\tif (sessions.has(sessionId)) return;\n\t\tsessions.add(sessionId);\n\t\tthis.connectionSessions.set(id, sessions);\n\t\tthis.replaySnapshot(id, sessionId);\n\t\tfor (const frame of this.pendingQuestions.get(sessionId)?.values() ?? []) {\n\t\t\tthis.connections.get(id)?.actor.enqueue(\n\t\t\t\tserializeJsonLine({\n\t\t\t\t\t...frame,\n\t\t\t\t\tremainingMs: typeof frame.deadlineAtMs === \"number\" ? Math.max(0, frame.deadlineAtMs - Date.now()) : 0,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t}\n\n\tdetachConnectionFromSession(id: string, sessionId: string): void {\n\t\tthis.connectionSessions.get(id)?.delete(sessionId);\n\t}\n\n\tsetConnectionCapabilities(id: string, capabilities: readonly string[]): void {\n\t\tconst registered = this.connections.get(id);\n\t\tif (!registered) return;\n\t\tconst wasCapable = this.connectionCapabilities.get(id)?.has(RENDERED_COMPONENTS_CAPABILITY) ?? false;\n\t\tthis.connectionCapabilities.set(id, new Set(capabilities));\n\t\tthis.registeredCapabilityConnections.add(id);\n\t\tif (!wasCapable && capabilities.includes(RENDERED_COMPONENTS_CAPABILITY))\n\t\t\tfor (const sessionId of this.connectionSessions.get(id) ?? []) this.replayRendered(id, sessionId);\n\t}\n\n\tclearConnectionCapabilities(id: string): void {\n\t\tif (this.connections.has(id)) {\n\t\t\tthis.connectionCapabilities.set(id, new Set());\n\t\t\tthis.registeredCapabilityConnections.delete(id);\n\t\t}\n\t}\n\n\thasRegisteredConnectionCapabilities(id: string): boolean {\n\t\treturn this.registeredCapabilityConnections.has(id);\n\t}\n\n\tgetConnectionCapabilities(id: string): readonly string[] | undefined {\n\t\tif (!this.registeredCapabilityConnections.has(id)) return undefined;\n\t\treturn [...(this.connectionCapabilities.get(id) ?? [])];\n\t}\n\n\thasCapableConnection(sessionId: string): boolean {\n\t\tfor (const id of this.connectionCapabilities.keys())\n\t\t\tif (this.connectionHas(id, RENDERED_COMPONENTS_CAPABILITY) && this.connectionSessions.get(id)?.has(sessionId))\n\t\t\t\treturn true;\n\t\treturn false;\n\t}\n\n\t/** Whether a connection advertised a capability. The only capability lookup in this file. */\n\tconnectionHas(id: string | undefined, capability: string): boolean {\n\t\treturn id === undefined ? false : (this.connectionCapabilities.get(id)?.has(capability) ?? false);\n\t}\n\n\ttargets(\n\t\tsessionId: string,\n\t\ttargetId: string | undefined,\n\t\tisTargeted: boolean,\n\t\trendered: boolean,\n\t\trecordType: unknown,\n\t): readonly (string | undefined)[] {\n\t\tif (isTargeted) return [targetId];\n\t\tif (typeof recordType === \"string\" && BROADCAST_LIFECYCLE_RECORDS.has(recordType))\n\t\t\treturn this.connections.size > 0 ? [...this.connections.keys()] : [undefined];\n\t\tif (rendered)\n\t\t\treturn this.connections.size > 0\n\t\t\t\t? [...this.connections.keys()].filter(\n\t\t\t\t\t\t(id) =>\n\t\t\t\t\t\t\tthis.connectionHas(id, RENDERED_COMPONENTS_CAPABILITY) &&\n\t\t\t\t\t\t\tthis.connectionSessions.get(id)?.has(sessionId),\n\t\t\t\t\t)\n\t\t\t\t: [undefined];\n\t\treturn this.connections.size > 0\n\t\t\t? [...this.connections.keys()].filter((id) => this.connectionSessions.get(id)?.has(sessionId))\n\t\t\t: [undefined];\n\t}\n\n\tget(id: string): RegisteredConnection | undefined {\n\t\treturn this.connections.get(id);\n\t}\n\n\tvalues(): IterableIterator<RegisteredConnection> {\n\t\treturn this.connections.values();\n\t}\n\n\t/** True when no socket connection is registered, i.e. records must fall back to the stdio lane. */\n\tisEmpty(): boolean {\n\t\treturn this.connections.size === 0;\n\t}\n\n\tbroadcast(line: string): void {\n\t\tfor (const { actor } of this.connections.values()) actor.enqueue(line);\n\t}\n\n\t/** Deliver one line to the connections attached to a session, never to the rest of the fanout. */\n\tdeliverToSession(sessionId: string, line: string): void {\n\t\tfor (const [id, { actor }] of this.connections)\n\t\t\tif (this.connectionSessions.get(id)?.has(sessionId)) actor.enqueue(line);\n\t}\n\n\trememberSnapshot(\n\t\tsessionId: string,\n\t\tvalue: Record<string, unknown>,\n\t\tline: string,\n\t\tplaceholderLine?: string,\n\t\tsource?: Record<string, unknown>,\n\t): void {\n\t\tif (value.type === \"extension_ui_request\" && value.method === \"question\" && typeof value.id === \"string\") {\n\t\t\tconst pending = this.pendingQuestions.get(sessionId) ?? new Map<string, Record<string, unknown>>();\n\t\t\tpending.set(value.id, { ...value });\n\t\t\tthis.pendingQuestions.set(sessionId, pending);\n\t\t\treturn;\n\t\t}\n\t\tif (value.type === \"question_resolved\" && typeof value.id === \"string\") {\n\t\t\tthis.pendingQuestions.get(sessionId)?.delete(value.id);\n\t\t\treturn;\n\t\t}\n\t\tif (value.type === \"question_updated\" && typeof value.id === \"string\") {\n\t\t\tconst frame = this.pendingQuestions.get(sessionId)?.get(value.id);\n\t\t\tif (frame) Object.assign(frame, { deadlineAtMs: value.deadlineAtMs, remainingMs: value.remainingMs });\n\t\t\treturn;\n\t\t}\n\t\tconst event = value.assistantMessageEvent as Record<string, unknown> | undefined;\n\t\tconst record: SnapshotRecord = {\n\t\t\tline,\n\t\t\tplaceholderLine,\n\t\t\tsource,\n\t\t\trendered: value[RENDERED_COMPONENT_RECORD] === true,\n\t\t};\n\t\tif (value.type === \"message_start\" || (value.type === \"message_update\" && event?.type === \"text_start\")) {\n\t\t\tthis.sessionSnapshots.set(sessionId, [record]);\n\t\t} else if (this.sessionSnapshots.has(sessionId)) {\n\t\t\tthis.sessionSnapshots.get(sessionId)?.push(record);\n\t\t}\n\t\tif (value.type === \"message_end\") this.sessionSnapshots.delete(sessionId);\n\t}\n\n\tforgetSession(sessionId: string): void {\n\t\tthis.pendingQuestions.delete(sessionId);\n\t\tthis.sessionSnapshots.delete(sessionId);\n\t}\n\n\tprivate replaySnapshot(id: string, sessionId: string): void {\n\t\tconst actor = this.connections.get(id)?.actor;\n\t\tif (!actor) return;\n\t\tconst capable = this.connectionHas(id, RENDERED_COMPONENTS_CAPABILITY);\n\t\tconst placeholders = this.connectionHas(id, MEDIA_PLACEHOLDERS_CAPABILITY);\n\t\tfor (const record of this.sessionSnapshots.get(sessionId) ?? [])\n\t\t\tif (!record.rendered || capable) actor.enqueue(placeholders ? snapshotPlaceholderLine(record) : record.line);\n\t}\n\n\tprivate replayRendered(id: string, sessionId: string): void {\n\t\tconst actor = this.connections.get(id)?.actor;\n\t\tif (!actor) return;\n\t\tfor (const record of this.sessionSnapshots.get(sessionId) ?? []) if (record.rendered) actor.enqueue(record.line);\n\t}\n}\n"]}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SessionKind } from "../../core/extensions/types.ts";
|
|
1
2
|
import { type SessionEventWriterConnection } from "./session-event-fanout.ts";
|
|
2
3
|
export { RENDERED_COMPONENT_RECORD, type SessionEventWriterConnection } from "./session-event-fanout.ts";
|
|
3
4
|
type RawWriter = (chunk: string) => void;
|
|
@@ -21,6 +22,8 @@ export declare class SessionEventWriter {
|
|
|
21
22
|
private readonly controlQueue;
|
|
22
23
|
private readonly readyQueues;
|
|
23
24
|
private readonly sealedSessions;
|
|
25
|
+
/** Sessions whose lifecycle records stay on their attached connections (`kind: "worker"`). */
|
|
26
|
+
private readonly workerSessions;
|
|
24
27
|
private readonly writeRaw;
|
|
25
28
|
private readonly waitForBackpressure?;
|
|
26
29
|
private readonly scheduleFlush;
|
|
@@ -51,6 +54,13 @@ export declare class SessionEventWriter {
|
|
|
51
54
|
hasRegisteredConnectionCapabilities(id: string): boolean;
|
|
52
55
|
getConnectionCapabilities(id: string): readonly string[] | undefined;
|
|
53
56
|
hasCapableConnection(sessionId: string): boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Records a session's visibility class. A worker session is machine-driven work that
|
|
59
|
+
* only its attached connections track, so its lifecycle records are delivered to them
|
|
60
|
+
* instead of broadcast; an interactive session keeps the broadcast every client (the
|
|
61
|
+
* desktop mirror, the supervisor's idle observer) relies on.
|
|
62
|
+
*/
|
|
63
|
+
setSessionKind(sessionId: string, kind: SessionKind): void;
|
|
54
64
|
/** Execute a connection's command with its response destination in context. */
|
|
55
65
|
withConnection<T>(id: string, task: () => T): T;
|
|
56
66
|
/** Connection id of the command currently being dispatched, when one owns it. */
|
|
@@ -72,12 +82,31 @@ export declare class SessionEventWriter {
|
|
|
72
82
|
private sessionActors;
|
|
73
83
|
/** Queue one untagged host-control response for the current connection. */
|
|
74
84
|
enqueueControl(value: object): Promise<void>;
|
|
85
|
+
/**
|
|
86
|
+
* Queue one HOST-level lifecycle record for every registered connection, or the
|
|
87
|
+
* shared stdio lane when none is registered. Unlike session records it is not tagged
|
|
88
|
+
* with a routing handle by the writer: `host_stalled` carries the handle it blames,
|
|
89
|
+
* and `host_memory_pressure` belongs to the process, not to a session.
|
|
90
|
+
*/
|
|
91
|
+
broadcastHostRecord(record: object): void;
|
|
75
92
|
/**
|
|
76
93
|
* Prevent subsequent records for a session and append its terminal response.
|
|
77
94
|
* Existing records retain FIFO order; this response is therefore that
|
|
78
95
|
* session's final stdout record.
|
|
79
96
|
*/
|
|
80
97
|
closeSession(sessionId: string, response: object): void;
|
|
98
|
+
/**
|
|
99
|
+
* Seal a session the host PARKED and publish `session_parked`.
|
|
100
|
+
*
|
|
101
|
+
* Parking is the idle sweep putting a RETAINED session back on disk: the routing
|
|
102
|
+
* handle ends exactly as a close ends it, but the session survives and reopens with
|
|
103
|
+
* `open_session { sessionPath }`, so the record a client dispatches on must say so
|
|
104
|
+
* instead of claiming the session ended. Delivery follows the `session_closed` rule -
|
|
105
|
+
* a worker session's record reaches only its attached connections, an interactive
|
|
106
|
+
* session's reaches every connection. No client asked for this teardown, so there is
|
|
107
|
+
* no close response to answer.
|
|
108
|
+
*/
|
|
109
|
+
parkSession(sessionId: string, sessionPath: string): void;
|
|
81
110
|
/**
|
|
82
111
|
* Admit reply debt before routing can mutate attachments or await finalization.
|
|
83
112
|
* Reserve the lifecycle as well: the claimant's role is not known yet. Rejected
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-event-writer.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/session-event-writer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"session-event-writer.d.ts","sourceRoot":"","sources":["../../../src/modes/rpc/session-event-writer.ts"],"names":[],"mappings":"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"}
|
|
@@ -64,6 +64,8 @@ export class SessionEventWriter {
|
|
|
64
64
|
this.controlQueue = { latestByKey: new Map(), ready: false };
|
|
65
65
|
this.readyQueues = [];
|
|
66
66
|
this.sealedSessions = new Set();
|
|
67
|
+
/** Sessions whose lifecycle records stay on their attached connections (`kind: "worker"`). */
|
|
68
|
+
this.workerSessions = new Set();
|
|
67
69
|
this.flushScheduled = false;
|
|
68
70
|
this.controlOverflowReported = false;
|
|
69
71
|
this.closeOverflowReported = false;
|
|
@@ -123,6 +125,18 @@ export class SessionEventWriter {
|
|
|
123
125
|
hasCapableConnection(sessionId) {
|
|
124
126
|
return this.fanout.hasCapableConnection(sessionId);
|
|
125
127
|
}
|
|
128
|
+
/**
|
|
129
|
+
* Records a session's visibility class. A worker session is machine-driven work that
|
|
130
|
+
* only its attached connections track, so its lifecycle records are delivered to them
|
|
131
|
+
* instead of broadcast; an interactive session keeps the broadcast every client (the
|
|
132
|
+
* desktop mirror, the supervisor's idle observer) relies on.
|
|
133
|
+
*/
|
|
134
|
+
setSessionKind(sessionId, kind) {
|
|
135
|
+
if (kind === "worker")
|
|
136
|
+
this.workerSessions.add(sessionId);
|
|
137
|
+
else
|
|
138
|
+
this.workerSessions.delete(sessionId);
|
|
139
|
+
}
|
|
126
140
|
/** Execute a connection's command with its response destination in context. */
|
|
127
141
|
withConnection(id, task) {
|
|
128
142
|
return this.connectionContext.run(id, task);
|
|
@@ -229,6 +243,21 @@ export class SessionEventWriter {
|
|
|
229
243
|
this.requestFlush();
|
|
230
244
|
return completion;
|
|
231
245
|
}
|
|
246
|
+
/**
|
|
247
|
+
* Queue one HOST-level lifecycle record for every registered connection, or the
|
|
248
|
+
* shared stdio lane when none is registered. Unlike session records it is not tagged
|
|
249
|
+
* with a routing handle by the writer: `host_stalled` carries the handle it blames,
|
|
250
|
+
* and `host_memory_pressure` belongs to the process, not to a session.
|
|
251
|
+
*/
|
|
252
|
+
broadcastHostRecord(record) {
|
|
253
|
+
if (this.fanout.isEmpty()) {
|
|
254
|
+
this.append(this.controlQueue, { ...record });
|
|
255
|
+
this.markReady(this.controlQueue);
|
|
256
|
+
}
|
|
257
|
+
else
|
|
258
|
+
this.fanout.broadcast(serializeJsonLine(record));
|
|
259
|
+
this.requestFlush();
|
|
260
|
+
}
|
|
232
261
|
/**
|
|
233
262
|
* Prevent subsequent records for a session and append its terminal response.
|
|
234
263
|
* Existing records retain FIFO order; this response is therefore that
|
|
@@ -243,6 +272,8 @@ export class SessionEventWriter {
|
|
|
243
272
|
const lifecycle = { type: "session_closed", sessionId };
|
|
244
273
|
if (this.fanout.isEmpty())
|
|
245
274
|
this.appendSessionRecord(sessionId, lifecycle);
|
|
275
|
+
else if (this.workerSessions.has(sessionId))
|
|
276
|
+
this.fanout.deliverToSession(sessionId, serializeJsonLine(lifecycle));
|
|
246
277
|
else
|
|
247
278
|
this.fanout.broadcast(serializeJsonLine(lifecycle));
|
|
248
279
|
const taggedResponse = { ...response, sessionId };
|
|
@@ -253,6 +284,31 @@ export class SessionEventWriter {
|
|
|
253
284
|
this.appendSessionRecord(sessionId, taggedResponse, targetId);
|
|
254
285
|
this.requestFlush();
|
|
255
286
|
}
|
|
287
|
+
/**
|
|
288
|
+
* Seal a session the host PARKED and publish `session_parked`.
|
|
289
|
+
*
|
|
290
|
+
* Parking is the idle sweep putting a RETAINED session back on disk: the routing
|
|
291
|
+
* handle ends exactly as a close ends it, but the session survives and reopens with
|
|
292
|
+
* `open_session { sessionPath }`, so the record a client dispatches on must say so
|
|
293
|
+
* instead of claiming the session ended. Delivery follows the `session_closed` rule -
|
|
294
|
+
* a worker session's record reaches only its attached connections, an interactive
|
|
295
|
+
* session's reaches every connection. No client asked for this teardown, so there is
|
|
296
|
+
* no close response to answer.
|
|
297
|
+
*/
|
|
298
|
+
parkSession(sessionId, sessionPath) {
|
|
299
|
+
if (this.sealedSessions.has(sessionId))
|
|
300
|
+
return;
|
|
301
|
+
this.sealedSessions.add(sessionId);
|
|
302
|
+
this.fanout.forgetSession(sessionId);
|
|
303
|
+
const lifecycle = { type: "session_parked", sessionId, sessionPath };
|
|
304
|
+
if (this.fanout.isEmpty())
|
|
305
|
+
this.appendSessionRecord(sessionId, lifecycle);
|
|
306
|
+
else if (this.workerSessions.has(sessionId))
|
|
307
|
+
this.fanout.deliverToSession(sessionId, serializeJsonLine(lifecycle));
|
|
308
|
+
else
|
|
309
|
+
this.fanout.broadcast(serializeJsonLine(lifecycle));
|
|
310
|
+
this.requestFlush();
|
|
311
|
+
}
|
|
256
312
|
/**
|
|
257
313
|
* Admit reply debt before routing can mutate attachments or await finalization.
|
|
258
314
|
* Reserve the lifecycle as well: the claimant's role is not known yet. Rejected
|
|
@@ -331,6 +387,7 @@ export class SessionEventWriter {
|
|
|
331
387
|
*/
|
|
332
388
|
forgetSession(sessionId) {
|
|
333
389
|
this.sealedSessions.delete(sessionId);
|
|
390
|
+
this.workerSessions.delete(sessionId);
|
|
334
391
|
this.fanout.forgetSession(sessionId);
|
|
335
392
|
}
|
|
336
393
|
/** Drain every retained lane and the current in-flight record. */
|