@mirasoth/soothe-client 0.4.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +39 -21
- package/dist/{chunk-U6RMINYV.js → chunk-YYUVHZ3W.js} +120 -28
- package/dist/chunk-YYUVHZ3W.js.map +1 -0
- package/dist/client-SOJZSF7C.js +7 -0
- package/dist/index.cjs +168 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +91 -41
- package/dist/index.d.ts +91 -41
- package/dist/index.js +52 -3
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-U6RMINYV.js.map +0 -1
- package/dist/client-UNPC32NQ.js +0 -7
- /package/dist/{client-UNPC32NQ.js.map → client-SOJZSF7C.js.map} +0 -0
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/verbosity.ts","../src/config.ts","../src/protocol.ts","../src/intent_hints.ts","../src/events.ts","../src/multiplexer.ts","../src/stream_terminal.ts","../src/inbound_priority.ts","../src/client.ts","../src/index.ts","../src/command_client.ts","../src/session.ts","../src/helpers.ts","../src/appkit/broadcaster.ts","../src/appkit/classifier.ts","../src/appkit/thinking_step.ts","../src/appkit/query_gate.ts","../src/appkit/pool.ts","../src/appkit/client.ts","../src/appkit/attachments.ts","../src/appkit/turn_runner.ts","../src/appkit/daemon_session.ts","../src/appkit/chunk_filter.ts","../src/appkit/events.ts","../src/appkit/observability.ts"],"sourcesContent":["/**\n * Custom error types for the Soothe client (RFC-450 protocol-1).\n */\n\n/** Represents a WebSocket connection failure. */\nexport class ConnectionError extends Error {\n readonly url: string;\n readonly attempt: number;\n readonly cause: Error;\n\n constructor(url: string, attempt: number, cause: Error) {\n super(`connection error to ${url} (attempt ${attempt}): ${cause.message}`);\n this.name = \"ConnectionError\";\n this.url = url;\n this.attempt = attempt;\n this.cause = cause;\n }\n}\n\n/**\n * Represents an error reported by the Soothe daemon (RFC-450 §7).\n *\n * The daemon's structured error object carries a numeric `code` from the\n * reserved ranges, a human-readable `message`, and optional `data`.\n */\nexport class DaemonError extends Error {\n /** Numeric error code from the RFC-450 §7.3 registry. */\n readonly code: number;\n /** The daemon's error message text. */\n readonly daemonMessage: string;\n /** Optional machine-parseable error details. */\n readonly data: unknown;\n\n constructor(code: number, message: string, data?: unknown) {\n super(`daemon error [${code}]: ${message}`);\n this.name = \"DaemonError\";\n this.code = code;\n this.daemonMessage = message;\n this.data = data;\n }\n}\n\n/** Represents a timeout waiting for a daemon response. */\nexport class TimeoutError extends Error {\n readonly operation: string;\n readonly duration: string;\n\n constructor(operation: string, duration: string) {\n super(`timeout after ${duration} waiting for ${operation}`);\n this.name = \"TimeoutError\";\n this.operation = operation;\n this.duration = duration;\n }\n}\n\n/**\n * Distinguishes clean vs unclean connection loss (RFC-450 §4, §8.3).\n *\n * A clean drop follows a `disconnect` notification (loops keep running\n * server-side); an unclean drop is a read/write error or a missed pong\n * (in-flight queries are cancelled). Pair with the Client's `'disconnected'`\n * event: the cause is emitted exactly once when the connection drops.\n */\nexport enum DisconnectCause {\n /** Abrupt loss: read/write error or missed pong (RFC-450 §8.3). */\n Unclean = 0,\n /** Graceful peer-initiated `disconnect` notification (RFC-450 §9.2). */\n Clean = 1,\n}\n\n/** Human-readable cause name for logging. */\nexport function disconnectCauseName(cause: DisconnectCause): string {\n return cause === DisconnectCause.Clean ? \"clean\" : \"unclean\";\n}\n\n/** Indicates a failed reconnection attempt sequence. */\nexport class ReconnectError extends Error {\n readonly url: string;\n readonly attempts: number;\n readonly cause: Error;\n\n constructor(url: string, attempts: number, cause: Error) {\n super(`reconnect to ${url} failed after ${attempts} attempts: ${cause.message}`);\n this.name = \"ReconnectError\";\n this.url = url;\n this.attempts = attempts;\n this.cause = cause;\n }\n}\n\n/**\n * Returned by `reattachAndProbe` when a loop accepts the reattach handshake\n * but fails the `loop_get` liveness probe. Callers should fall back to a\n * fresh `loop_new` bootstrap.\n */\nexport class StaleLoopError extends Error {\n readonly loopID: string;\n readonly cause?: Error;\n\n constructor(loopID: string, cause?: Error) {\n const detail = cause ? `: ${cause.message}` : \"\";\n super(`stale loop ${loopID}: reattach accepted but liveness probe failed${detail}`);\n this.name = \"StaleLoopError\";\n this.loopID = loopID;\n this.cause = cause;\n }\n}\n","/**\n * Verbosity levels and tiers for event filtering.\n */\n\n/** User-configurable verbosity setting. */\nexport type VerbosityLevel = \"quiet\" | \"normal\" | \"debug\";\n\n/** Minimum verbosity level at which content is visible. */\nexport enum VerbosityTier {\n /** Always visible (errors, assistant text, final reports) */\n Quiet = 0,\n /** Standard progress (plan updates, milestones, agentic loop) */\n Normal = 1,\n /** Detailed internals (protocol events, tool calls, subagent activity) */\n Detailed = 2,\n /** Everything including internals (thinking, heartbeats) */\n Debug = 3,\n /** Never shown at any level (implementation details) */\n Internal = 99,\n}\n\nconst verbosityLevelValues: Record<VerbosityLevel, number> = {\n quiet: 0,\n normal: 1,\n debug: 3,\n};\n\n/** Returns true if content at the given tier is visible at the given verbosity. */\nexport function shouldShow(tier: VerbosityTier, verbosity: VerbosityLevel): boolean {\n if (tier === VerbosityTier.Internal) {\n return false;\n }\n const level = verbosityLevelValues[verbosity] ?? 1; // default to normal\n return tier <= level;\n}\n\n/** Checks whether a string is a valid verbosity level. */\nexport function isValidVerbosityLevel(s: string): s is VerbosityLevel {\n return s in verbosityLevelValues;\n}\n","/**\n * Client configuration for connecting to the Soothe daemon.\n */\n\nimport type { VerbosityLevel } from \"./verbosity.js\";\n\nexport interface Config {\n /** WebSocket URL for Soothe daemon */\n daemonURL: string;\n /** Event verbosity: quiet/minimal/normal/detailed/debug */\n verbosityLevel: VerbosityLevel;\n /** Maximum connection retry attempts */\n maxRetries: number;\n /** Initial reconnect delay in ms */\n reconnectDelay: number;\n /** Application-level heartbeat interval in ms */\n heartbeatInterval: number;\n /** Handshake: wait for connection_ack (readiness \"ready\") in ms */\n daemonReadyTimeout: number;\n /** Bootstrap: wait for status with loop_id in ms */\n loopStatusTimeout: number;\n /** After subscribe(method:\"loop_events\"): wait for confirmation in ms */\n subscriptionTimeout: number;\n\n // Mid-session reconnect (RFC-450 §8.3 dead-connection detection).\n /** Max reconnection attempts on a mid-session drop (0 = infinite). */\n reconnectMaxAttempts: number;\n /** Initial backoff delay (ms) between reconnect attempts. */\n reconnectInitialDelay: number;\n /** Cap (ms) on exponential backoff delay between reconnect attempts. */\n reconnectMaxDelay: number;\n /** `loop_get` liveness probe timeout (ms) in reattachAndProbe. */\n reattachProbeTimeout: number;\n}\n\n/** Returns default configuration. */\nexport function defaultConfig(): Config {\n return {\n daemonURL: \"ws://localhost:8765\",\n verbosityLevel: \"normal\",\n maxRetries: 5,\n reconnectDelay: 2000,\n heartbeatInterval: 30000,\n daemonReadyTimeout: 20000,\n loopStatusTimeout: 60000,\n subscriptionTimeout: 10000,\n\n reconnectMaxAttempts: 10,\n reconnectInitialDelay: 500,\n reconnectMaxDelay: 10000,\n reattachProbeTimeout: 5000,\n };\n}\n\n/** Loads configuration from environment variables. */\nexport function loadConfigFromEnv(): Config {\n const config = defaultConfig();\n\n if (typeof process === \"undefined\") return config;\n\n const url = process.env.SOOTHE_DAEMON_URL;\n if (url) config.daemonURL = url;\n\n const verbosity = process.env.SOOTHE_VERBOSITY;\n if (verbosity) config.verbosityLevel = verbosity as VerbosityLevel;\n\n const retries = process.env.SOOTHE_MAX_RETRIES;\n if (retries) {\n const val = parseInt(retries, 10);\n if (!isNaN(val)) config.maxRetries = val;\n }\n\n const readyTimeout = process.env.SOOTHE_DAEMON_READY_TIMEOUT_SEC;\n if (readyTimeout) {\n const val = parseInt(readyTimeout, 10);\n if (val > 0) config.daemonReadyTimeout = val * 1000;\n }\n\n const statusTimeout = process.env.SOOTHE_LOOP_STATUS_TIMEOUT_SEC;\n if (statusTimeout) {\n const val = parseInt(statusTimeout, 10);\n if (val > 0) config.loopStatusTimeout = val * 1000;\n }\n\n const subTimeout = process.env.SOOTHE_SUBSCRIPTION_TIMEOUT_SEC;\n if (subTimeout) {\n const val = parseInt(subTimeout, 10);\n if (val > 0) config.subscriptionTimeout = val * 1000;\n }\n\n return config;\n}\n","/**\n * Protocol-1 wire envelope: message types, encode/decode, NDJSON splitting,\n * and factory functions for the Soothe daemon (RFC-450).\n *\n * The unified `{proto, type, method, params, id}` envelope combines\n * JSON-RPC 2.0's `method`/`params`/`id` structure with graphql-ws's `type`\n * semantics for message class distinction.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport type { LoopInputIntentHint } from \"./intent_hints.js\";\n\n/** Protocol version string (RFC-450 §8.1). */\nexport const PROTO_VERSION = \"1\";\n\n/** Default client capabilities declared in the connection_init handshake. */\nexport const DEFAULT_CLIENT_CAPABILITIES = [\"streaming\", \"batch\", \"heartbeat\", \"receipts\"];\n\n/** Client version reported in the connection_init handshake. */\nexport const CLIENT_VERSION = \"0.4.0\";\n\n// ---------------------------------------------------------------------------\n// Envelope message classes (RFC-450 §9.1)\n// ---------------------------------------------------------------------------\n\nexport type MessageType =\n | \"connection_init\"\n | \"connection_ack\"\n | \"request\"\n | \"response\"\n | \"notification\"\n | \"subscribe\"\n | \"next\"\n | \"error\"\n | \"complete\"\n | \"unsubscribe\"\n | \"ping\"\n | \"pong\"\n | \"receipt_response\"\n | \"disconnect\"\n | \"status\";\n\n/** Method names carried in the envelope `method` field (RFC-450 §9.2). */\nexport type MethodName =\n | \"loop_list\"\n | \"loop_get\"\n | \"loop_tree\"\n | \"loop_prune\"\n | \"loop_delete\"\n | \"loop_new\"\n | \"loop_reattach\"\n | \"loop_detach\"\n | \"loop_input\"\n | \"loop_messages\"\n | \"loop_state_get\"\n | \"loop_state_update\"\n | \"loop_cards_fetch\"\n | \"loop_history_fetch\"\n | \"loop_events\"\n | \"autopilot_events\"\n | \"job_create\"\n | \"job_status\"\n | \"job_pause\"\n | \"job_resume\"\n | \"job_cancel\"\n | \"job_dag\"\n | \"job_guidance\"\n | \"daemon_status\"\n | \"daemon_shutdown\"\n | \"config_get\"\n | \"config_reload\"\n | \"skills_list\"\n | \"invoke_skill\"\n | \"models_list\"\n | \"mcp_status\"\n | \"auth\"\n | \"auth_refresh\"\n | \"slash_command\"\n | \"rpc_command\"\n | \"delivery_ack\"\n | \"cron_add\"\n | \"cron_list\"\n | \"cron_show\"\n | \"cron_cancel\"\n | \"disconnect\";\n\n// ---------------------------------------------------------------------------\n// Envelope interfaces (RFC-450 §5.2)\n// ---------------------------------------------------------------------------\n\n/** Base fields shared by every protocol-1 message. */\nexport interface BaseEnvelope {\n proto: string;\n type: MessageType;\n}\n\n/** A client→server RPC request (expects a `response` correlated by `id`). */\nexport interface RequestEnvelope extends BaseEnvelope {\n type: \"request\";\n method: MethodName;\n params?: Record<string, unknown>;\n id: string;\n}\n\n/** A server→client RPC success response. */\nexport interface ResponseEnvelope extends BaseEnvelope {\n type: \"response\";\n result?: Record<string, unknown>;\n id?: string;\n}\n\n/** A fire-and-forget client→server notification (no `id`, no response). */\nexport interface NotificationEnvelope extends BaseEnvelope {\n type: \"notification\";\n method: MethodName;\n params?: Record<string, unknown>;\n /** Optional receipt id for delivery confirmation (RFC-450 §5.7). */\n receipt?: string;\n}\n\n/** Start a subscription stream (events arrive as `next`). */\nexport interface SubscribeEnvelope extends BaseEnvelope {\n type: \"subscribe\";\n method: \"loop_events\" | \"autopilot_events\";\n params?: {\n loop_id?: string;\n verbosity?: string;\n /** Stream delivery mode: batch (coalesce until turn end), adaptive (small payloads passthrough), streaming (real-time chunks). */\n stream_delivery?: \"batch\" | \"adaptive\" | \"streaming\";\n /** Wire serialization tier: full (all fields), compact (essential fields only). */\n wire_tier?: \"full\" | \"compact\";\n } & Record<string, unknown>;\n id: string;\n}\n\n/** A stream event for an active subscription. */\nexport interface NextEnvelope extends BaseEnvelope {\n type: \"next\";\n payload?: Record<string, unknown>;\n id?: string;\n}\n\n/** Structured error response (terminates the operation). */\nexport interface ErrorEnvelope extends BaseEnvelope {\n type: \"error\";\n error: { code: number; message: string; data?: unknown };\n id?: string;\n}\n\n/** Explicit stream-completion signal. */\nexport interface CompleteEnvelope extends BaseEnvelope {\n type: \"complete\";\n id?: string;\n}\n\n/** Cancel a subscription by `id`. */\nexport interface UnsubscribeEnvelope extends BaseEnvelope {\n type: \"unsubscribe\";\n id: string;\n}\n\n/** Connection handshake (client→server, first message). */\nexport interface ConnectionInitEnvelope extends BaseEnvelope {\n type: \"connection_init\";\n params?: {\n client_version: string;\n client_name?: string;\n accept_proto?: string[];\n capabilities?: string[];\n };\n}\n\n/** Connection handshake response (server→client). */\nexport interface ConnectionAckEnvelope extends BaseEnvelope {\n type: \"connection_ack\";\n result?: {\n server_version?: string;\n protocol_version?: string;\n capabilities?: string[];\n readiness_state?: string;\n heartbeat_interval_ms?: number;\n };\n}\n\n/** Heartbeat ping (either direction). */\nexport interface PingEnvelope extends BaseEnvelope {\n type: \"ping\";\n}\n\n/** Heartbeat pong response. */\nexport interface PongEnvelope extends BaseEnvelope {\n type: \"pong\";\n}\n\n/** Delivery confirmation for a notification that carried a `receipt`. */\nexport interface ReceiptResponseEnvelope extends BaseEnvelope {\n type: \"receipt_response\";\n receipt: string;\n}\n\n/** Clean connection close (daemon keeps loops running). */\nexport interface DisconnectEnvelope extends BaseEnvelope {\n type: \"disconnect\";\n}\n\n/**\n * A daemon status frame. `status` is a defined protocol-1 top-level type\n * (RFC-450 §9.1): it passes through the daemon's legacy→`next` translator\n * unchanged, so it is NOT wrapped in a `next` envelope.\n */\nexport interface StatusFrame extends BaseEnvelope {\n type: \"status\";\n state?: string;\n loop_id?: string;\n workspace?: string;\n input_history?: string[];\n conversation_history?: unknown[];\n [key: string]: unknown;\n}\n\n/** Discriminated union of all decoded protocol-1 messages. */\nexport type DecodedMessage =\n | RequestEnvelope\n | ResponseEnvelope\n | NotificationEnvelope\n | SubscribeEnvelope\n | NextEnvelope\n | ErrorEnvelope\n | CompleteEnvelope\n | UnsubscribeEnvelope\n | ConnectionInitEnvelope\n | ConnectionAckEnvelope\n | PingEnvelope\n | PongEnvelope\n | ReceiptResponseEnvelope\n | DisconnectEnvelope\n | StatusFrame\n | Record<string, unknown>;\n\n// ---------------------------------------------------------------------------\n// Typed request/notification payload interfaces (params shapes)\n// ---------------------------------------------------------------------------\n\nexport interface LoopInputParams {\n loop_id: string;\n content: string;\n autonomous?: boolean;\n max_iterations?: number;\n preferred_subagent?: string;\n /** @deprecated Ignored by daemon; loop_input always uses non-interactive autonomous mode. */\n interactive?: boolean;\n model?: string;\n model_params?: Record<string, unknown>;\n attachments?: Record<string, unknown>[];\n intent_hint?: LoopInputIntentHint;\n response_schema?: Record<string, unknown>;\n response_schema_name?: string;\n response_schema_strict?: boolean;\n clarification_mode?: string;\n clarification_answer?: boolean;\n clarification_answers?: string[];\n}\n\n/** Options for `loop_new` workspace fields. */\nexport interface LoopNewOptions {\n client_workspace?: string;\n client_workspace_id?: string;\n user_id?: string;\n is_ephemeral?: boolean;\n /** @deprecated Use `client_workspace`. */\n workspace?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Stream-event payload helpers (RFC-450 §9.3)\n// ---------------------------------------------------------------------------\n\n/**\n * Shape of a `next` payload when the daemon wraps a legacy free-form frame.\n * The original frame type becomes `mode`; `data` carries the frame body with\n * `loop_id` preserved.\n */\nexport interface StreamEventPayload {\n namespace?: unknown;\n mode?: string;\n data?: Record<string, unknown>;\n}\n\n// ---------------------------------------------------------------------------\n// Encode / Decode\n// ---------------------------------------------------------------------------\n\n/** Encodes a message as JSON with a newline delimiter (NDJSON frame). */\nexport function encodeMessage(msg: unknown): string {\n return JSON.stringify(msg) + \"\\n\";\n}\n\n/**\n * Decodes a JSON message and returns a typed object. Unknown types return a\n * raw map. The decoder is permissive: it accepts protocol-1 envelopes and\n * surfaces `response.result` / `next.payload` for consumers that read them,\n * but always returns the full envelope so callers can inspect `type`/`id`.\n */\nexport function decodeMessage(data: string): DecodedMessage | null {\n if (!data || data.length === 0) return null;\n\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(data);\n } catch {\n throw new Error(`invalid JSON: ${data}`);\n }\n\n if (!parsed || typeof parsed !== \"object\") return parsed;\n\n const type = parsed.type as MessageType | undefined;\n if (!type) return parsed;\n\n switch (type) {\n case \"connection_init\":\n return { ...parsed } as unknown as ConnectionInitEnvelope;\n case \"connection_ack\":\n return { ...parsed } as unknown as ConnectionAckEnvelope;\n case \"request\":\n return { ...parsed } as unknown as RequestEnvelope;\n case \"response\":\n return { ...parsed } as unknown as ResponseEnvelope;\n case \"notification\":\n return { ...parsed } as unknown as NotificationEnvelope;\n case \"subscribe\":\n return { ...parsed } as unknown as SubscribeEnvelope;\n case \"next\":\n return { ...parsed } as unknown as NextEnvelope;\n case \"error\":\n return { ...parsed } as unknown as ErrorEnvelope;\n case \"complete\":\n return { ...parsed } as unknown as CompleteEnvelope;\n case \"unsubscribe\":\n return { ...parsed } as unknown as UnsubscribeEnvelope;\n case \"ping\":\n return { ...parsed } as unknown as PingEnvelope;\n case \"pong\":\n return { ...parsed } as unknown as PongEnvelope;\n case \"receipt_response\":\n return { ...parsed } as unknown as ReceiptResponseEnvelope;\n case \"disconnect\":\n return { ...parsed } as unknown as DisconnectEnvelope;\n case \"status\":\n return { ...parsed } as unknown as StatusFrame;\n default:\n return parsed;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Envelope factory helpers (RFC-450 §5)\n// ---------------------------------------------------------------------------\n\n/** Builds a `request` envelope. */\nexport function requestEnvelope(\n method: MethodName,\n params?: Record<string, unknown>,\n id?: string,\n): RequestEnvelope {\n return {\n proto: PROTO_VERSION,\n type: \"request\",\n method,\n params,\n id: id ?? newRequestID(),\n };\n}\n\n/** Builds a `notification` envelope (no `id`). */\nexport function notificationEnvelope(\n method: MethodName,\n params?: Record<string, unknown>,\n): NotificationEnvelope {\n return { proto: PROTO_VERSION, type: \"notification\", method, params };\n}\n\n/** Builds a `subscribe` envelope. */\nexport function subscribeEnvelope(\n method: \"loop_events\" | \"autopilot_events\",\n params?: Record<string, unknown>,\n id?: string,\n): SubscribeEnvelope {\n return {\n proto: PROTO_VERSION,\n type: \"subscribe\",\n method,\n params,\n id: id ?? newRequestID(),\n };\n}\n\n/** Builds an `unsubscribe` envelope. */\nexport function unsubscribeEnvelope(id: string): UnsubscribeEnvelope {\n return { proto: PROTO_VERSION, type: \"unsubscribe\", id };\n}\n\n/** Builds a `connection_init` handshake envelope. */\nexport function connectionInitEnvelope(opts?: {\n client_version?: string;\n client_name?: string;\n accept_proto?: string[];\n capabilities?: string[];\n}): ConnectionInitEnvelope {\n return {\n proto: PROTO_VERSION,\n type: \"connection_init\",\n params: {\n client_version: opts?.client_version ?? CLIENT_VERSION,\n client_name: opts?.client_name ?? \"soothe-client-ts\",\n accept_proto: opts?.accept_proto ?? [PROTO_VERSION],\n capabilities: opts?.capabilities ?? DEFAULT_CLIENT_CAPABILITIES,\n },\n };\n}\n\n/** Builds a `ping` heartbeat envelope. */\nexport function pingEnvelope(): PingEnvelope {\n return { proto: PROTO_VERSION, type: \"ping\" };\n}\n\n/** Builds a `pong` heartbeat envelope. */\nexport function pongEnvelope(): PongEnvelope {\n return { proto: PROTO_VERSION, type: \"pong\" };\n}\n\n/** Builds a `disconnect` notification envelope. */\nexport function disconnectEnvelope(): DisconnectEnvelope {\n return { proto: PROTO_VERSION, type: \"disconnect\" };\n}\n\n// ---------------------------------------------------------------------------\n// NDJSON splitting\n// ---------------------------------------------------------------------------\n\n/** Splits a single WebSocket text payload into individual JSON lines. */\nexport function splitWirePayload(data: string): string[] {\n const trimmed = data.trim();\n if (trimmed === \"\") return [];\n\n const lines = trimmed\n .split(\"\\n\")\n .map(l => l.trim())\n .filter(l => l !== \"\");\n return lines.length > 0 ? lines : [data];\n}\n\n// ---------------------------------------------------------------------------\n// Event/loop extraction helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Returns the StrangeLoop id when present in a message.\n *\n * Under protocol-1, loop-scoped stream events arrive as `next` envelopes\n * whose `payload.data` carries the original frame (with `loop_id`). Raw\n * `status` frames carry `loop_id` at the top level. This helper inspects\n * both shapes.\n */\nexport function extractSootheLoopID(msg: unknown): [string, boolean] {\n if (!msg || typeof msg !== \"object\") return [\"\", false];\n const m = msg as Record<string, unknown>;\n\n // `next` envelope: dig into payload.data.loop_id.\n if (m.type === \"next\") {\n const payload = m.payload as Record<string, unknown> | undefined;\n if (payload && typeof payload === \"object\") {\n const data = payload.data as Record<string, unknown> | undefined;\n if (data && typeof data === \"object\") {\n const id = data.loop_id as string | undefined;\n if (id && id !== \"\") return [id, true];\n }\n // Some payloads carry loop_id directly.\n const pid = payload.loop_id as string | undefined;\n if (pid && pid !== \"\") return [pid, true];\n }\n return [\"\", false];\n }\n\n if (m.type === \"status\") {\n const id = m.loop_id as string | undefined;\n if (id && id !== \"\") return [id, true];\n return [\"\", false];\n }\n\n // Generic fallback: top-level loop_id.\n const generic = m.loop_id as string | undefined;\n if (generic && generic !== \"\") return [generic, true];\n\n return [\"\", false];\n}\n// ---------------------------------------------------------------------------\n// Message factory functions\n// ---------------------------------------------------------------------------\n\n/** Generates a new UUID correlation ID (RFC-450 §5.2 `id`). */\nexport function newRequestID(): string {\n return randomUUID();\n}\n\n/** Creates a `loop_input` notification envelope. */\nexport function newLoopInputMessage(loopID: string, content: string): NotificationEnvelope {\n return notificationEnvelope(\"loop_input\", {\n loop_id: loopID,\n content,\n autonomous: false,\n });\n}\n\n/** Creates a `loop_new` request envelope. */\nexport function newLoopNewMessage(opts?: LoopNewOptions | string): RequestEnvelope {\n const options: LoopNewOptions =\n typeof opts === \"string\" ? { client_workspace: opts } : (opts ?? {});\n const clientWorkspace = options.client_workspace ?? options.workspace;\n const params: Record<string, unknown> = {};\n if (clientWorkspace?.trim()) {\n params.client_workspace = clientWorkspace.trim();\n }\n if (options.user_id?.trim()) {\n params.user_id = options.user_id.trim();\n }\n if (options.client_workspace_id?.trim()) {\n params.client_workspace_id = options.client_workspace_id.trim();\n }\n if (options.is_ephemeral) {\n params.is_ephemeral = true;\n }\n return requestEnvelope(\"loop_new\", params);\n}\n\n/** Creates a `loop_events` subscribe envelope. */\nexport function newLoopSubscribeMessage(\n loopID: string,\n verbosity: string,\n streamDelivery?: \"batch\" | \"adaptive\" | \"streaming\",\n): SubscribeEnvelope {\n const params: Record<string, unknown> = { loop_id: loopID, verbosity };\n if (streamDelivery) {\n params.stream_delivery = streamDelivery;\n }\n return subscribeEnvelope(\"loop_events\", params);\n}\n","/**\n * Daemon ``loop_input`` intent_hint values (direct model turns, no agent graph).\n */\n\n/** Text-only chat completion via the configured ``default`` role. */\nexport const INTENT_HINT_TEXT_COMPLETION = \"text_completion\" as const;\n\n/** Vision / image understanding via the configured ``image`` role (attachments required). */\nexport const INTENT_HINT_IMAGE_TO_TEXT = \"image_to_text\" as const;\n\n/** OCR via the configured ``ocr`` role (attachments required). */\nexport const INTENT_HINT_OCR = \"ocr\" as const;\n\n/** Embedding via the configured ``embedding`` role (text-only; JSON vector response). */\nexport const INTENT_HINT_EMBED = \"embed\" as const;\n\n/** Supported daemon direct-model intent hints. */\nexport type IntentHint =\n | typeof INTENT_HINT_TEXT_COMPLETION\n | typeof INTENT_HINT_IMAGE_TO_TEXT\n | typeof INTENT_HINT_OCR\n | typeof INTENT_HINT_EMBED;\n\n/** Legacy intent_hint values removed from the daemon wire contract. */\nexport const REMOVED_INTENT_HINTS = [\"direct_llm\", \"quiz\"] as const;\n\nexport type RemovedIntentHint = (typeof REMOVED_INTENT_HINTS)[number];\n\nconst REMOVED_INTENT_HINT_MESSAGES: Record<RemovedIntentHint, string> = {\n direct_llm:\n \"intent_hint direct_llm is removed; use text_completion (text-only) or image_to_text (with attachments)\",\n quiz: \"intent_hint quiz is removed; omit intent_hint and let intake classify the turn\",\n};\n\n/**\n * Wire ``loop_input.intent_hint``: direct model hints or agent-path pass-through\n * (e.g. ``resume_clarification``, ``skill:foo``). Legacy ``direct_llm`` and\n * ``quiz`` are rejected before send.\n */\nexport type LoopInputIntentHint = IntentHint | (string & {});\n\n/** Returns an error message when ``hint`` is a removed legacy value; otherwise null. */\nexport function validateLoopInputIntentHint(hint: string): string | null {\n const key = hint.trim().toLowerCase();\n if (key === \"direct_llm\" || key === \"quiz\") {\n return REMOVED_INTENT_HINT_MESSAGES[key];\n }\n return null;\n}\n\n/** Phases emitted on ``mode=messages`` for user-visible loop assistant output. */\nexport const LOOP_ASSISTANT_OUTPUT_PHASES = [\n \"goal_completion\",\n \"quiz\",\n \"autonomous_goal\",\n \"direct_model\",\n \"text_completion\",\n \"image_to_text\",\n \"ocr\",\n \"embed\",\n \"plan_direct\",\n] as const;\n\nexport type LoopAssistantOutputPhase = (typeof LOOP_ASSISTANT_OUTPUT_PHASES)[number];\n\n/** Default deliverable phases for triarch-style apps (direct hints + agent outputs). */\nexport const DEFAULT_DELIVERABLE_PHASES: ReadonlySet<string> = new Set([\n \"quiz\",\n \"goal_completion\",\n \"direct_model\",\n \"text_completion\",\n \"image_to_text\",\n \"ocr\",\n \"embed\",\n]);\n","/**\n * Client-facing event namespace constants for the Soothe daemon wire protocol.\n *\n * Internal catalog types (`soothe.internal.*`) are server-only and are never\n * broadcast to WebSocket clients. Do not add them here.\n *\n * Format: soothe.<domain>.<component>.<action>\n */\n\nimport { VerbosityTier } from \"./verbosity.js\";\n\n// Plan events (client UX)\nexport const EventPlanCreated = \"soothe.cognition.plan.created\";\n\n// Explore subagent events (built-in wire, IG-339)\nexport const EventExploreStarted = \"soothe.subagent.explore.started\";\nexport const EventExploreMilestone = \"soothe.subagent.explore.milestone\";\nexport const EventExploreStepCompleted = \"soothe.subagent.explore.step.completed\";\nexport const EventExploreCompleted = \"soothe.subagent.explore.completed\";\n\n// Tacitus subagent events (built-in wire, IG-339)\nexport const EventTacitusStarted = \"soothe.subagent.tacitus.started\";\nexport const EventTacitusGatherSummary = \"soothe.subagent.tacitus.gather.summary\";\nexport const EventTacitusCompleted = \"soothe.subagent.tacitus.completed\";\n\n// Control-plane wire envelopes (not soothe.* catalog events)\nexport const EventReplayComplete = \"replay_complete\";\nexport const EventLoopReattachedWire = \"loop_reattached\";\n\n// Card ledger replay frames (RFC-413, card_binder design)\nexport const EventCardReplayBegin = \"card.replay_begin\";\nexport const EventCardCreated = \"card.created\";\nexport const EventCardReplayEnd = \"card.replay_end\";\n\n// Tool events\nexport const EventToolStarted = \"soothe.tool.execution.started\";\nexport const EventToolCompleted = \"soothe.tool.execution.completed\";\nexport const EventToolError = \"soothe.tool.execution.error\";\n\n// Stream tool call events (RFC-450, IG-416)\nexport const EventStreamToolCallUpdate = \"soothe.stream.tool_call.update\";\nexport const EventToolCallUpdatesBatch = \"tool_call_updates_batch\";\n\n// StrangeLoop events (cognition domain)\nexport const EventStrangeLoopStarted = \"soothe.cognition.strange_loop.started\";\nexport const EventStrangeLoopCompleted = \"soothe.cognition.strange_loop.completed\";\nexport const EventStrangeLoopPlanDecision = \"soothe.cognition.strange_loop.plan.decision\";\nexport const EventStrangeLoopReasoned = \"soothe.cognition.strange_loop.reasoned\";\nexport const EventStrangeLoopStepStarted = \"soothe.cognition.strange_loop.step.started\";\nexport const EventStrangeLoopStepQueued = \"soothe.cognition.strange_loop.step.queued\";\nexport const EventStrangeLoopStepCompleted = \"soothe.cognition.strange_loop.step.completed\";\nexport const EventStrangeLoopContextCompacted = \"soothe.cognition.strange_loop.context.compacted\";\n\n// Message protocol events (client stream metadata)\nexport const EventMessageReceived = \"soothe.protocol.message.received\";\nexport const EventMessageSent = \"soothe.protocol.message.sent\";\n\n// Output events\nexport const EventFinalReport = \"soothe.output.autonomous.final_report.reported\";\n\n// Autopilot events (RFC-228)\nexport const EventAutopilotGoalStatus = \"soothe.autopilot.goal.status\";\nexport const EventAutopilotGoalProgress = \"soothe.autopilot.goal.progress\";\nexport const EventAutopilotGoalCreated = \"soothe.autopilot.goal.created\";\nexport const EventAutopilotGoalCompleted = \"soothe.autopilot.goal.completed\";\nexport const EventAutopilotWorkerAssigned = \"soothe.autopilot.worker.assigned\";\nexport const EventAutopilotWorkerUnassigned = \"soothe.autopilot.worker.unassigned\";\n\n// Error events\nexport const EventGeneralFailed = \"soothe.error.general.failed\";\n\n// ---------------------------------------------------------------------------\n// Namespace parsing\n// ---------------------------------------------------------------------------\n\n/** Splits a 4-segment event namespace into domain, component, and action. */\nexport function parseNamespace(\n ns: string,\n): { domain: string; component: string; action: string } | null {\n const parts = splitNamespace(ns);\n if (parts.length < 4 || parts[0] !== \"soothe\") {\n return null;\n }\n if (parts[1] === \"internal\") {\n return null;\n }\n return { domain: parts[1], component: parts[2], action: parts[3] };\n}\n\nfunction splitNamespace(ns: string): string[] {\n const parts: string[] = [];\n let start = 0;\n for (let i = 0; i < ns.length; i++) {\n if (ns[i] === \".\") {\n parts.push(ns.slice(start, i));\n start = i + 1;\n }\n }\n parts.push(ns.slice(start));\n return parts;\n}\n\n// ---------------------------------------------------------------------------\n// Classification\n// ---------------------------------------------------------------------------\n\n/** Returns the VerbosityTier for a given event type string. */\nexport function classifyEventVerbosity(eventTypeOrNamespace: string): VerbosityTier {\n const parsed = parseNamespace(eventTypeOrNamespace);\n if (!parsed) {\n return classifyByEventTypeString(eventTypeOrNamespace);\n }\n return classifyByDomainAndComponent(parsed.domain, parsed.component, eventTypeOrNamespace);\n}\n\nfunction classifyByDomainAndComponent(\n domain: string,\n _component: string,\n full: string,\n): VerbosityTier {\n switch (domain) {\n case \"cognition\":\n return VerbosityTier.Normal;\n case \"protocol\":\n return VerbosityTier.Detailed;\n case \"tool\":\n return VerbosityTier.Internal;\n case \"subagent\":\n return classifySubagentEvent(full);\n case \"autopilot\":\n return VerbosityTier.Normal;\n case \"output\":\n case \"error\":\n return VerbosityTier.Quiet;\n default:\n return VerbosityTier.Normal;\n }\n}\n\nfunction classifySubagentEvent(full: string): VerbosityTier {\n const parsed = parseNamespace(full);\n if (!parsed) return VerbosityTier.Normal;\n switch (parsed.action) {\n case \"started\":\n case \"completed\":\n return VerbosityTier.Normal;\n default:\n return VerbosityTier.Detailed;\n }\n}\n\nfunction classifyByEventTypeString(eventType: string): VerbosityTier {\n if (eventType === EventFinalReport || eventType === EventGeneralFailed) {\n return VerbosityTier.Quiet;\n }\n if (eventType === EventToolStarted) {\n return VerbosityTier.Internal;\n }\n return VerbosityTier.Normal;\n}\n\n// ---------------------------------------------------------------------------\n// Event classification helpers\n// ---------------------------------------------------------------------------\n\n/** Event types that represent completion milestones. */\nexport function isCompletionEvent(eventType: string): boolean {\n return (\n eventType.endsWith(\".completed\") ||\n eventType.endsWith(\".failed\") ||\n eventType === EventGeneralFailed\n );\n}\n\n/** Lifecycle subagent events (started/completed) for progress UI. */\nexport function isSubagentProgressEvent(eventType: string): boolean {\n const parsed = parseNamespace(eventType);\n if (!parsed || parsed.domain !== \"subagent\") {\n return false;\n }\n return parsed.action === \"started\" || parsed.action === \"completed\";\n}\n","/**\n * Inbound-frame multiplexer for the protocol-1 client (RFC-629 constraint #1,\n * RFC-450 §5.2/§5.5).\n *\n * Routes inbound protocol-1 frames to the correct waiter by `(type, id)`\n * instead of discarding non-matching events. This makes the Client safe for\n * concurrent RPCs and lets an active subscription stream coexist with RPC\n * waits without starvation.\n *\n * Routing rules:\n * - `response`/`error` with `id` in pending RPCs → pending RPC waiter\n * - `next`/`complete` with `id` in pending subs → pending subscription waiter\n * - `receipt_response` with `receipt` in receipts → receipt waiter\n * - everything else → not consumed (flows to\n * the application event\n * stream / resolver queue)\n *\n * `ping`/`pong`/`connection_ack` are id-less lifecycle frames handled by the\n * Client before reaching the multiplexer; the multiplexer leaves them\n * un-consumed so the Client's existing handlers still see them.\n *\n * A frame routed to a waiter is consumed (returns `true`) and must NOT be\n * forwarded to the resolver queue / event stream.\n */\n\nimport { DaemonError } from \"./errors.js\";\n\n/** A single in-flight RPC wait. */\ninterface PendingCall {\n /** Resolve with the `result` object on `response`; reject with DaemonError on `error`. */\n resolve: (result: Record<string, unknown>) => void;\n reject: (err: Error) => void;\n}\n\n/** A single in-flight subscription stream. */\ninterface PendingSubscription {\n /** Push `next`/`complete` frames to the subscriber. */\n push: (frame: Record<string, unknown>) => void;\n /** Resolves when the waiter has gone away (unsubscribed/timed out). */\n done: Promise<void>;\n /** Internal — resolves `done`. */\n resolveDone: () => void;\n /** Whether the waiter is still registered. */\n settled: boolean;\n}\n\n/**\n * Multiplexer holds pending RPC, subscription, and receipt waiters keyed by\n * their correlation id. The Client consults `route()` for each inbound frame\n * before pushing it to the resolver queue.\n */\nexport class Multiplexer {\n private rpcs = new Map<string, PendingCall>();\n private subs = new Map<string, PendingSubscription>();\n private receipts = new Map<string, (frame: Record<string, unknown>) => void>();\n\n /**\n * Installs a pending RPC wait keyed by `id`. Returns the pending call and an\n * unregister function that MUST be called when the wait ends (success,\n * timeout, or cancel) to avoid leaks. If a late response arrives after the\n * caller has unregistered, it is dropped (log-and-drop) — no leak.\n */\n registerRPC(id: string): {\n call: Promise<Record<string, unknown>>;\n unregister: () => void;\n } {\n let callResolve!: (result: Record<string, unknown>) => void;\n let callReject!: (err: Error) => void;\n const call = new Promise<Record<string, unknown>>((resolve, reject) => {\n callResolve = resolve;\n callReject = reject;\n });\n const pending: PendingCall = { resolve: callResolve, reject: callReject };\n this.rpcs.set(id, pending);\n const unregister = () => {\n // Only delete if still our entry (a later registration with the same id\n // should not be clobbered).\n if (this.rpcs.get(id) === pending) {\n this.rpcs.delete(id);\n }\n };\n return { call, unregister };\n }\n\n /**\n * Installs a pending subscription stream keyed by `id`. Returns the stream\n * channel (an async-iterable-like push sink), a `done` signal, and an\n * unregister function. The Client pushes `next`/`complete` frames via\n * `push`; the application reads from the channel.\n */\n registerSubscription(id: string): {\n push: (frame: Record<string, unknown>) => void;\n done: Promise<void>;\n unregister: () => void;\n } {\n let resolveDone!: () => void;\n const done = new Promise<void>(resolve => {\n resolveDone = resolve;\n });\n const pending: PendingSubscription = {\n push: () => {\n // Overridden by the caller via the returned push closure below.\n },\n done,\n resolveDone,\n settled: false,\n };\n // Wire the push closure to the subscription's push so unregister can\n // short-circuit later deliveries.\n const push = (frame: Record<string, unknown>) => {\n if (pending.settled) return;\n pending.push(frame);\n };\n // Default push is a no-op until the caller installs a real sink. The\n // Client wires a real sink after registering; this guards against a race\n // where a frame arrives between register and sink-install.\n pending.push = () => {};\n this.subs.set(id, pending);\n const unregister = () => {\n if (this.subs.get(id) === pending) {\n pending.settled = true;\n this.subs.delete(id);\n resolveDone();\n }\n };\n return { push, done, unregister };\n }\n\n /**\n * Installs a pending receipt wait keyed by `receipt`. Returns an unregister\n * function.\n */\n registerReceipt(receipt: string): {\n wait: Promise<Record<string, unknown>>;\n unregister: () => void;\n } {\n let resolveWait!: (frame: Record<string, unknown>) => void;\n const wait = new Promise<Record<string, unknown>>(resolve => {\n resolveWait = resolve;\n });\n this.receipts.set(receipt, resolveWait);\n const unregister = () => {\n this.receipts.delete(receipt);\n };\n return { wait, unregister };\n }\n\n /**\n * Wires a real sink for a registered subscription's `push`. Called by the\n * Client right after `registerSubscription` to install the channel/queue the\n * application reads from.\n */\n setSubscriptionSink(id: string, sink: (frame: Record<string, unknown>) => void): void {\n const sub = this.subs.get(id);\n if (sub) sub.push = sink;\n }\n\n /**\n * Inspects one decoded frame, delivers it to a matching waiter if one\n * exists, and returns `true` (consumed). Returns `false` for frames with no\n * matching waiter — these flow on to the resolver queue / event stream.\n * Safe to call from the message handler.\n */\n route(frame: Record<string, unknown>): boolean {\n if (!frame || typeof frame !== \"object\") return false;\n const typ = frame.type as string | undefined;\n const id = frame.id as string | undefined;\n\n if (typ === \"response\" || typ === \"error\") {\n if (!id) return false;\n const pc = this.rpcs.get(id);\n if (!pc) return false;\n if (typ === \"error\") {\n const errObj =\n (frame.error as {\n code?: number;\n message?: string;\n data?: unknown;\n }) ?? {};\n const code = typeof errObj.code === \"number\" ? errObj.code : -32603;\n const message = errObj.message ?? \"daemon error\";\n pc.reject(new DaemonError(code, message, errObj.data));\n } else {\n const result = (frame.result as Record<string, unknown> | undefined) ?? frame;\n pc.resolve(result);\n }\n // Waiter is single-shot; remove so a duplicate late frame is dropped.\n this.rpcs.delete(id);\n return true;\n }\n\n if (typ === \"next\" || typ === \"complete\") {\n if (!id) return false;\n const ps = this.subs.get(id);\n if (!ps) return false;\n if (ps.settled) return true; // waiter gone; consume to avoid re-forwarding\n ps.push(frame);\n return true;\n }\n\n if (typ === \"receipt_response\") {\n const rid = frame.receipt as string | undefined;\n if (!rid) return false;\n const ch = this.receipts.get(rid);\n if (!ch) return false;\n ch(frame);\n this.receipts.delete(rid);\n return true;\n }\n\n return false;\n }\n\n /** Reports whether an RPC waiter is registered for `id`. */\n hasRPCWaiter(id: string): boolean {\n return this.rpcs.has(id);\n }\n}\n","/**\n * Shared stream/turn terminal frame helpers for Client and DaemonSession.\n *\n * Keeps peel-at-turn-start and turn-end detection on one vocabulary so leftover\n * prior-goal terminals cannot blank the next query.\n */\n\nimport {\n EventCardCreated,\n EventCardReplayBegin,\n EventCardReplayEnd,\n EventPlanCreated,\n EventStrangeLoopCompleted,\n EventStrangeLoopStepCompleted,\n EventStrangeLoopStepQueued,\n EventStrangeLoopStepStarted,\n} from \"./events.js\";\n\n/** Daemon turn-scoped stream end custom type. */\nexport const STREAM_END = \"soothe.stream.end\";\n\nexport const TURN_END_CUSTOM_TYPES: ReadonlySet<string> = new Set([\n STREAM_END,\n EventStrangeLoopCompleted,\n]);\n\nconst TURN_PROGRESS_CUSTOM_TYPES: ReadonlySet<string> = new Set([\n EventPlanCreated,\n EventStrangeLoopStepStarted,\n EventStrangeLoopStepQueued,\n EventStrangeLoopStepCompleted,\n]);\n\n/** Handshake / card-replay / subscription leftovers safe to drop at turn start. */\nexport const STALE_TURN_PENDING_TYPES: ReadonlySet<string> = new Set([\n \"connection_ack\",\n EventCardReplayBegin,\n EventCardReplayEnd,\n EventCardCreated,\n \"complete\",\n]);\n\n/** True when `data` is a turn-scoped terminal custom payload. */\nexport function isTurnEndCustomData(data: unknown): data is Record<string, unknown> {\n if (!data || typeof data !== \"object\") return false;\n const customType = String((data as Record<string, unknown>).type ?? \"\").trim();\n if (!TURN_END_CUSTOM_TYPES.has(customType)) return false;\n if (customType === STREAM_END) {\n const scope = String((data as Record<string, unknown>).scope ?? \"turn\")\n .trim()\n .toLowerCase();\n return scope === \"\" || scope === \"turn\";\n }\n return true;\n}\n\n/**\n * True when a chunk proves the active turn has non-intake progress.\n * Used so late prior-goal stream.end cannot close a turn that has only seen\n * intake lifecycle (e.g. plan.phase).\n */\nexport function isTurnProgressChunk(mode: string, data: unknown): boolean {\n if (mode === \"messages\" || mode === \"updates\") return true;\n if (mode !== \"custom\" || !data || typeof data !== \"object\") return false;\n if (isTurnEndCustomData(data)) return false;\n const customType = String((data as Record<string, unknown>).type ?? \"\").trim();\n if (TURN_PROGRESS_CUSTOM_TYPES.has(customType)) return true;\n if (customType.startsWith(\"soothe.cognition.strange_loop.step\")) return true;\n return false;\n}\n\n/** Return a peel label when `event` is safe to drop at turn start. */\nexport function stalePendingFrameLabel(event: Record<string, unknown>): string | null {\n const eventType = String(event.type ?? \"\");\n if (STALE_TURN_PENDING_TYPES.has(eventType)) return eventType;\n\n if (eventType === \"next\") {\n const payload = event.payload;\n if (!payload || typeof payload !== \"object\") return null;\n const p = payload as Record<string, unknown>;\n const staleMode = String(p.mode ?? \"\");\n if (STALE_TURN_PENDING_TYPES.has(staleMode)) return staleMode;\n const inner = p.data;\n if (inner && typeof inner === \"object\") {\n return stalePendingFrameLabel(inner as Record<string, unknown>);\n }\n return null;\n }\n\n if (eventType === \"event\") {\n const mode = String(event.mode ?? \"\");\n const data = event.data;\n if (mode === \"custom\" && isTurnEndCustomData(data)) {\n return String((data as Record<string, unknown>).type ?? \"\").trim();\n }\n }\n return null;\n}\n\n/** True when the client should bump delivery_ack sequence for this frame. */\nexport function inboundNeedsDeliveryAck(event: Record<string, unknown>): boolean {\n const eventType = String(event.type ?? \"\");\n if (eventType === \"complete\") return true;\n if (eventType === \"next\") {\n const payload = event.payload;\n if (!payload || typeof payload !== \"object\") return false;\n const p = payload as Record<string, unknown>;\n const inner = p.data;\n if (!inner || typeof inner !== \"object\") return false;\n if (String(p.mode ?? \"\") === \"event\") {\n return inboundNeedsAckFromEventShape(inner as Record<string, unknown>);\n }\n return false;\n }\n if (eventType === \"event\") return inboundNeedsAckFromEventShape(event);\n return false;\n}\n\nfunction inboundNeedsAckFromEventShape(event: Record<string, unknown>): boolean {\n const mode = String(event.mode ?? \"\");\n const data = event.data;\n if (mode === \"custom\" && isTurnEndCustomData(data)) return true;\n if (mode === \"messages\" && Array.isArray(data) && data.length > 0) {\n const body = data[0];\n if (!body || typeof body !== \"object\") return false;\n const t = String((body as Record<string, unknown>).type ?? \"\");\n return t === STREAM_END || t.includes(\"stream.end\");\n }\n return false;\n}\n\n/** Extract loop_id from a frame or nested next payload. */\nexport function extractLoopIdFromInbound(event: Record<string, unknown>): string {\n const direct = String(event.loop_id ?? \"\").trim();\n if (direct) return direct;\n if (String(event.type ?? \"\") !== \"next\") return \"\";\n const payload = event.payload;\n if (!payload || typeof payload !== \"object\") return \"\";\n const p = payload as Record<string, unknown>;\n const fromPayload = String(p.loop_id ?? \"\").trim();\n if (fromPayload) return fromPayload;\n const inner = p.data;\n if (inner && typeof inner === \"object\") {\n return String((inner as Record<string, unknown>).loop_id ?? \"\").trim();\n }\n return \"\";\n}\n","/**\n * Inbound drop priorities (lower = keep). Python WebSocketClient parity.\n */\n\nimport { STREAM_END, isTurnEndCustomData } from \"./stream_terminal.js\";\n\nexport const DROP_PRIORITY_CRITICAL = 0;\nexport const DROP_PRIORITY_HIGH = 1;\nexport const DROP_PRIORITY_NORMAL = 2;\n\n/** Pending / messageBuffer cap (Python inbound queue parity). */\nexport const DEFAULT_INBOUND_MAX_SIZE = 20_000;\n\n/** Return drop priority for an inbound frame. */\nexport function inboundFrameDropPriority(event: Record<string, unknown> | null | undefined): number {\n if (!event) return DROP_PRIORITY_CRITICAL;\n let eventType = String(event.type ?? \"\");\n if (eventType === \"event_batch\" || eventType === \"tool_call_updates_batch\") {\n return DROP_PRIORITY_HIGH;\n }\n if (eventType === \"next\") {\n const payload = event.payload;\n if (payload && typeof payload === \"object\") {\n const p = payload as Record<string, unknown>;\n const innerMode = String(p.mode ?? \"\");\n const innerData = p.data;\n if (innerMode === \"messages\") {\n if (messagesWireTerminal(innerData)) return DROP_PRIORITY_CRITICAL;\n if (Array.isArray(innerData) && innerData[0] && typeof innerData[0] === \"object\") {\n if (String((innerData[0] as Record<string, unknown>).phase ?? \"\") === \"goal_completion\") {\n return DROP_PRIORITY_CRITICAL;\n }\n }\n }\n if (String(p.type ?? \"\") === \"complete\") return DROP_PRIORITY_CRITICAL;\n if (innerData && typeof innerData === \"object\") {\n return inboundFrameDropPriority(innerData as Record<string, unknown>);\n }\n eventType = String(p.type ?? \"\");\n }\n }\n if (eventType === \"complete\" || eventType === \"error\" || eventType === \"connection_ack\") {\n return DROP_PRIORITY_CRITICAL;\n }\n if (eventType === \"status\") {\n const state = String(event.state ?? \"\");\n if ([\"idle\", \"running\", \"stopped\", \"detached\"].includes(state)) {\n return DROP_PRIORITY_CRITICAL;\n }\n }\n if (eventType === \"event\") {\n const mode = String(event.mode ?? \"\");\n const data = event.data;\n if (mode === \"custom\") {\n if (isTurnEndCustomData(data)) return DROP_PRIORITY_CRITICAL;\n if (data && typeof data === \"object\") {\n const customType = String((data as Record<string, unknown>).type ?? \"\");\n if (customType.startsWith(\"soothe.cognition.\")) return DROP_PRIORITY_HIGH;\n if (customType.startsWith(\"soothe.error.\") || customType === \"stream_degraded\") {\n return DROP_PRIORITY_CRITICAL;\n }\n if (customType === \"soothe.ux.stream_tool_wire.tool_call_updates_batch\") {\n return DROP_PRIORITY_HIGH;\n }\n }\n }\n if (mode === \"messages\") {\n if (messagesWireTerminal(data)) return DROP_PRIORITY_CRITICAL;\n if (Array.isArray(data) && data[0] && typeof data[0] === \"object\") {\n if (String((data[0] as Record<string, unknown>).phase ?? \"\") === \"goal_completion\") {\n return DROP_PRIORITY_CRITICAL;\n }\n }\n }\n }\n return DROP_PRIORITY_NORMAL;\n}\n\nfunction messagesWireTerminal(data: unknown): boolean {\n if (!Array.isArray(data) || data.length === 0) return false;\n const body = data[0];\n if (!body || typeof body !== \"object\") return false;\n const t = String((body as Record<string, unknown>).type ?? \"\");\n return t === STREAM_END || t.includes(\"stream.end\");\n}\n","/**\n * Client manages a WebSocket session with the Soothe daemon (RFC-450 protocol-1).\n *\n * After close(), a new Client must be created to reconnect. The connection\n * begins with a bidirectional connection_init/connection_ack handshake; no\n * requests are accepted until the daemon reports readiness_state \"ready\".\n */\n\nimport { EventEmitter } from \"node:events\";\nimport WebSocket from \"ws\";\nimport type { Config } from \"./config.js\";\nimport { defaultConfig } from \"./config.js\";\nimport { DaemonError, DisconnectCause, ReconnectError, StaleLoopError } from \"./errors.js\";\nimport { Multiplexer } from \"./multiplexer.js\";\nimport type { LoopInputIntentHint } from \"./intent_hints.js\";\nimport { validateLoopInputIntentHint } from \"./intent_hints.js\";\nimport { extractLoopIdFromInbound, inboundNeedsDeliveryAck, stalePendingFrameLabel } from \"./stream_terminal.js\";\nimport {\n DEFAULT_INBOUND_MAX_SIZE,\n DROP_PRIORITY_NORMAL,\n inboundFrameDropPriority,\n} from \"./inbound_priority.js\";\nimport {\n CLIENT_VERSION,\n DEFAULT_CLIENT_CAPABILITIES,\n PROTO_VERSION,\n connectionInitEnvelope,\n decodeMessage,\n disconnectEnvelope,\n newLoopNewMessage,\n newRequestID,\n notificationEnvelope,\n pingEnvelope,\n pongEnvelope,\n requestEnvelope,\n splitWirePayload,\n subscribeEnvelope,\n unsubscribeEnvelope,\n type ConnectionAckEnvelope,\n type DecodedMessage,\n type LoopNewOptions,\n type MethodName,\n} from \"./protocol.js\";\n\n/** Input options for `sendInput` (loop_input). */\nexport interface InputOptions {\n /** Subscribed StrangeLoop id (required for loop_input). */\n loopID?: string;\n autonomous?: boolean;\n maxIterations?: number;\n subagent?: string;\n /** @deprecated Ignored by daemon; loop_input always uses non-interactive autonomous mode. */\n interactive?: boolean;\n model?: string;\n modelParams?: Record<string, unknown>;\n attachments?: Record<string, unknown>[];\n /** Daemon direct-model hint or agent-path pass-through (resume_clarification, skill:foo). */\n intentHint?: LoopInputIntentHint;\n /** JSON Schema for structured output (text_completion or image_to_text). */\n responseSchema?: Record<string, unknown>;\n /** Provider schema name for structured output. */\n responseSchemaName?: string;\n /** Strict mode for JSON schema (default true). */\n responseSchemaStrict?: boolean;\n /** Clarification relay mode (\"auto\" / \"manual\"). */\n clarificationMode?: string;\n /** Treat this input as answer to pending clarification interrupt. */\n clarificationAnswer?: boolean;\n /** Per-question answers for multi-question clarifications. */\n clarificationAnswers?: string[];\n}\n\n/** Capability set negotiated with the daemon. */\nexport type NegotiatedCapabilities = ReadonlySet<string>;\n\nexport class Client extends EventEmitter {\n private url: string;\n private config: Config;\n private ws: WebSocket | null = null;\n private messageBuffer: DecodedMessage[] = [];\n private inboundMaxSize = DEFAULT_INBOUND_MAX_SIZE;\n private inboundDroppedCount = 0;\n private onStreamDegraded: ((dropped: number, reason: string) => void) | null = null;\n private resolvers: Array<(value: DecodedMessage | null) => void> = [];\n // Protocol-1 handshake state (RFC-450 §8.2)\n private handshakeComplete = false;\n private negotiatedCapabilities: NegotiatedCapabilities = new Set();\n private protocolVersion: string | null = null;\n private readinessState: string | null = null;\n private heartbeatIntervalMs = 0;\n private heartbeatTimer: NodeJS.Timeout | null = null;\n private lastPongMonotonic = 0;\n // Mid-session drop signal (RFC-450 §8.3). The 'disconnected' event is\n // emitted exactly once when the connection drops, carrying a DisconnectCause\n // that distinguishes clean (peer `disconnect`) from unclean (read/write\n // error or missed pong). `disconnFired` guards the once-only delivery.\n private disconnFired = false;\n // Pending-request/subscription multiplexer (RFC-629 constraint #1). Routes\n // inbound frames by (type, id) instead of discarding non-matching events.\n private mux = new Multiplexer();\n private deliveryRecvSeq = new Map<string, number>();\n private deliveryAckedSeq = new Map<string, number>();\n\n constructor(url: string, config?: Config) {\n super();\n this.url = url;\n this.config = config ?? defaultConfig();\n }\n\n // ---------------------------------------------------------------------------\n // Connection lifecycle\n // ---------------------------------------------------------------------------\n\n /**\n * Dials the Soothe daemon WebSocket and completes the protocol-1 handshake\n * (connection_init → connection_ack with readiness_state \"ready\").\n */\n connect(): Promise<void> {\n return new Promise((resolve, reject) => {\n const ws = new WebSocket(this.url, {\n handshakeTimeout: 10_000,\n });\n\n ws.on(\"open\", () => {\n this.ws = ws;\n // Reset the drop signal and multiplexer for a fresh connection so\n // reconnect() on the same Client starts with a clean slate.\n this.disconnFired = false;\n this._lastCause = null;\n this.mux = new Multiplexer();\n // Kick off the protocol-1 handshake; resolve connect() once ready.\n this._performHandshake()\n .then(ack => {\n this.handshakeComplete = true;\n this.readinessState = ack.result?.readiness_state ?? \"ready\";\n this._startHeartbeat();\n resolve();\n })\n .catch(err => {\n // Handshake failed — tear down the underlying socket so server\n // close() does not hang on a lingering connection.\n this._stopHeartbeat();\n this.ws = null;\n this.handshakeComplete = false;\n try {\n ws.close(1011, \"handshake failed\");\n } catch {\n // ignore\n }\n reject(err);\n });\n });\n\n ws.on(\"error\", err => {\n // A write/read error indicates a broken connection — signal an unclean\n // drop so consumers (e.g. ConnectionPool) can reconnect + reattach.\n // Idempotent if the close handler already fired.\n this._signalDisconnect(DisconnectCause.Unclean);\n if (!this.ws) {\n reject(new Error(`soothe dial: ${err.message}`));\n }\n });\n\n ws.on(\"message\", (data: WebSocket.RawData) => {\n const text = data.toString();\n for (const frame of splitWirePayload(text)) {\n let msg: DecodedMessage | null;\n try {\n msg = decodeMessage(frame);\n } catch {\n continue;\n }\n if (msg === null) continue;\n\n // Intercept heartbeat frames (RFC-450 §8.3).\n const m = msg as Record<string, unknown>;\n if (m.type === \"ping\") {\n this._sendRaw(pongEnvelope());\n continue;\n }\n if (m.type === \"pong\") {\n this.lastPongMonotonic = Date.now();\n continue;\n }\n // A `disconnect` notification is a clean peer-initiated drop\n // (RFC-450 §9.2); loops keep running server-side.\n if (m.type === \"disconnect\") {\n this._signalDisconnect(DisconnectCause.Clean);\n // Still surface it to listeners (existing behavior) before close.\n }\n\n // Route solicited frames (response/error/next/complete/receipt with\n // a matching pending multiplexer waiter) to their waiters; do not\n // forward to the resolver queue (RFC-629 constraint #1).\n if (this.mux.route(m)) {\n this._trackInboundDeliveryAck(m);\n continue;\n }\n\n this._trackInboundDeliveryAck(m);\n\n // If a reader is waiting, deliver directly; otherwise buffer for\n // later readEvent/receiveMessages calls. Never do both — a single\n // inbound frame must be consumed exactly once.\n const resolver = this.resolvers.shift();\n if (resolver) {\n resolver(msg);\n } else {\n this.enqueueMessageBuffer(msg);\n }\n this.emit(\"message\", msg);\n }\n });\n\n ws.on(\"close\", () => {\n this.ws = null;\n this._stopHeartbeat();\n this.handshakeComplete = false;\n // Signal an unclean drop (a close without a `disconnect` notification\n // is an abrupt loss). Idempotent if a clean signal already fired.\n this._signalDisconnect(DisconnectCause.Unclean);\n this.emit(\"close\");\n // Resolve any pending readEvent calls with null.\n for (const resolver of this.resolvers) {\n resolver(null);\n }\n this.resolvers = [];\n });\n });\n }\n\n /** Sends a `disconnect` notification and closes the WebSocket. */\n close(): void {\n this._stopHeartbeat();\n if (!this.ws) return;\n try {\n // Best-effort clean disconnect (daemon keeps loops running).\n if (this.ws.readyState === WebSocket.OPEN) {\n this.ws.send(JSON.stringify(disconnectEnvelope()));\n }\n this.ws.close(1000, \"\");\n } catch {\n // ignore close errors\n }\n this.ws = null;\n this.handshakeComplete = false;\n }\n\n /** Returns whether the client has an active, handshaked WebSocket connection. */\n isConnected(): boolean {\n return this.ws !== null && this.ws.readyState === WebSocket.OPEN && this.handshakeComplete;\n }\n\n // ---------------------------------------------------------------------------\n // Mid-session drop signal + reconnect/reattach (RFC-450 §8.3, RFC-629 L0)\n // ---------------------------------------------------------------------------\n\n /**\n * Returns whether the connection has dropped (the `'disconnected'` event has\n * fired). Pair with the `'disconnected'` event for the signal. Use\n * `disconnectCause()` to read the cause.\n */\n isDisconnected(): boolean {\n return this.disconnFired;\n }\n\n /**\n * Returns the cause of the most recent drop, or `null` if the connection has\n * not dropped. Clean follows a `disconnect` notification (loops keep running\n * server-side); unclean is a read/write error or missed pong.\n */\n disconnectCause(): DisconnectCause | null {\n if (!this.disconnFired) return null;\n return this._lastCause ?? DisconnectCause.Unclean;\n }\n\n private _lastCause: DisconnectCause | null = null;\n\n /**\n * Delivers the disconnect cause exactly once via the `'disconnected'` event.\n * Safe to call from any path; subsequent calls are no-ops. Listeners receive\n * the cause as the event argument.\n */\n private _signalDisconnect(cause: DisconnectCause): void {\n if (this.disconnFired) return;\n this.disconnFired = true;\n this._lastCause = cause;\n // Emit synchronously so a listener wired during the same message-handler\n // tick receives it. Callers that attach a listener after the drop can poll\n // isDisconnected()/disconnectCause() instead — mirroring Go's closed\n // buffered channel, which unblocks late readers immediately.\n try {\n this.emit(\"disconnected\", cause);\n } catch {\n // Listener errors must not propagate into the read loop.\n }\n }\n\n /**\n * Re-dials the daemon and re-handshakes after a connection drop (RFC-450\n * §8.3). Does not re-establish loop subscriptions; follow with\n * `reattachAndProbe()` to resume a loop session. The caller should invoke\n * this after the `'disconnected'` event fires. Reuses the same Client,\n * resetting the drop signal and multiplexer.\n *\n * Performs bounded-retry backoff using the configured reconnect knobs.\n */\n async reconnect(): Promise<void> {\n const maxAttempts = this.config.reconnectMaxAttempts || 10;\n const initialDelay = this.config.reconnectInitialDelay || 500;\n const maxDelay = this.config.reconnectMaxDelay || 10_000;\n\n let lastErr: Error | null = null;\n let delay = initialDelay;\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n // connect() resets disconnFired / mux and performs the\n // connection_init/connection_ack handshake with readiness retry.\n await this.connect();\n return;\n } catch (err) {\n lastErr = err as Error;\n }\n if (attempt < maxAttempts) {\n await new Promise(resolve => setTimeout(resolve, delay));\n delay = Math.min(delay * 2, maxDelay);\n }\n }\n throw new ReconnectError(this.url, maxAttempts, lastErr ?? new Error(\"unknown error\"));\n }\n\n /**\n * Resumes an existing loop after a reconnect: issues `loop_reattach`,\n * re-subscribes to `loop_events`, then runs a `loop_get` liveness probe to\n * detect stale loops that accept the handshake but silently drop input.\n * Returns a `StaleLoopError` when the probe fails; callers should fall back\n * to a fresh `loop_new` bootstrap.\n *\n * Per RFC-629: connection-level readiness is the handshake's readiness_state\n * (+ daemon_status); loop_get is a loop-scoped probe only, not a readiness\n * probe.\n */\n async reattachAndProbe(loopID: string): Promise<void> {\n if (!loopID || !loopID.trim()) {\n throw new Error(\"soothe: reattachAndProbe requires a loop id\");\n }\n const lid = loopID.trim();\n\n // 1. loop_reattach (RFC-450 §9.2): reconstruct event history and replay.\n const reattachTimeout = this.config.loopStatusTimeout || 15_000;\n try {\n await this.requestResponse(\n \"loop_reattach\" as unknown as MethodName,\n { loop_id: lid },\n \"loop_reattach\",\n reattachTimeout,\n );\n } catch (err) {\n throw new Error(`loop_reattach: ${(err as Error).message}`);\n }\n\n // 2. Re-subscribe to the loop event stream (RFC-450 §9.4: subscribe +\n // method:\"loop_events\"). Confirmation arrives as a `next` frame.\n const subTimeout = this.config.subscriptionTimeout || 10_000;\n try {\n await this.subscribe(\n \"loop_events\",\n { loop_id: lid, verbosity: this.config.verbosityLevel },\n subTimeout,\n );\n } catch (err) {\n throw new Error(`loop events subscription failed: ${(err as Error).message}`);\n }\n\n // 3. loop_get liveness probe — side-effect-free read (RFC-450 §9.2).\n // A LOOP_NOT_FOUND (-32200) or timeout means the loop is stale: it\n // accepted the reattach handshake but is not actually live.\n const probeTimeout = this.config.reattachProbeTimeout || 5_000;\n try {\n await this.getLoop(lid, probeTimeout);\n } catch (err) {\n if (err instanceof DaemonError && err.code === -32200) {\n throw new StaleLoopError(lid, err);\n }\n // Timeout or other error during probe → treat as stale.\n throw new StaleLoopError(lid, err as Error);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Protocol-1 handshake (RFC-450 §8.2)\n // ---------------------------------------------------------------------------\n\n /** Send connection_init and wait for connection_ack with readiness \"ready\". */\n private async _performHandshake(): Promise<ConnectionAckEnvelope> {\n const init = connectionInitEnvelope({\n client_version: CLIENT_VERSION,\n client_name: \"soothe-client-ts\",\n accept_proto: [PROTO_VERSION],\n capabilities: DEFAULT_CLIENT_CAPABILITIES,\n });\n await this.sendMessage(init);\n\n const deadline = Date.now() + this.config.daemonReadyTimeout;\n while (Date.now() < deadline) {\n const remaining = deadline - Date.now();\n if (remaining <= 0) break;\n const ev = (await this.readEventWithTimeout(remaining)) as Record<string, unknown> | null;\n if (ev === null) {\n throw new Error(\"connection closed during handshake\");\n }\n // Discard the initial `status` frame; keep other frames for later.\n if (ev.type === \"status\") {\n continue;\n }\n if (ev.type !== \"connection_ack\") {\n continue;\n }\n const ack = ev as unknown as ConnectionAckEnvelope;\n const result = ack.result ?? {};\n const state = result.readiness_state ?? \"ready\";\n this.protocolVersion = result.protocol_version ?? PROTO_VERSION;\n this.negotiatedCapabilities = new Set(result.capabilities ?? []);\n this.heartbeatIntervalMs = result.heartbeat_interval_ms ?? 0;\n\n if (state === \"incompatible\") {\n throw new Error(`protocol version incompatible: daemon returned ${this.protocolVersion}`);\n }\n if (state === \"ready\") {\n return ack;\n }\n if (state === \"error\") {\n throw new Error(\"daemon startup failed\");\n }\n if (state === \"degraded\") {\n throw new Error(\"daemon is degraded\");\n }\n // starting / warming — bounded retry by re-sending connection_init.\n await this._sleep(50);\n await this.sendMessage(init);\n }\n throw new Error(`timeout after ${this.config.daemonReadyTimeout}ms waiting for connection_ack`);\n }\n\n // ---------------------------------------------------------------------------\n // Heartbeat (RFC-450 §8.3)\n // ---------------------------------------------------------------------------\n\n private _startHeartbeat(): void {\n if (!this.negotiatedCapabilities.has(\"heartbeat\")) return;\n const interval = this.heartbeatIntervalMs;\n if (interval <= 0) return;\n this.lastPongMonotonic = Date.now();\n this.heartbeatTimer = setInterval(() => this._heartbeatTick(interval), interval);\n }\n\n private _stopHeartbeat(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n }\n\n private _heartbeatTick(intervalMs: number): void {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;\n const timeoutMs = Math.max(10_000, intervalMs * 2);\n const now = Date.now();\n if (now - (this.lastPongMonotonic || now) > intervalMs + timeoutMs) {\n // Dead connection (missed pong, RFC-450 §8.3) — signal an unclean drop\n // and force close so consumers can reconnect + reattach.\n this._signalDisconnect(DisconnectCause.Unclean);\n try {\n this.ws.close(1001, \"heartbeat timeout\");\n } catch {\n // ignore\n }\n return;\n }\n try {\n this.ws.send(JSON.stringify(pingEnvelope()));\n } catch {\n // ignore transient send failures\n }\n }\n\n private _sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n\n // ---------------------------------------------------------------------------\n // Core messaging\n // ---------------------------------------------------------------------------\n\n /** Serializes msg as JSON and sends it as a WebSocket text frame. */\n sendMessage(msg: unknown): Promise<void> {\n return new Promise((resolve, reject) => {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n reject(new Error(\"soothe: not connected\"));\n return;\n }\n const payload = JSON.stringify(msg);\n this.ws.send(payload, err => {\n if (err) {\n // Write failure indicates a broken connection — signal an unclean\n // drop so consumers can reconnect. Idempotent if the read loop\n // already fired.\n this._signalDisconnect(DisconnectCause.Unclean);\n reject(err);\n } else {\n resolve();\n }\n });\n });\n }\n\n /** Low-level send that does not reject on a missing connection (best-effort). */\n private _sendRaw(msg: unknown): void {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;\n try {\n this.ws.send(JSON.stringify(msg));\n } catch {\n // ignore\n }\n }\n\n /** Returns an async iterable of decoded messages. Ends when connection closes. */\n async *receiveMessages(signal?: AbortSignal): AsyncGenerator<DecodedMessage> {\n while (true) {\n if (signal?.aborted) return;\n\n // Drain buffer first.\n while (this.messageBuffer.length > 0) {\n const msg = this.messageBuffer.shift()!;\n yield msg;\n }\n\n // Wait for next message or close.\n const msg = await new Promise<DecodedMessage | null>(resolve => {\n if (!this.ws) {\n resolve(null);\n return;\n }\n this.resolvers.push(resolve);\n });\n\n if (msg === null) return;\n yield msg;\n }\n }\n\n /** Reads a single event from the daemon. Returns null on connection close. */\n async readEvent(): Promise<Record<string, unknown> | null> {\n if (this.messageBuffer.length > 0) {\n const msg = this.messageBuffer.shift()!;\n return msg as Record<string, unknown>;\n }\n if (!this.ws) return null;\n const msg = await new Promise<DecodedMessage | null>(resolve => {\n this.resolvers.push(resolve);\n });\n if (msg === null) return null;\n return msg as Record<string, unknown>;\n }\n\n /** Reads a single event with a timeout. Returns null on timeout or close. */\n readEventWithTimeout(timeout: number): Promise<Record<string, unknown> | null> {\n if (this.messageBuffer.length > 0) {\n const msg = this.messageBuffer.shift()!;\n return Promise.resolve(msg as Record<string, unknown>);\n }\n if (!this.ws) return Promise.resolve(null);\n\n return new Promise<Record<string, unknown> | null>(resolve => {\n const timer = setTimeout(() => {\n const idx = this.resolvers.indexOf(resolver);\n if (idx >= 0) this.resolvers.splice(idx, 1);\n resolve(null);\n }, timeout);\n\n const resolver = (val: DecodedMessage | null) => {\n clearTimeout(timer);\n resolve(val as Record<string, unknown> | null);\n };\n\n this.resolvers.push(resolver);\n });\n }\n\n /**\n * Remove stale handshake/terminal frames left in `messageBuffer` before a turn.\n * Returns labels of removed frames (in order).\n */\n peelStalePendingControlEvents(): string[] {\n if (this.messageBuffer.length === 0) return [];\n const kept: DecodedMessage[] = [];\n const removed: string[] = [];\n while (this.messageBuffer.length > 0) {\n const event = this.messageBuffer.shift()! as Record<string, unknown>;\n const label = stalePendingFrameLabel(event);\n if (label !== null) {\n removed.push(label);\n continue;\n }\n kept.push(event as DecodedMessage);\n }\n this.messageBuffer = kept;\n return removed;\n }\n\n /** True when the underlying socket is still open (may not be handshaked). */\n isConnectionAlive(): boolean {\n return this.ws !== null && this.ws.readyState === WebSocket.OPEN;\n }\n\n /** Override pending buffer cap (tests / tuning). */\n setInboundMaxSize(n: number): void {\n if (n > 0) this.inboundMaxSize = n;\n }\n\n /** How many NORMAL-priority frames were dropped under backpressure. */\n inboundDropped(): number {\n return this.inboundDroppedCount;\n }\n\n /** Hook invoked on the first inbound overflow drop. */\n setStreamDegradedCallback(fn: ((dropped: number, reason: string) => void) | null): void {\n this.onStreamDegraded = fn;\n }\n\n private enqueueMessageBuffer(msg: DecodedMessage): void {\n const max = this.inboundMaxSize > 0 ? this.inboundMaxSize : DEFAULT_INBOUND_MAX_SIZE;\n if (this.messageBuffer.length < max) {\n this.messageBuffer.push(msg);\n return;\n }\n const ev = msg as Record<string, unknown>;\n let dropIdx = -1;\n let dropPri = -1;\n for (let i = 0; i < this.messageBuffer.length; i++) {\n const p = inboundFrameDropPriority(this.messageBuffer[i] as Record<string, unknown>);\n if (p > dropPri) {\n dropPri = p;\n dropIdx = i;\n }\n }\n const incomingPri = inboundFrameDropPriority(ev);\n if (dropIdx >= 0 && dropPri >= DROP_PRIORITY_NORMAL) {\n this.messageBuffer.splice(dropIdx, 1);\n this.messageBuffer.push(msg);\n this.noteInboundDrop();\n return;\n }\n if (incomingPri >= DROP_PRIORITY_NORMAL) {\n this.noteInboundDrop();\n return;\n }\n if (this.messageBuffer.length > 0) {\n this.messageBuffer.shift();\n this.noteInboundDrop();\n }\n this.messageBuffer.push(msg);\n }\n\n private noteInboundDrop(): void {\n this.inboundDroppedCount += 1;\n if (this.onStreamDegraded && this.inboundDroppedCount === 1) {\n try {\n this.onStreamDegraded(1, \"inbound_queue_overflow\");\n } catch {\n // ignore callback errors\n }\n }\n }\n\n // ---------------------------------------------------------------------------\n // Protocol-1 RPC primitives (RFC-450 §5/§9)\n // ---------------------------------------------------------------------------\n\n /**\n * Reads the next frame directly from the live socket (via a resolver),\n * bypassing `messageBuffer`. Used by RPC waits so that stream events\n * previously buffered for `readEvent()`/`receiveMessages()` consumers are\n * not re-cycled through the RPC wait loop (which would stall behind a\n * continuous subscription stream). Non-RPC frames read here are pushed to\n * `messageBuffer` for the stream readers.\n */\n private readLiveEventWithTimeout(timeout: number): Promise<Record<string, unknown> | null> {\n if (!this.ws) return Promise.resolve(null);\n return new Promise<Record<string, unknown> | null>(resolve => {\n const timer = setTimeout(() => {\n const idx = this.resolvers.indexOf(resolver);\n if (idx >= 0) this.resolvers.splice(idx, 1);\n resolve(null);\n }, timeout);\n\n const resolver = (val: DecodedMessage | null) => {\n clearTimeout(timer);\n resolve(val as Record<string, unknown> | null);\n };\n\n this.resolvers.push(resolver);\n });\n }\n\n /**\n * Sends a `request` envelope and waits for the matching `response` (or\n * `error`) correlated by `id` (RFC-450 §5/§9). Returns the `result` object.\n *\n * Multiplexer-aware (RFC-629 constraint #1): registers a pending RPC wait\n * keyed by the request id so that, even when a `receiveMessages()` reader\n * is concurrently active, the matching `response`/`error` is routed to\n * this caller instead of being discarded or buffered behind a stream.\n * Non-matching frames are routed to their own waiters by the multiplexer\n * or flow on to the resolver queue for stream readers.\n */\n async requestResponse(\n method: MethodName,\n params: Record<string, unknown>,\n responseType?: string,\n timeout: number = 15_000,\n ): Promise<Record<string, unknown>> {\n const req = requestEnvelope(method, params);\n const rid = req.id;\n // Register the RPC waiter BEFORE sending so a fast echo response is not\n // routed before the waiter exists (RFC-629 constraint #1 ordering).\n const { call, unregister } = this.mux.registerRPC(rid);\n const label = responseType ?? method;\n try {\n await this.sendMessage(req);\n const result = await this._raceRPC(call, timeout, label);\n return result;\n } finally {\n unregister();\n }\n }\n\n /**\n * Races the multiplexer's RPC promise against a timeout and the connection\n * drop signal. Resolves with the `result` on `response`; rejects with a\n * `DaemonError` on `error`; rejects with a timeout/close error otherwise.\n * The disconnect listener is always removed to avoid accumulating handlers.\n */\n private async _raceRPC(\n call: Promise<Record<string, unknown>>,\n timeout: number,\n label: string,\n ): Promise<Record<string, unknown>> {\n let timer: NodeJS.Timeout | undefined;\n let cleanupDisconnect: () => void = () => {};\n const timeoutP = new Promise<never>((_, reject) => {\n timer = setTimeout(\n () => reject(new Error(`timeout after ${timeout}ms waiting for ${label}`)),\n timeout,\n );\n });\n const closedP = new Promise<never>((_, reject) => {\n if (this.disconnFired) {\n reject(new Error(`connection closed waiting for ${label}`));\n return;\n }\n const onDisconnect = () => {\n reject(new Error(`connection closed waiting for ${label}`));\n };\n this.once(\"disconnected\", onDisconnect);\n cleanupDisconnect = () => this.removeListener(\"disconnected\", onDisconnect);\n });\n try {\n return await Promise.race([call, timeoutP, closedP]);\n } finally {\n if (timer) clearTimeout(timer);\n cleanupDisconnect();\n }\n }\n\n /**\n * Sends a pre-built envelope (e.g. `unsubscribe`) that carries an `id` and\n * waits for the matching `response`/`error`. Used for envelope types that\n * are not `request` (e.g. `unsubscribe` → `autopilot_unsubscribe`) but still\n * expect a correlated response from the daemon.\n */\n private async _requestResponseForEnvelope(\n env: { id: string; proto?: string; type?: string },\n label: string,\n timeout: number,\n ): Promise<Record<string, unknown>> {\n const rid = env.id;\n const { call, unregister } = this.mux.registerRPC(rid);\n try {\n await this.sendMessage(env);\n return await this._raceRPC(call, timeout, label);\n } finally {\n unregister();\n }\n }\n\n /** Sends a fire-and-forget `notification` envelope (no response expected). */\n notify(method: MethodName, params: Record<string, unknown>): Promise<void> {\n return this.sendMessage(notificationEnvelope(method, params));\n }\n\n private _trackInboundDeliveryAck(event: Record<string, unknown>): void {\n if (String(event.type ?? \"\") === \"event_batch\") {\n const events = event.events;\n if (Array.isArray(events)) {\n for (const sub of events) {\n if (sub && typeof sub === \"object\") {\n this._trackInboundDeliveryAck(sub as Record<string, unknown>);\n }\n }\n }\n return;\n }\n if (!inboundNeedsDeliveryAck(event)) return;\n const loopId = extractLoopIdFromInbound(event);\n if (!loopId) return;\n const next = (this.deliveryRecvSeq.get(loopId) ?? 0) + 1;\n this.deliveryRecvSeq.set(loopId, next);\n void this._sendDeliveryAck(loopId, next);\n }\n\n private async _sendDeliveryAck(loopId: string, seq: number): Promise<void> {\n const acked = this.deliveryAckedSeq.get(loopId) ?? 0;\n if (seq <= acked) return;\n this.deliveryAckedSeq.set(loopId, seq);\n if (!this.isConnected()) return;\n try {\n await this.notify(\"delivery_ack\", { loop_id: loopId, seq });\n } catch {\n // best-effort; daemon drain may retry\n }\n }\n\n /**\n * Starts a subscription stream. Returns the subscription `id` for later\n * correlation and `unsubscribe()`. Stream events arrive as `next` frames\n * carrying the same `id`.\n */\n async subscribe(\n method: \"loop_events\" | \"autopilot_events\",\n params: Record<string, unknown>,\n timeout: number = 5_000,\n ): Promise<string> {\n const req = subscribeEnvelope(method, params);\n const subId = req.id;\n await this.sendMessage(req);\n\n // Wait briefly for either a subscription-confirmation `next` or an `error`\n // with the matching id. If neither arrives, assume accepted. Read from the\n // live socket so buffered stream events do not stall the confirmation wait.\n const deadline = Date.now() + timeout;\n while (Date.now() < deadline) {\n const remaining = deadline - Date.now();\n if (remaining <= 0) break;\n const ev = await this.readLiveEventWithTimeout(remaining);\n if (ev === null) break;\n const evId = ev.id as string | undefined;\n if (evId !== subId) {\n this.enqueueMessageBuffer(ev as DecodedMessage);\n continue;\n }\n const typ = ev.type as string;\n if (typ === \"error\") {\n const errObj = (ev.error as { code?: number; message?: string; data?: unknown }) ?? {};\n throw new DaemonError(\n errObj.code ?? -32603,\n errObj.message ?? \"subscription rejected\",\n errObj.data,\n );\n }\n if (typ === \"next\" || typ === \"complete\") {\n // Subscription confirmed (next) or already complete. Re-buffer for the\n // stream reader so it sees the first event.\n this.messageBuffer.unshift(ev as DecodedMessage);\n break;\n }\n }\n return subId;\n }\n\n /** Cancels an active subscription by id. */\n unsubscribe(subscriptionId: string): Promise<void> {\n return this.sendMessage(unsubscribeEnvelope(subscriptionId));\n }\n\n /**\n * Reads the next stream event from a subscription. For `next` frames the\n * `payload` is returned; for `complete`/`error` the full envelope is\n * returned so the caller can inspect termination.\n */\n async next(): Promise<Record<string, unknown> | null> {\n const ev = await this.readEvent();\n if (ev === null) return null;\n if (ev.type === \"next\") {\n return (ev.payload as Record<string, unknown>) ?? {};\n }\n return ev;\n }\n\n // ---------------------------------------------------------------------------\n // High-level API methods (Loop-first, RFC-503)\n // ---------------------------------------------------------------------------\n\n /** Sends user input to the daemon (loop_input notification; requires loopID). */\n sendInput(text: string, options?: InputOptions): Promise<void> {\n const loopId = (options?.loopID ?? \"\").trim();\n if (!loopId) {\n return Promise.reject(new Error(\"sendInput requires options.loopID\"));\n }\n const params: Record<string, unknown> = {\n loop_id: loopId,\n content: text,\n autonomous: options?.autonomous ?? false,\n };\n if (options?.maxIterations !== undefined) params.max_iterations = options.maxIterations;\n if (options?.subagent) params.preferred_subagent = options.subagent;\n if (options?.model) params.model = options.model;\n if (options?.modelParams) params.model_params = options.modelParams;\n if (options?.attachments) params.attachments = options.attachments;\n if (options?.intentHint) {\n const hintError = validateLoopInputIntentHint(options.intentHint);\n if (hintError) {\n return Promise.reject(new Error(hintError));\n }\n params.intent_hint = options.intentHint;\n }\n if (options?.responseSchema) params.response_schema = options.responseSchema;\n if (options?.responseSchemaName) params.response_schema_name = options.responseSchemaName;\n if (options?.responseSchemaStrict !== undefined)\n params.response_schema_strict = options.responseSchemaStrict;\n if (options?.clarificationMode) params.clarification_mode = options.clarificationMode;\n if (options?.clarificationAnswer) params.clarification_answer = true;\n if (options?.clarificationAnswers) params.clarification_answers = options.clarificationAnswers;\n return this.notify(\"loop_input\", params);\n }\n\n /** Sends a slash command to the daemon (slash_command notification). */\n sendCommand(cmd: string): Promise<void> {\n return this.notify(\"slash_command\", { cmd });\n }\n\n // ---------------------------------------------------------------------------\n // Loop lifecycle methods (RFC-503)\n // ---------------------------------------------------------------------------\n\n /** Requests the daemon to create a new StrangeLoop and waits for the response. */\n sendLoopNew(opts?: LoopNewOptions | string): Promise<void> {\n return this.sendMessage(newLoopNewMessage(opts));\n }\n\n /** Subscribes to events for a loop (subscribe → loop_events). */\n async sendLoopSubscribe(\n loopID: string,\n verbosity: string,\n streamDelivery?: \"batch\" | \"adaptive\" | \"streaming\",\n ): Promise<void> {\n await this.subscribe(\"loop_events\", {\n loop_id: loopID,\n verbosity,\n stream_delivery: streamDelivery,\n });\n }\n\n /** Detaches from a loop (unsubscribe by subscription id). */\n sendLoopDetach(loopID: string): Promise<void> {\n // To preserve the loopID-based signature we send an unsubscribe envelope\n // carrying the loop-derived subscription id.\n return this.sendMessage(unsubscribeEnvelope(loopID));\n }\n\n /** Notifies the daemon that this client is leaving (disconnect notification). */\n sendDetach(): Promise<void> {\n return this.sendMessage(disconnectEnvelope());\n }\n\n /** Requests daemon status check. */\n sendDaemonStatus(): Promise<void> {\n return this.sendMessage(requestEnvelope(\"daemon_status\", {}));\n }\n\n /** Requests daemon shutdown. */\n sendDaemonShutdown(): Promise<void> {\n return this.sendMessage(requestEnvelope(\"daemon_shutdown\", {}));\n }\n\n /** Requests a config section from the daemon. */\n sendConfigGet(section: string): Promise<void> {\n return this.sendMessage(requestEnvelope(\"config_get\", { section }));\n }\n\n // ---------------------------------------------------------------------------\n // Convenience RPC methods (blocking request/response)\n // ---------------------------------------------------------------------------\n\n /** Requests the skills catalog and waits for the response. */\n listSkills(timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\"skills_list\", {}, \"skills_list\", timeout ?? 15_000);\n }\n\n /** Requests the models catalog and waits for the response. */\n listModels(timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\"models_list\", {}, \"models_list\", timeout ?? 15_000);\n }\n\n /** Invokes a skill on the daemon host and receives echo. */\n invokeSkill(skill: string, args?: string, timeout?: number): Promise<Record<string, unknown>> {\n const params: Record<string, unknown> = { skill, args: args ?? \"\" };\n return this.requestResponse(\"invoke_skill\", params, \"invoke_skill\", timeout ?? 120_000);\n }\n\n /** Requests loop list and waits for response. */\n listLoops(timeout?: number, workspace?: string): Promise<Record<string, unknown>> {\n const params: Record<string, unknown> = {};\n if (workspace) params.filter = { workspace };\n return this.requestResponse(\"loop_list\", params, \"loop_list\", timeout ?? 15_000);\n }\n\n /** Requests loop details and waits for response. */\n getLoop(loopID: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\"loop_get\", { loop_id: loopID }, \"loop_get\", timeout ?? 15_000);\n }\n\n /** Requests loop tree and waits for response. */\n getLoopTree(loopID: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\"loop_tree\", { loop_id: loopID }, \"loop_tree\", timeout ?? 15_000);\n }\n\n /** Requests loop deletion and waits for response. */\n deleteLoop(loopID: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\n \"loop_delete\",\n { loop_id: loopID },\n \"loop_delete\",\n timeout ?? 15_000,\n );\n }\n\n /** Requests persisted conversation/activity rows. */\n sendLoopMessages(\n loopID: string,\n limit?: number,\n offset?: number,\n includeEvents?: boolean,\n ): Promise<void> {\n const params: Record<string, unknown> = { loop_id: loopID };\n if (limit !== undefined) params.limit = limit;\n if (offset !== undefined) params.offset = offset;\n if (includeEvents) params.include_events = true;\n return this.sendMessage(requestEnvelope(\"loop_messages\", params));\n }\n\n /** Requests LangGraph checkpoint channel values. */\n sendLoopStateGet(loopID: string): Promise<void> {\n return this.sendMessage(requestEnvelope(\"loop_state_get\", { loop_id: loopID }));\n }\n\n /** Applies partial checkpoint values. */\n sendLoopStateUpdate(\n loopID: string,\n values: Record<string, unknown>,\n asNode?: string,\n ): Promise<void> {\n const params: Record<string, unknown> = { loop_id: loopID, values };\n if (asNode) params.as_node = asNode;\n return this.sendMessage(requestEnvelope(\"loop_state_update\", params));\n }\n\n /** Requests display card ledger snapshot. */\n sendLoopCardsFetch(loopID: string): Promise<void> {\n return this.sendMessage(requestEnvelope(\"loop_cards_fetch\", { loop_id: loopID }));\n }\n\n /** Requests the full loop history (RFC-631). */\n sendLoopHistoryFetch(loopID: string): Promise<void> {\n return this.sendMessage(requestEnvelope(\"loop_history_fetch\", { loop_id: loopID }));\n }\n\n /** Requests MCP server status. */\n sendMCPStatus(): Promise<void> {\n return this.sendMessage(requestEnvelope(\"mcp_status\", {}));\n }\n\n /** Requests daemon config reload. */\n sendConfigReload(): Promise<void> {\n return this.sendMessage(requestEnvelope(\"config_reload\", {}));\n }\n\n /** Submits credentials for daemon-side authentication. */\n sendAuth(accessKey: string, secretKey: string): Promise<void> {\n return this.sendMessage(\n requestEnvelope(\"auth\", { access_key: accessKey, secret_key: secretKey }),\n );\n }\n\n /** Refreshes the daemon-side auth token. */\n sendAuthRefresh(refreshToken: string): Promise<void> {\n return this.sendMessage(requestEnvelope(\"auth_refresh\", { refresh_token: refreshToken }));\n }\n\n /** Requests persisted messages and waits for response. */\n getLoopMessages(\n loopID: string,\n limit?: number,\n offset?: number,\n includeEvents?: boolean,\n timeout?: number,\n ): Promise<Record<string, unknown>> {\n const params: Record<string, unknown> = { loop_id: loopID };\n if (limit !== undefined) params.limit = limit;\n if (offset !== undefined) params.offset = offset;\n if (includeEvents) params.include_events = true;\n return this.requestResponse(\"loop_messages\", params, \"loop_messages\", timeout ?? 15_000);\n }\n\n /** Requests loop state and waits for response. */\n getLoopState(loopID: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\n \"loop_state_get\",\n { loop_id: loopID },\n \"loop_state_get\",\n timeout ?? 15_000,\n );\n }\n\n /** Updates loop state and waits for response. */\n updateLoopState(\n loopID: string,\n values: Record<string, unknown>,\n asNode?: string,\n timeout?: number,\n ): Promise<Record<string, unknown>> {\n const params: Record<string, unknown> = { loop_id: loopID, values };\n if (asNode) params.as_node = asNode;\n return this.requestResponse(\n \"loop_state_update\",\n params,\n \"loop_state_update\",\n timeout ?? 15_000,\n );\n }\n\n /** Requests display cards and waits for response. */\n fetchLoopCards(loopID: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\n \"loop_cards_fetch\",\n { loop_id: loopID },\n \"loop_cards_fetch\",\n timeout ?? 15_000,\n );\n }\n\n /** Requests MCP status and waits for response. */\n getMCPStatus(timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\"mcp_status\", {}, \"mcp_status\", timeout ?? 15_000);\n }\n\n /** Requests loop history and waits for response. */\n fetchLoopHistory(loopID: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\n \"loop_history_fetch\",\n { loop_id: loopID },\n \"loop_history_fetch\",\n timeout ?? 15_000,\n );\n }\n\n /** Requests daemon config reload and waits for response. */\n reloadConfig(timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\"config_reload\", {}, \"config_reload\", timeout ?? 15_000);\n }\n\n /** Submits credentials for daemon-side authentication and waits for response. */\n authenticate(\n accessKey: string,\n secretKey: string,\n timeout?: number,\n ): Promise<Record<string, unknown>> {\n return this.requestResponse(\n \"auth\",\n { access_key: accessKey, secret_key: secretKey },\n \"auth\",\n timeout ?? 15_000,\n );\n }\n\n /** Refreshes the daemon-side auth token and waits for response. */\n refreshAuthToken(refreshToken: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\n \"auth_refresh\",\n { refresh_token: refreshToken },\n \"auth_refresh\",\n timeout ?? 15_000,\n );\n }\n\n // ---------------------------------------------------------------------------\n // RFC-228 Job IPC methods\n // ---------------------------------------------------------------------------\n\n /** Creates an autopilot job and waits for the response. */\n createJob(\n goal: string,\n verificationRules?: string,\n workspace?: string,\n timeout?: number,\n ): Promise<Record<string, unknown>> {\n const params: Record<string, unknown> = { goal };\n if (verificationRules) params.verification_rules = verificationRules;\n if (workspace) params.workspace = workspace;\n return this.requestResponse(\"job_create\", params, \"job_create\", timeout ?? 15_000);\n }\n\n /** Queries job status and waits for the response. */\n getJobStatus(jobId: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\"job_status\", { job_id: jobId }, \"job_status\", timeout ?? 15_000);\n }\n\n /** Pauses a running job. */\n pauseJob(jobId: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\"job_pause\", { job_id: jobId }, \"job_pause\", timeout ?? 15_000);\n }\n\n /** Resumes a paused job. */\n resumeJob(jobId: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\"job_resume\", { job_id: jobId }, \"job_resume\", timeout ?? 15_000);\n }\n\n /** Cancels a job. */\n cancelJob(jobId: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\"job_cancel\", { job_id: jobId }, \"job_cancel\", timeout ?? 15_000);\n }\n\n /** Requests the DAG visualization for a job. */\n getJobDag(jobId: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\"job_dag\", { job_id: jobId }, \"job_dag\", timeout ?? 15_000);\n }\n\n /** Sends guidance to a job or specific goal. */\n sendJobGuidance(\n jobId: string,\n text: string,\n goalId?: string,\n timeout?: number,\n ): Promise<Record<string, unknown>> {\n const params: Record<string, unknown> = { job_id: jobId, content: text };\n if (goalId) params.goal_id = goalId;\n return this.requestResponse(\"job_guidance\", params, \"job_guidance\", timeout ?? 30_000);\n }\n\n /** Subscribes to autopilot worker events. */\n autopilotSubscribe(timeout?: number): Promise<string> {\n return this.subscribe(\"autopilot_events\", {}, timeout ?? 15_000);\n }\n\n /** Unsubscribes from autopilot worker events. */\n autopilotUnsubscribe(timeout?: number): Promise<Record<string, unknown>> {\n // Send an unsubscribe envelope (no loop_id in params → daemon infers\n // autopilot_unsubscribe). The daemon sends a `response` correlated by\n // the envelope id; wait for it via requestResponse semantics.\n const req = unsubscribeEnvelope(newRequestID());\n return this._requestResponseForEnvelope(req, \"autopilot_unsubscribe\", timeout ?? 15_000);\n }\n\n // ---------------------------------------------------------------------------\n // RFC-229 Cron IPC methods\n // ---------------------------------------------------------------------------\n\n /** Creates a scheduled job from natural language. */\n cronAdd(text: string, priority?: number, timeout?: number): Promise<Record<string, unknown>> {\n const params: Record<string, unknown> = { text };\n if (priority !== undefined) params.priority = priority;\n return this.requestResponse(\n \"cron_add\",\n params,\n \"cron_add\",\n timeout ?? 30_000, // Longer timeout for NL extraction\n );\n }\n\n /** Lists scheduled jobs. */\n cronList(status?: string, timeout?: number): Promise<Record<string, unknown>> {\n const params: Record<string, unknown> = {};\n if (status !== undefined) params.status = status;\n return this.requestResponse(\"cron_list\", params, \"cron_list\", timeout ?? 15_000);\n }\n\n /** Shows a specific scheduled job. */\n cronShow(jobId: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\"cron_show\", { job_id: jobId }, \"cron_show\", timeout ?? 15_000);\n }\n\n /** Cancels a scheduled job. */\n cronCancel(jobId: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\"cron_cancel\", { job_id: jobId }, \"cron_cancel\", timeout ?? 15_000);\n }\n\n // ---------------------------------------------------------------------------\n // Wait helpers\n /**\n * Waits for the connection_ack to report readiness (already done in\n * connect(); kept for callers that reconnect manually). Resolves\n * immediately if the handshake is already complete.\n */\n async waitForDaemonReady(timeout?: number): Promise<Record<string, unknown>> {\n if (this.handshakeComplete) {\n return { readiness_state: this.readinessState ?? \"ready\" };\n }\n const t = timeout ?? 10_000;\n const deadline = Date.now() + t;\n while (Date.now() < deadline) {\n const remaining = deadline - Date.now();\n if (remaining <= 0) break;\n const ev = await this.readEventWithTimeout(remaining);\n if (ev === null) break;\n if (ev.type !== \"connection_ack\") continue;\n const result = (ev.result as Record<string, unknown> | undefined) ?? {};\n const state = result.readiness_state as string | undefined;\n if (state === \"ready\") return ev;\n throw new Error(`daemon not ready: state=${state ?? \"unknown\"}`);\n }\n throw new Error(`timeout after ${t}ms waiting for connection_ack`);\n }\n}\n","/**\n * Soothe WebSocket Client - TypeScript\n *\n * A WebSocket client for the Soothe daemon (RFC-450 protocol-1 wire contract),\n * providing the unified `{proto, type, method, params, id}` envelope, session\n * bootstrap, and convenience RPC helpers.\n */\n\n// Errors\nexport {\n ConnectionError,\n DaemonError,\n TimeoutError,\n ReconnectError,\n StaleLoopError,\n DisconnectCause,\n disconnectCauseName,\n} from \"./errors.js\";\n\n// Verbosity\nexport { VerbosityTier, shouldShow, isValidVerbosityLevel } from \"./verbosity.js\";\nexport type { VerbosityLevel } from \"./verbosity.js\";\n\n// Config\nexport { defaultConfig, loadConfigFromEnv } from \"./config.js\";\nexport type { Config } from \"./config.js\";\n\n// Protocol (RFC-450 protocol-1 envelope)\nexport {\n PROTO_VERSION,\n DEFAULT_CLIENT_CAPABILITIES,\n CLIENT_VERSION,\n encodeMessage,\n decodeMessage,\n splitWirePayload,\n extractSootheLoopID,\n newRequestID,\n requestEnvelope,\n notificationEnvelope,\n subscribeEnvelope,\n unsubscribeEnvelope,\n connectionInitEnvelope,\n pingEnvelope,\n pongEnvelope,\n disconnectEnvelope,\n newLoopInputMessage,\n newLoopNewMessage,\n newLoopSubscribeMessage,\n} from \"./protocol.js\";\nexport type {\n MessageType,\n MethodName,\n BaseEnvelope,\n RequestEnvelope,\n ResponseEnvelope,\n NotificationEnvelope,\n SubscribeEnvelope,\n NextEnvelope,\n ErrorEnvelope,\n CompleteEnvelope,\n UnsubscribeEnvelope,\n ConnectionInitEnvelope,\n ConnectionAckEnvelope,\n PingEnvelope,\n PongEnvelope,\n ReceiptResponseEnvelope,\n DisconnectEnvelope,\n StatusFrame,\n DecodedMessage,\n LoopInputParams,\n LoopNewOptions,\n StreamEventPayload,\n} from \"./protocol.js\";\nexport type {\n IntentHint,\n LoopAssistantOutputPhase,\n LoopInputIntentHint,\n RemovedIntentHint,\n} from \"./intent_hints.js\";\nexport {\n DEFAULT_DELIVERABLE_PHASES,\n INTENT_HINT_EMBED,\n INTENT_HINT_IMAGE_TO_TEXT,\n INTENT_HINT_OCR,\n INTENT_HINT_TEXT_COMPLETION,\n LOOP_ASSISTANT_OUTPUT_PHASES,\n REMOVED_INTENT_HINTS,\n validateLoopInputIntentHint,\n} from \"./intent_hints.js\";\n\n// Events\nexport {\n EventPlanCreated,\n EventExploreStarted,\n EventExploreMilestone,\n EventExploreStepCompleted,\n EventExploreCompleted,\n EventTacitusStarted,\n EventTacitusGatherSummary,\n EventTacitusCompleted,\n EventReplayComplete,\n EventLoopReattachedWire,\n EventCardReplayBegin,\n EventCardCreated,\n EventCardReplayEnd,\n EventStrangeLoopStarted,\n EventStrangeLoopCompleted,\n EventStrangeLoopPlanDecision,\n EventStrangeLoopReasoned,\n EventStrangeLoopStepStarted,\n EventStrangeLoopStepQueued,\n EventStrangeLoopStepCompleted,\n EventStrangeLoopContextCompacted,\n EventToolStarted,\n EventToolCompleted,\n EventToolError,\n EventStreamToolCallUpdate,\n EventToolCallUpdatesBatch,\n EventMessageReceived,\n EventMessageSent,\n EventFinalReport,\n EventAutopilotGoalStatus,\n EventAutopilotGoalProgress,\n EventAutopilotGoalCreated,\n EventAutopilotGoalCompleted,\n EventAutopilotWorkerAssigned,\n EventAutopilotWorkerUnassigned,\n EventGeneralFailed,\n parseNamespace,\n classifyEventVerbosity,\n isCompletionEvent,\n isSubagentProgressEvent,\n} from \"./events.js\";\n\n// Client\nexport { Client } from \"./client.js\";\nexport type { InputOptions, NegotiatedCapabilities } from \"./client.js\";\n\n// Ephemeral one-shot RPCs (jobs / cron / autopilot)\nexport { CommandClient } from \"./command_client.js\";\n\n// Helpers\nexport {\n checkDaemonStatus,\n isDaemonLive,\n requestDaemonShutdown,\n requestDaemonConfigReload,\n fetchSkillsCatalog,\n fetchConfigSection,\n fetchLoopHistory,\n fetchLoopCards,\n fetchLoopMessages,\n authenticate,\n refreshAuthToken,\n connectedWebsocket,\n protocol1Rpc,\n} from \"./helpers.js\";\n\n// Session\nexport {\n bootstrapLoopSession,\n waitDaemonReady,\n waitLoopStatusWithID,\n waitSubscriptionConfirmed,\n connectWithRetries,\n} from \"./session.js\";\n\n// Stream terminal helpers (used by DaemonSession consumers)\nexport {\n STREAM_END,\n isTurnEndCustomData,\n isTurnProgressChunk,\n inboundNeedsDeliveryAck,\n} from \"./stream_terminal.js\";\n\n// appkit (RFC-629 Layer 1) — slim surface matching Python\nexport {\n DaemonSession,\n ConnectionPool,\n TurnRunner,\n QueryGate,\n EventClassifier,\n ChatEventTerminal,\n SSEBroadcaster,\n ErrPoolExhausted,\n ErrQueryBusy,\n ErrIdleTimeout,\n ErrQueryTimeout,\n TimeoutPolicy,\n StreamCloseFail,\n StreamCloseSoftComplete,\n defaultPoolConfig,\n PooledConn,\n compactAttachments,\n compactImageAttachment,\n extractThinkingStep,\n DEFAULT_THINKING_STEP_EVENTS,\n idleTimeoutForTurn,\n inputMessageForLoop,\n TurnEventStats,\n DEFAULT_POST_IDLE_DRAIN_MS,\n} from \"./appkit/index.js\";\nexport type {\n SessionStore,\n SessionEntry,\n SessionMessage,\n SSEEvent,\n ChatEventResult,\n ClassifierConfig,\n PoolConfig,\n TurnConfig,\n InputOpts,\n Attachment,\n OnComplete,\n OnError,\n StreamClosePolicy,\n DaemonSessionOptions,\n TurnChunk,\n CompactImageOptions,\n} from \"./appkit/index.js\";\n","/**\n * Ephemeral one-shot RPC client for jobs / cron / autopilot.\n * Mirrors Python AsyncCommandClient / CommandClient (RFC-629 / IG-662).\n */\n\nimport { Client } from \"./client.js\";\nimport { defaultConfig, type Config } from \"./config.js\";\nimport type { MethodName } from \"./protocol.js\";\nimport { connectWithRetries } from \"./session.js\";\n\nexport class CommandClient {\n readonly url: string;\n readonly timeoutMs: number;\n private readonly config: Config;\n\n constructor(url: string, opts?: { timeoutMs?: number; config?: Config }) {\n this.url = url;\n this.timeoutMs = opts?.timeoutMs && opts.timeoutMs > 0 ? opts.timeoutMs : 30_000;\n this.config = opts?.config ?? defaultConfig();\n }\n\n private async withClient<T>(fn: (client: Client) => Promise<T>): Promise<T> {\n const client = new Client(this.url, this.config);\n try {\n await connectWithRetries(client, 5, 250);\n return await fn(client);\n } finally {\n client.close();\n }\n }\n\n /** Generic one-shot RPC. */\n async request(\n method: MethodName,\n params: Record<string, unknown> = {},\n ): Promise<Record<string, unknown>> {\n return this.withClient(client =>\n client.requestResponse(method, params, undefined, this.timeoutMs),\n );\n }\n\n async jobCreate(goal: string, workspace = \"\"): Promise<Record<string, unknown>> {\n const params: Record<string, unknown> = { goal };\n if (workspace) params.workspace = workspace;\n return this.request(\"job_create\", params);\n }\n\n async jobStatus(jobId: string): Promise<Record<string, unknown>> {\n return this.request(\"job_status\", { job_id: jobId });\n }\n\n async jobCancel(jobId: string): Promise<Record<string, unknown>> {\n return this.request(\"job_cancel\", { job_id: jobId });\n }\n\n async cronAdd(text: string, priority = 0): Promise<Record<string, unknown>> {\n const params: Record<string, unknown> = { text };\n if (priority > 0) params.priority = priority;\n return this.request(\"cron_add\", params);\n }\n\n async cronList(status = \"\"): Promise<Record<string, unknown>> {\n const params: Record<string, unknown> = {};\n if (status) params.status = status;\n return this.request(\"cron_list\", params);\n }\n}\n","/**\n * Session bootstrap flows, wait helpers, and connect-with-retries.\n *\n * Under protocol-1 (RFC-450) the connection handshake (connection_init /\n * connection_ack) is performed by `client.connect()`. Bootstrap therefore\n * jumps straight to loop_new + subscribe(loop_events).\n */\n\nimport type { Client } from \"./client.js\";\nimport type { Config } from \"./config.js\";\nimport { defaultConfig } from \"./config.js\";\nimport { newLoopNewMessage } from \"./protocol.js\";\nimport { DaemonError } from \"./errors.js\";\n\n// ---------------------------------------------------------------------------\n// Bootstrap flows (loop-first, RFC-503)\n// ---------------------------------------------------------------------------\n\n/**\n * loop_new (or reuse id) → subscribe(loop_events); returns the loop id.\n * The protocol-1 handshake is assumed to have completed in `client.connect()`.\n */\nexport async function bootstrapLoopSession(\n client: Client,\n resumeLoopId: string | null | undefined,\n config?: Config,\n loopNew?: import(\"./protocol.js\").LoopNewOptions,\n): Promise<string> {\n const cfg = config ?? defaultConfig();\n\n let loopId = (resumeLoopId ?? \"\").trim();\n if (!loopId) {\n const env = newLoopNewMessage(loopNew);\n const newResp = await client.requestResponse(\n env.method,\n env.params ?? {},\n \"loop_new\",\n cfg.loopStatusTimeout,\n );\n loopId = String(newResp.loop_id ?? \"\").trim();\n if (!loopId) {\n throw new Error(\"loop_new response missing loop_id\");\n }\n }\n\n // Subscribe to the loop event stream. Confirmation arrives as a `next`\n // frame; client.subscribe() handles the initial ack/error window.\n await client.subscribe(\n \"loop_events\",\n { loop_id: loopId, verbosity: cfg.verbosityLevel },\n cfg.subscriptionTimeout,\n );\n\n return loopId;\n}\n\n// ---------------------------------------------------------------------------\n// Wait helpers (use client's readEventWithTimeout internally)\n// ---------------------------------------------------------------------------\n\n/**\n * Blocks until connection_ack reports readiness \"ready\". Resolves immediately\n * if the handshake already completed during connect().\n */\nexport async function waitDaemonReady(client: Client, timeout: number): Promise<void> {\n if (client.isConnected()) return;\n const deadline = Date.now() + timeout;\n while (Date.now() < deadline) {\n const remaining = deadline - Date.now();\n if (remaining <= 0) break;\n const ev = (await client.readEventWithTimeout(remaining)) as Record<string, unknown> | null;\n if (ev === null) break;\n if (ev.type === \"connection_ack\") {\n const result = (ev.result as Record<string, unknown> | undefined) ?? {};\n const state = result.readiness_state as string | undefined;\n if (state === \"ready\") return;\n throw new Error(`daemon not ready: state=${JSON.stringify(state ?? \"unknown\")}`);\n }\n }\n throw new Error(`timeout after ${timeout}ms waiting for connection_ack (ready)`);\n}\n\n/** Waits for a status message with a non-empty loop_id. */\nexport async function waitLoopStatusWithID(\n client: Client,\n timeout: number,\n): Promise<Record<string, unknown>> {\n const deadline = Date.now() + timeout;\n while (Date.now() < deadline) {\n const remaining = deadline - Date.now();\n if (remaining <= 0) break;\n const ev = (await client.readEventWithTimeout(remaining)) as Record<string, unknown> | null;\n if (ev === null) break;\n\n if (ev.type === \"error\") {\n const errObj = (ev.error as { code?: number; message?: string }) ?? {};\n throw new DaemonError(errObj.code ?? -32603, errObj.message ?? \"daemon error\");\n }\n\n if (ev.type === \"status\") {\n const lid = ev.loop_id as string | undefined;\n if (lid && lid !== \"\") {\n return ev;\n }\n }\n }\n throw new Error(`timeout after ${timeout}ms waiting for status with loop_id`);\n}\n\n/** Waits for a subscription confirmation `next` matching loop id. */\nexport async function waitSubscriptionConfirmed(\n client: Client,\n wantLoopID: string,\n _wantVerbosity: string,\n timeout: number,\n): Promise<void> {\n const deadline = Date.now() + timeout;\n while (Date.now() < deadline) {\n const remaining = deadline - Date.now();\n if (remaining <= 0) break;\n const ev = (await client.readEventWithTimeout(remaining)) as Record<string, unknown> | null;\n if (ev === null) break;\n if (ev.type === \"next\") {\n const payload = (ev.payload as Record<string, unknown> | undefined) ?? {};\n const lid = String(payload.loop_id ?? \"\");\n if (lid === wantLoopID && payload.success === true) return;\n continue;\n }\n if (ev.type === \"error\") {\n const errObj = (ev.error as { message?: string }) ?? {};\n throw new Error(`daemon error: ${errObj.message ?? \"subscription failed\"}`);\n }\n }\n throw new Error(`timeout after ${timeout}ms waiting for subscription confirmation`);\n}\n\n// ---------------------------------------------------------------------------\n// Connect with retries\n// ---------------------------------------------------------------------------\n\n/** Attempts to connect to the Soothe daemon with bounded retries. */\nexport async function connectWithRetries(\n client: Client,\n maxRetries?: number,\n retryDelay?: number,\n): Promise<void> {\n const retries = maxRetries && maxRetries > 0 ? maxRetries : 40;\n const delay = retryDelay && retryDelay > 0 ? retryDelay : 250;\n\n let lastErr: Error | null = null;\n for (let attempt = 0; attempt < retries; attempt++) {\n try {\n await client.connect();\n return;\n } catch (err) {\n lastErr = err as Error;\n }\n await new Promise(resolve => setTimeout(resolve, delay));\n }\n throw new Error(\n `failed to connect after ${retries} attempts: ${lastErr?.message ?? \"unknown error\"}`,\n );\n}\n","/**\n * Convenience RPC helper functions for the Soothe client (RFC-450 protocol-1).\n */\n\nimport type { Client } from \"./client.js\";\nimport { defaultConfig } from \"./config.js\";\n\n/** Checks daemon status via RPC. */\nexport async function checkDaemonStatus(\n client: Client,\n timeout?: number,\n): Promise<Record<string, unknown>> {\n return client.requestResponse(\"daemon_status\", {}, \"daemon_status\", timeout ?? 5_000);\n}\n\n/** Performs a composite health check: connect + handshake + status RPC. */\nexport async function isDaemonLive(wsURL: string, timeout?: number): Promise<boolean> {\n const { Client } = await import(\"./client.js\");\n const t = timeout ?? 5_000;\n const client = new Client(wsURL, defaultConfig());\n\n try {\n await client.connect();\n } catch {\n return false;\n }\n\n try {\n await checkDaemonStatus(client, t);\n return true;\n } catch {\n return false;\n } finally {\n client.close();\n }\n}\n\n/** Requests daemon shutdown via RPC. */\nexport async function requestDaemonShutdown(client: Client, timeout?: number): Promise<void> {\n const resp = await client.requestResponse(\n \"daemon_shutdown\",\n {},\n \"daemon_shutdown\",\n timeout ?? 10_000,\n );\n if (resp.status !== \"acknowledged\") {\n throw new Error(`shutdown not acknowledged: ${JSON.stringify(resp)}`);\n }\n}\n\n/** Fetches the skills catalog via RPC. */\nexport async function fetchSkillsCatalog(\n client: Client,\n timeout?: number,\n): Promise<Record<string, unknown>[]> {\n const resp = await client.requestResponse(\"skills_list\", {}, \"skills_list\", timeout ?? 15_000);\n const skillsRaw = resp.skills;\n if (!skillsRaw || !Array.isArray(skillsRaw)) return [];\n return skillsRaw.filter((s): s is Record<string, unknown> => typeof s === \"object\" && s !== null);\n}\n\n/** Fetches a daemon config section via RPC. */\nexport async function fetchConfigSection(\n client: Client,\n section: string,\n timeout?: number,\n): Promise<Record<string, unknown>> {\n const resp = await client.requestResponse(\n \"config_get\",\n { section },\n \"config_get\",\n timeout ?? 5_000,\n );\n const sec = resp[section];\n if (sec && typeof sec === \"object\") {\n return sec as Record<string, unknown>;\n }\n return resp;\n}\n\n/** Requests daemon config reload via RPC. */\nexport async function requestDaemonConfigReload(\n client: Client,\n timeout?: number,\n): Promise<Record<string, unknown>> {\n return client.requestResponse(\"config_reload\", {}, \"config_reload\", timeout ?? 15_000);\n}\n\n/** Requests loop history (RFC-631) and waits for the response. */\nexport async function fetchLoopHistory(\n client: Client,\n loopID: string,\n timeout?: number,\n): Promise<Record<string, unknown>> {\n return client.requestResponse(\n \"loop_history_fetch\",\n { loop_id: loopID },\n \"loop_history_fetch\",\n timeout ?? 15_000,\n );\n}\n\n/** Submits credentials for daemon-side authentication and waits for the response. */\nexport async function authenticate(\n client: Client,\n accessKey: string,\n secretKey: string,\n timeout?: number,\n): Promise<Record<string, unknown>> {\n return client.requestResponse(\n \"auth\",\n { access_key: accessKey, secret_key: secretKey },\n \"auth\",\n timeout ?? 15_000,\n );\n}\n\n/** Refreshes the daemon-side auth token and waits for the response. */\nexport async function refreshAuthToken(\n client: Client,\n refreshToken: string,\n timeout?: number,\n): Promise<Record<string, unknown>> {\n return client.requestResponse(\n \"auth_refresh\",\n { refresh_token: refreshToken },\n \"auth_refresh\",\n timeout ?? 15_000,\n );\n}\n\n/** Fetch bound display-card snapshot for a loop. */\nexport async function fetchLoopCards(\n client: Client,\n loopID: string,\n timeout?: number,\n): Promise<Record<string, unknown>> {\n return client.fetchLoopCards(loopID, timeout);\n}\n\n/** Fetch persisted conversation/activity rows for a loop. */\nexport async function fetchLoopMessages(\n client: Client,\n loopID: string,\n opts?: { limit?: number; offset?: number; includeEvents?: boolean; timeout?: number },\n): Promise<Record<string, unknown>> {\n return client.getLoopMessages(\n loopID,\n opts?.limit,\n opts?.offset,\n opts?.includeEvents,\n opts?.timeout,\n );\n}\n\n/**\n * Connect, handshake, and yield a ready Client. Always closes in finally.\n */\nexport async function connectedWebsocket<T>(\n wsUrl: string,\n fn: (client: Client) => Promise<T>,\n timeoutMs = 30_000,\n): Promise<T> {\n const { Client } = await import(\"./client.js\");\n const client = new Client(wsUrl, defaultConfig());\n const deadline = Date.now() + timeoutMs;\n try {\n await client.connect();\n while (!client.isConnected() && Date.now() < deadline) {\n await new Promise(r => setTimeout(r, 25));\n }\n if (!client.isConnected()) {\n throw new Error(\"Timed out waiting for daemon handshake\");\n }\n return await fn(client);\n } finally {\n client.close();\n }\n}\n\n/**\n * One-shot protocol-1 RPC / notify / subscribe with dict-style error contract.\n * Callers check `if (\"error\" in response)`.\n */\nexport async function protocol1Rpc(\n wsUrl: string,\n method: string,\n params: Record<string, unknown> | null = null,\n opts: { mode?: \"request\" | \"notify\" | \"subscribe\"; timeoutMs?: number } = {},\n): Promise<Record<string, unknown>> {\n const mode = opts.mode ?? \"request\";\n const timeoutMs = opts.timeoutMs ?? 30_000;\n try {\n return await connectedWebsocket(\n wsUrl,\n async client => {\n if (mode === \"notify\") {\n await client.notify(method as import(\"./protocol.js\").MethodName, params ?? {});\n return {};\n }\n if (mode === \"subscribe\") {\n const subId = await client.subscribe(\n method as \"loop_events\" | \"autopilot_events\",\n params ?? {},\n timeoutMs,\n );\n return { subscription_id: subId };\n }\n const result = await client.requestResponse(\n method as import(\"./protocol.js\").MethodName,\n params ?? {},\n method,\n timeoutMs,\n );\n return result && typeof result === \"object\" ? result : { result };\n },\n timeoutMs,\n );\n } catch (exc) {\n const msg = exc instanceof Error ? exc.message : String(exc);\n if (msg.toLowerCase().includes(\"timed out\") || msg.toLowerCase().includes(\"timeout\")) {\n return { error: \"Timed out waiting for daemon response\" };\n }\n if (msg.toLowerCase().includes(\"connect\") || msg.toLowerCase().includes(\"dial\")) {\n return { error: `Connection error: ${msg}` };\n }\n return { error: msg };\n }\n}\n","/**\n * SSE-style pub/sub fan-out for appkit (RFC-629 Layer 1).\n *\n * Generic, string-keyed pub/sub for SSE-style event delivery. The\n * application-agnostic successor to a domain-keyed broadcaster: applications\n * convert from their domain key type to `string` at their own boundary.\n *\n * Slow consumers do not stall the broadcaster: each subscriber has a bounded\n * queue and overflowing events are dropped (drop-on-full).\n */\n\n/** One Server-Sent Event payload. The Type vocabulary is app-defined. */\nexport interface SSEEvent {\n type: string;\n data: unknown;\n}\n\n/** Per-subscriber bounded queue. Events past the cap are dropped. */\nconst SUBSCRIBER_QUEUE_CAP = 100;\n\ninterface Subscriber {\n queue: SSEEvent[];\n /** Resolvers waiting for the next event. */\n waiters: Array<(ev: SSEEvent | null) => void>;\n closed: boolean;\n}\n\n/**\n * SSEBroadcaster fans events out to all subscribers for a session id.\n * Non-blocking: a full subscriber queue drops the event so one slow consumer\n * cannot block the others.\n */\nexport class SSEBroadcaster {\n private subscribers = new Map<string, Map<string, Subscriber>>();\n private nextSubID = 0;\n\n /** Creates an empty broadcaster. */\n constructor() {}\n\n /**\n * Registers a new subscriber channel for a session id. Returns an async\n * iterable the subscriber reads events from. Unsubscribe via\n * `unsubscribe()` or `close()`.\n */\n subscribe(sessionID: string): { iterable: AsyncIterable<SSEEvent>; id: string } {\n const subID = String(this.nextSubID++);\n const sub: Subscriber = { queue: [], waiters: [], closed: false };\n let subs = this.subscribers.get(sessionID);\n if (!subs) {\n subs = new Map();\n this.subscribers.set(sessionID, subs);\n }\n subs.set(subID, sub);\n\n const iterable: AsyncIterable<SSEEvent> = {\n [Symbol.asyncIterator]() {\n return {\n next(): Promise<IteratorResult<SSEEvent>> {\n if (sub.queue.length > 0) {\n return Promise.resolve({ value: sub.queue.shift()!, done: false });\n }\n if (sub.closed) {\n return Promise.resolve({ value: undefined as unknown as SSEEvent, done: true });\n }\n return new Promise<IteratorResult<SSEEvent>>(resolve => {\n sub.waiters.push(ev => {\n if (ev === null) {\n resolve({ value: undefined as unknown as SSEEvent, done: true });\n } else {\n resolve({ value: ev, done: false });\n }\n });\n });\n },\n };\n },\n };\n return { iterable, id: subID };\n }\n\n /** Removes a subscriber by id and closes its iterable. Safe if unknown. */\n unsubscribe(sessionID: string, subID: string): void {\n const subs = this.subscribers.get(sessionID);\n if (!subs) return;\n const sub = subs.get(subID);\n if (!sub) return;\n sub.closed = true;\n for (const w of sub.waiters) w(null);\n sub.waiters = [];\n subs.delete(subID);\n if (subs.size === 0) this.subscribers.delete(sessionID);\n }\n\n /**\n * Sends an event to all subscribers for a session id. Non-blocking: a full\n * subscriber queue is skipped (drop-on-full) so one slow consumer cannot\n * block the others.\n */\n broadcast(sessionID: string, event: SSEEvent): void {\n const subs = this.subscribers.get(sessionID);\n if (!subs) return;\n for (const sub of subs.values()) {\n if (sub.closed) continue;\n if (sub.waiters.length > 0) {\n const w = sub.waiters.shift()!;\n w(event);\n } else if (sub.queue.length < SUBSCRIBER_QUEUE_CAP) {\n sub.queue.push(event);\n }\n // else: drop-on-full.\n }\n }\n\n /** Closes all subscribers for a session id and removes the entry. */\n close(sessionID: string): void {\n const subs = this.subscribers.get(sessionID);\n if (!subs) return;\n for (const sub of subs.values()) {\n sub.closed = true;\n for (const w of sub.waiters) w(null);\n sub.waiters = [];\n }\n this.subscribers.delete(sessionID);\n }\n\n /** Closes every subscriber channel across all sessions. */\n closeAll(): void {\n for (const [sessionID, subs] of this.subscribers) {\n for (const sub of subs.values()) {\n sub.closed = true;\n for (const w of sub.waiters) w(null);\n sub.waiters = [];\n }\n this.subscribers.delete(sessionID);\n }\n }\n}\n","/**\n * Event classifier for appkit (RFC-629 Layer 1).\n *\n * Maps a stream of decoded daemon events into deliverable/streaming/terminal\n * outcomes, keyed on (namespace, mode, phase) per RFC-614/RFC-403\n * (RFC-629 constraint #4). The app-agnostic successor to triarch's\n * ProcessChatEvent, with the deliverable phase set promoted from hardcoded\n * constants to configuration.\n *\n * Event shape: a protocol-1 `next` envelope carries\n * `{type:\"next\", payload:{namespace, mode, data, loop_id}}`. The daemon\n * wraps legacy free-form frames as `{payload:{namespace, mode:<orig type>,\n * data:<orig frame>}}` (RFC-450 §9.3). The classifier inspects the payload's\n * `mode`/`data`/`namespace` and the inner message's `phase`/`type`/`content`.\n */\n\nimport { DaemonError } from \"../errors.js\";\nimport { EventFinalReport } from \"../events.js\";\nimport { DEFAULT_THINKING_STEP_EVENTS, extractThinkingStep } from \"./thinking_step.js\";\n\n/** How a processed event should end the query loop. */\nexport enum ChatEventTerminal {\n /** Accumulate content; the query is still running. */\n Continue = 0,\n /** A user-visible final reply; persist it. */\n DeliverableComplete = 1,\n /** The query failed; persist an error. */\n FailedComplete = 2,\n}\n\n/** The structured outcome of classifying one daemon event. */\nexport interface ChatEventResult {\n content?: string;\n /** User-visible progress line (not a final reply). */\n thinkingStep?: string;\n terminal: ChatEventTerminal;\n /** soothe wire event type when terminal === DeliverableComplete. */\n completionEvent?: string;\n err?: Error;\n}\n\n/**\n * Product-specific decisions an EventClassifier needs. The DeliverablePhases\n * set is the key product knob: which message `phase` values count as\n * user-facing deliverables (triarch uses quiz, goal_completion, direct_model, and\n * direct intent_hint phases text_completion, image_to_text, ocr, embed;\n * other apps pass their own).\n */\nexport interface ClassifierConfig {\n /** Recognizes loop-tagged message phases that may end a query with\n * user-facing text. Required. */\n deliverablePhases: ReadonlySet<string>;\n /** Minimum trimmed rune count for a reply to be persisted as final\n * (avoids finishing on stub ACKs like \"...\"). Defaults to 8. */\n minDeliverableRunes?: number;\n /** Optional app override of the default thinking-step event allowlist. */\n thinkingStepEvents?: ReadonlySet<string>;\n /**\n * When true, a status frame with state=idle and non-empty accumulated\n * assistant text is DeliverableComplete (typical for direct-model turns).\n * Default false keeps Continue-on-status behaviour.\n */\n treatStatusIdleAsComplete?: boolean;\n}\n\n/** Event type of the daemon's replay completion signal (internal). */\nconst EVENT_LOOP_HISTORY_REPLAYED = \"soothe.lifecycle.loop.history.replayed\";\n\n/** Maps a stream of decoded daemon events into deliverable/streaming/terminal outcomes. */\nexport class EventClassifier {\n private deliverablePhases: ReadonlySet<string>;\n private minDeliverableRunes: number;\n private thinkingStepEvents?: ReadonlySet<string>;\n private treatStatusIdleAsComplete: boolean;\n\n constructor(cfg: ClassifierConfig) {\n if (!cfg.deliverablePhases) {\n throw new Error(\"appkit: ClassifierConfig.deliverablePhases must not be nil\");\n }\n this.deliverablePhases = cfg.deliverablePhases;\n this.minDeliverableRunes =\n cfg.minDeliverableRunes && cfg.minDeliverableRunes > 0 ? cfg.minDeliverableRunes : 8;\n this.thinkingStepEvents = cfg.thinkingStepEvents;\n this.treatStatusIdleAsComplete = Boolean(cfg.treatStatusIdleAsComplete);\n }\n\n /**\n * Inspects one decoded event and returns its outcome. `accumulated` is the\n * running assistant text so far, used to pick the final reply when a\n * deliverable event arrives.\n */\n classify(msg: unknown, accumulated: string): ChatEventResult {\n return this.processChatEvent(msg, accumulated);\n }\n\n /**\n * Reports whether a persisted completion_event is user-facing. Uses the\n * configured deliverable phase set; recognizes the protocol output namespace\n * and final_report component as deliverable.\n */\n isDeliverableCompletionEvent(eventType: string): boolean {\n if (!eventType) return false;\n switch (eventType) {\n case \"status.idle\":\n case \"idle_timeout\":\n case \"query_timeout\":\n case \"stream_closed\":\n return true;\n }\n if (eventType === EventFinalReport) return true;\n if (eventType.startsWith(\"soothe.protocol.message.\")) {\n const phase = eventType.slice(\"soothe.protocol.message.\".length);\n return this.isDeliverableLoopPhase(phase);\n }\n return eventType.includes(\"soothe.output\") && eventType.includes(\"responded\");\n }\n\n isDeliverableLoopPhase(phase: string): boolean {\n return this.deliverablePhases.has(phase);\n }\n\n private deliverableResult(content: string, completionEvent: string): ChatEventResult {\n return { content, terminal: ChatEventTerminal.DeliverableComplete, completionEvent };\n }\n\n private continueResult(content: string): ChatEventResult {\n return { content, terminal: ChatEventTerminal.Continue };\n }\n\n private failedResult(err: Error): ChatEventResult {\n return { terminal: ChatEventTerminal.FailedComplete, err };\n }\n\n /** Reports whether trimmed assistant text is long enough to persist as final. */\n isSubstantiveAssistantReply(content: string): boolean {\n return [...content.trim()].length >= this.minDeliverableRunes;\n }\n\n /**\n * Picks the user-visible reply for a completed query. Only a deliverable\n * terminal result with a recognized completion event yields a final reply.\n */\n resolveDeliverableFinalContent(\n eventResult: ChatEventResult,\n _accumulated: string,\n ): [string, boolean] {\n if (eventResult.terminal !== ChatEventTerminal.DeliverableComplete) return [\"\", false];\n if (!this.isDeliverableCompletionEvent(eventResult.completionEvent ?? \"\")) return [\"\", false];\n const final = (eventResult.content ?? \"\").trim();\n if (final) return [final, true];\n return [\"\", false];\n }\n\n /** The event→outcome mapper, ported from triarch's ProcessChatEvent. */\n private processChatEvent(msg: unknown, accumulated: string): ChatEventResult {\n if (!msg || typeof msg !== \"object\") {\n return { terminal: ChatEventTerminal.Continue };\n }\n const m = msg as Record<string, unknown>;\n const typ = m.type as string | undefined;\n\n // Protocol-1 `next` envelope: the daemon wraps legacy frames in payload.\n if (typ === \"next\") {\n return this.classifyNextEnvelope(m, accumulated);\n }\n\n // Protocol-1 RPC responses / subscription confirmations arrive as\n // response/next/complete envelopes. An `error` envelope is a daemon\n // failure; everything else is a protocol-level ack (not a deliverable).\n if (\n typ === \"response\" ||\n typ === \"complete\" ||\n typ === \"receipt_response\" ||\n typ === \"connection_ack\"\n ) {\n return { terminal: ChatEventTerminal.Continue };\n }\n if (typ === \"status\") {\n if (\n this.treatStatusIdleAsComplete &&\n String(m.state ?? \"\")\n .trim()\n .toLowerCase() === \"idle\" &&\n this.isSubstantiveAssistantReply(accumulated)\n ) {\n return this.deliverableResult(accumulated.trim(), \"status.idle\");\n }\n return { terminal: ChatEventTerminal.Continue };\n }\n if (typ === \"error\") {\n const errObj = (m.error as { code?: number; message?: string; data?: unknown }) ?? {};\n const code = typeof errObj.code === \"number\" ? errObj.code : -32603;\n return this.failedResult(\n new DaemonError(code, errObj.message ?? \"daemon error\", errObj.data),\n );\n }\n\n // Legacy flat-form `event` frame (mode/data at top level).\n if (typ === \"event\") {\n return this.classifyEventPayload(\n (m.namespace as unknown) ?? null,\n (m.mode as string) ?? \"\",\n m.data,\n );\n }\n\n return { terminal: ChatEventTerminal.Continue };\n }\n\n /** Classifies a `next` envelope by projecting its payload. */\n private classifyNextEnvelope(env: Record<string, unknown>, accumulated: string): ChatEventResult {\n const payload = (env.payload as Record<string, unknown> | undefined) ?? {};\n // The inner event frame lives in payload.data, with its own mode/data.\n const innerData = payload.data as Record<string, unknown> | undefined;\n if (innerData && typeof innerData === \"object\") {\n const innerType = (innerData.type as string) ?? \"\";\n if (innerType === \"status\") {\n return this.processChatEvent(innerData, accumulated);\n }\n const innerMode = (innerData.mode as string) ?? \"\";\n if (innerMode) {\n return this.classifyEventPayload(\n (innerData.namespace as unknown) ?? payload.namespace ?? null,\n innerMode,\n innerData.data,\n );\n }\n }\n // Fallback: payload itself carries mode/data directly.\n const mode = (payload.mode as string) ?? \"\";\n if (mode === \"status\" || mode === \"\") {\n if (typeof payload.state === \"string\" || (innerData && \"state\" in (innerData ?? {}))) {\n return this.processChatEvent({ type: \"status\", ...(innerData ?? payload) }, accumulated);\n }\n }\n if (mode) {\n return this.classifyEventPayload((payload.namespace as unknown) ?? null, mode, payload.data);\n }\n return { terminal: ChatEventTerminal.Continue };\n }\n\n /**\n * Classifies an event payload by (namespace, mode, phase). `data` may be a\n * map or an array of messages (mode=\"messages\").\n */\n private classifyEventPayload(namespace: unknown, mode: string, data: unknown): ChatEventResult {\n // Normalize namespace to a string for matching.\n const ns = namespaceToString(namespace);\n\n // Normalize data to a map for thinking-step / output extraction.\n const dataMap = normalizeEventData(data);\n\n if (dataMap) {\n let dataType = ns;\n const dt = dataMap[\"type\"];\n if (typeof dt === \"string\" && dt) dataType = dt;\n if (dataType === EVENT_LOOP_HISTORY_REPLAYED) {\n return { terminal: ChatEventTerminal.Continue };\n }\n const [step, ok] = extractThinkingStep(dataType, dataMap, this.thinkingStepEvents);\n if (ok) {\n return { thinkingStep: step, terminal: ChatEventTerminal.Continue };\n }\n }\n\n // mode=\"messages\": assistant content (streaming chunks or deliverable).\n if (mode === \"messages\") {\n const result = this.classifyMessagesMode(data, ns);\n if (result) return result;\n }\n\n if (!dataMap) {\n return { terminal: ChatEventTerminal.Continue };\n }\n\n let dataType = ns;\n const dt = dataMap[\"type\"];\n if (typeof dt === \"string\" && dt) dataType = dt;\n let completionEvent = dataType;\n if (!completionEvent) completionEvent = ns;\n\n // soothe.output / responded namespaces.\n if (\n isNamespaceMatch(ns, dataType, \"soothe.output\") ||\n isNamespaceMatch(ns, dataType, \"responded\")\n ) {\n const [content, ok] = extractContentFromData(dataMap);\n if (ok) {\n if (this.isFinalOutputEvent(dataType, ns)) {\n return this.deliverableResult(content, completionEvent);\n }\n return this.continueResult(content);\n }\n }\n\n if (\n isNamespaceMatch(ns, dataType, \"agent_loop.completed\") ||\n isNamespaceMatch(ns, dataType, \"agent_loop.reasoned\") ||\n isNamespaceMatch(ns, dataType, \"loop.completed\")\n ) {\n const [content, ok] = extractContentFromData(dataMap);\n if (ok) return this.continueResult(content);\n }\n\n if (isNamespaceMatch(ns, dataType, \"final_report\")) {\n const [content, ok] = extractContentFromData(dataMap);\n if (ok) return this.deliverableResult(content, completionEvent);\n }\n\n if (dataType.includes(\"soothe.error.\") || ns.includes(\"soothe.error.\")) {\n const errType = dataType || ns;\n const msg = dataMap[\"message\"];\n if (typeof msg === \"string\" && msg) {\n return this.failedResult(new Error(`${errType}: ${msg}`));\n }\n const [content, ok] = extractContentFromData(dataMap);\n if (ok) return this.failedResult(new Error(`${errType}: ${content}`));\n return this.failedResult(new Error(errType));\n }\n\n if (\n isNamespaceMatch(ns, dataType, \"stream\") ||\n isNamespaceMatch(ns, dataType, \"progress\") ||\n isNamespaceMatch(ns, dataType, \"tool_call_updates_batch\") ||\n isNamespaceMatch(ns, dataType, \"soothe.stream.tool_call.update\")\n ) {\n const delta = dataMap[\"delta\"];\n if (typeof delta === \"string\") return this.continueResult(delta);\n }\n\n if (\n isNamespaceMatch(ns, dataType, \"heartbeat\") ||\n isNamespaceMatch(ns, dataType, \"system.daemon\") ||\n isNamespaceMatch(ns, dataType, \"agent_loop.started\") ||\n isNamespaceMatch(ns, dataType, \"intent.classified\")\n ) {\n return { terminal: ChatEventTerminal.Continue };\n }\n\n return { terminal: ChatEventTerminal.Continue };\n }\n\n /** Classifies a mode=\"messages\" payload (array of message objects). */\n private classifyMessagesMode(data: unknown, _ns: string): ChatEventResult | null {\n const items = Array.isArray(data) ? data : null;\n if (!items || items.length === 0) return null;\n const first = items[0];\n if (!first || typeof first !== \"object\") return null;\n\n const [msgType, rawContent, phase, hasPayload] = firstMessagePayload(data);\n if (hasPayload && rawContent && isStreamingMessageType(msgType)) {\n return this.continueResult(rawContent);\n }\n\n // Loop-tagged assistant message.\n const loopMsg = loopAIMessage(data);\n if (loopMsg) {\n const content = loopMsg.content;\n if (content) {\n if (isStreamingMessageType(loopMsg.type)) {\n return this.continueResult(content);\n }\n if (\n this.isDeliverableLoopPhase(loopMsg.phase) &&\n this.isSubstantiveAssistantReply(content)\n ) {\n return this.deliverableResult(content, \"soothe.protocol.message.\" + loopMsg.phase);\n }\n return this.continueResult(content);\n }\n }\n\n // Direct-LLM assistant content (mode=messages, terminal AIMessage, no phase).\n const [directContent, directOk] = this.messagesModeAssistantContent(data);\n if (directOk && this.isSubstantiveAssistantReply(directContent)) {\n return this.deliverableResult(directContent, \"soothe.protocol.message.direct_model\");\n }\n\n if (hasPayload && rawContent) {\n if (isTerminalMessageType(msgType) || msgType === \"\") {\n if (this.isDeliverableLoopPhase(phase) && this.isSubstantiveAssistantReply(rawContent)) {\n return this.deliverableResult(rawContent, \"soothe.protocol.message.\" + phase);\n }\n return this.continueResult(rawContent);\n }\n return this.continueResult(rawContent);\n }\n return null;\n }\n\n /**\n * Extracts plain assistant text from mode=\"messages\" events that carry a\n * terminal AIMessage without loop-tagged phase metadata (legacy direct_llm turns\n * before phase tagging; prefer deliverablePhases including text_completion).\n */\n private messagesModeAssistantContent(data: unknown): [string, boolean] {\n if (!Array.isArray(data) || data.length === 0) return [\"\", false];\n const msgMap = data[0] as Record<string, unknown>;\n if (!msgMap || typeof msgMap !== \"object\") return [\"\", false];\n const phase = typeof msgMap.phase === \"string\" ? msgMap.phase.trim() : \"\";\n if (phase) return [\"\", false];\n const msgType = typeof msgMap.type === \"string\" ? msgMap.type : \"\";\n if (msgType && !isTerminalMessageType(msgType)) return [\"\", false];\n const content = extractContentFromMessage(msgMap).trim();\n if (!content) return [\"\", false];\n return [content, true];\n }\n\n /** soothe output/responded events that carry user-facing final text. */\n private isFinalOutputEvent(dataType: string, ns: string): boolean {\n const combined = dataType + \" \" + ns;\n if (combined.includes(\"final_report\")) return true;\n for (const phase of this.deliverablePhases) {\n if (combined.includes(phase)) return true;\n }\n return false;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers (module-private)\n// ---------------------------------------------------------------------------\n\nfunction isStreamingMessageType(msgType: string): boolean {\n return msgType === \"AIMessageChunk\" || msgType === \"ai_chunk\" || msgType === \"message_chunk\";\n}\n\nfunction isTerminalMessageType(msgType: string): boolean {\n return msgType === \"AIMessage\" || msgType === \"ai\" || msgType === \"assistant\";\n}\n\n/** Extracts the first message's (type, content, phase, hasPayload). */\nfunction firstMessagePayload(data: unknown): [string, string, string, boolean] {\n if (!Array.isArray(data) || data.length === 0) return [\"\", \"\", \"\", false];\n const msgMap = data[0] as Record<string, unknown>;\n if (!msgMap || typeof msgMap !== \"object\") return [\"\", \"\", \"\", false];\n const msgType = typeof msgMap.type === \"string\" ? msgMap.type : \"\";\n const phase = typeof msgMap.phase === \"string\" ? msgMap.phase : \"\";\n const content = extractContentFromMessage(msgMap);\n return [msgType, content, phase, true];\n}\n\n/** Extracts a loop-tagged assistant message (type, content, phase). */\nfunction loopAIMessage(data: unknown): { type: string; content: string; phase: string } | null {\n if (!Array.isArray(data) || data.length === 0) return null;\n const msgMap = data[0] as Record<string, unknown>;\n if (!msgMap || typeof msgMap !== \"object\") return null;\n const phase = typeof msgMap.phase === \"string\" ? msgMap.phase.trim() : \"\";\n if (!phase) return null;\n const type = typeof msgMap.type === \"string\" ? msgMap.type : \"\";\n const content = extractContentFromMessage(msgMap);\n return { type, content, phase };\n}\n\nfunction extractContentFromMessage(msgMap: Record<string, unknown>): string {\n const c = msgMap.content;\n if (typeof c === \"string\" && c) return c;\n if (Array.isArray(c) && c.length > 0) {\n let b = \"\";\n for (const item of c) {\n if (typeof item === \"string\") {\n b += item;\n continue;\n }\n if (item && typeof item === \"object\") {\n const blk = item as Record<string, unknown>;\n const t = blk.text;\n if (typeof t === \"string\") b += t;\n }\n }\n return b;\n }\n const blocks = msgMap.content_blocks;\n if (Array.isArray(blocks) && blocks.length > 0) {\n let b = \"\";\n for (const blk of blocks) {\n if (blk && typeof blk === \"object\") {\n const m = blk as Record<string, unknown>;\n const t = m.text;\n if (typeof t === \"string\") b += t;\n }\n }\n return b;\n }\n return \"\";\n}\n\nfunction extractContentFromData(data: Record<string, unknown>): [string, boolean] {\n for (const key of [\n \"final_stdout_message\",\n \"completion_summary\",\n \"content\",\n \"text\",\n \"response\",\n \"output\",\n \"message\",\n \"report\",\n ]) {\n const val = data[key];\n if (typeof val === \"string\" && val) return [val, true];\n }\n const nested = data.data;\n if (nested && typeof nested === \"object\") {\n const nm = nested as Record<string, unknown>;\n for (const key of [\n \"final_stdout_message\",\n \"completion_summary\",\n \"content\",\n \"text\",\n \"response\",\n \"output\",\n \"message\",\n \"report\",\n ]) {\n const val = nm[key];\n if (typeof val === \"string\" && val) return [val, true];\n }\n }\n return [\"\", false];\n}\n\nfunction isNamespaceMatch(ns: string, dataType: string, pattern: string): boolean {\n return dataType.includes(pattern) || ns.includes(pattern);\n}\n\n/** Normalizes a namespace value (string or string[]) to a dotted string. */\nfunction namespaceToString(namespace: unknown): string {\n if (typeof namespace === \"string\") return namespace;\n if (Array.isArray(namespace)) return namespace.filter(s => typeof s === \"string\").join(\".\");\n return \"\";\n}\n\n/** Normalizes event data to a map. Strings are parsed as JSON. */\nfunction normalizeEventData(data: unknown): Record<string, unknown> | null {\n if (data == null) return null;\n if (typeof data === \"object\" && !Array.isArray(data)) {\n return data as Record<string, unknown>;\n }\n if (typeof data === \"string\") {\n try {\n const m = JSON.parse(data);\n if (m && typeof m === \"object\" && !Array.isArray(m)) return m;\n } catch {\n return null;\n }\n }\n return null;\n}\n\n// Re-export for callers that want the default allowlist.\nexport { DEFAULT_THINKING_STEP_EVENTS };\n","/**\n * Thinking-step extraction for appkit (RFC-629 Layer 1).\n *\n * Maps an allowlisted progress event to one structured UI line. Free-form\n * streams (tokens, reports, reasoning) are excluded. Ported from the Go\n * appkit's thinking_step with the allowlist made configurable.\n */\n\nconst MAX_THINKING_STEP_RUNES = 280;\n\n/** Default thinking-step event allowlist (triarch's set). */\nexport const DEFAULT_THINKING_STEP_EVENTS: ReadonlySet<string> = new Set([\n \"soothe.cognition.plan.step.started\",\n \"soothe.cognition.plan.step.completed\",\n \"soothe.cognition.plan.step.failed\",\n \"soothe.lifecycle.iteration.started\",\n \"soothe.agent.loop.step.started\",\n \"soothe.agent.loop.started\",\n \"soothe.cognition.plan.batch.started\",\n \"soothe.cognition.plan.created\",\n \"soothe.cognition.goal.created\",\n \"soothe.tool.execution.started\",\n]);\n\n/**\n * Maps an allowlisted progress event to one structured UI line. Returns\n * [line, true] for a recognized event; [\"\", false] otherwise. `allow` may be\n * omitted to use the default allowlist.\n */\nexport function extractThinkingStep(\n eventType: string,\n data: Record<string, unknown> | null,\n allow?: ReadonlySet<string>,\n): [string, boolean] {\n if (!eventType || !data) return [\"\", false];\n const et = eventType.trim();\n if (!et) return [\"\", false];\n\n const allowlist = allow ?? DEFAULT_THINKING_STEP_EVENTS;\n if (!allowlist.has(et)) return [\"\", false];\n\n let line = \"\";\n switch (et) {\n case \"soothe.cognition.plan.step.started\":\n line = formatPlanStepLine(data, \"\");\n break;\n case \"soothe.cognition.plan.step.completed\":\n line = formatPlanStepLine(data, \"done\");\n break;\n case \"soothe.cognition.plan.step.failed\": {\n const stepID = strField(data, \"step_id\");\n const errMsg = strField(data, \"error\");\n if (stepID && errMsg) line = `Step ${stepID} failed: ${errMsg}`;\n else if (stepID) line = `Step ${stepID} failed`;\n else if (errMsg) line = `Step failed: ${errMsg}`;\n break;\n }\n case \"soothe.agent.loop.step.started\":\n line = formatAgentStepLine(data, \"\");\n break;\n case \"soothe.cognition.plan.batch.started\": {\n const n = data[\"parallel_count\"];\n if (typeof n === \"number\" && n > 0) line = `Running ${Math.floor(n)} steps in parallel`;\n break;\n }\n case \"soothe.cognition.plan.created\":\n case \"soothe.agent.loop.started\": {\n const g = strField(data, \"goal\");\n if (g) line = \"Goal: \" + g;\n break;\n }\n case \"soothe.cognition.goal.created\": {\n const g = strField(data, \"friendly_message\", \"description\");\n if (g) line = \"Goal: \" + g;\n break;\n }\n case \"soothe.lifecycle.iteration.started\": {\n const g = strField(data, \"goal_description\");\n if (g) line = \"Iteration: \" + g;\n break;\n }\n case \"soothe.tool.execution.started\": {\n const name = strField(data, \"tool_name\", \"name\");\n if (name) line = \"Tool: \" + name;\n break;\n }\n default:\n return [\"\", false];\n }\n\n line = line.trim();\n if (!line) return [\"\", false];\n const runes = [...line];\n if (runes.length > MAX_THINKING_STEP_RUNES) {\n line = runes.slice(0, MAX_THINKING_STEP_RUNES).join(\"\") + \"…\";\n }\n return [line, true];\n}\n\nfunction formatPlanStepLine(data: Record<string, unknown>, suffix: string): string {\n const stepID = strField(data, \"step_id\");\n const desc = strField(data, \"description\");\n if (stepID && suffix) return `Step ${stepID}: ${suffix}`;\n if (stepID && desc) return `Step ${stepID}: ${desc}`;\n if (stepID) return `Step ${stepID}`;\n if (desc && suffix) return `Step: ${suffix}`;\n if (desc) return `Step: ${desc}`;\n if (suffix) return \"Step: \" + suffix;\n return \"\";\n}\n\nfunction formatAgentStepLine(data: Record<string, unknown>, suffix: string): string {\n const stepID = strField(data, \"step_id\");\n const desc = strField(data, \"description\");\n if (stepID && desc) return `Step ${stepID}: ${desc}`;\n if (desc) return suffix ? `Step: ${suffix}` : `Step: ${desc}`;\n if (stepID) return `Step ${stepID}`;\n return \"\";\n}\n\n/** Returns the first non-empty trimmed string field among `keys`. */\nfunction strField(data: Record<string, unknown>, ...keys: string[]): string {\n for (const key of keys) {\n const v = data[key];\n if (typeof v === \"string\") {\n const s = v.trim();\n if (s) return s;\n }\n }\n return \"\";\n}\n","/**\n * Single-flight query gate for appkit (RFC-629 Layer 1).\n *\n * Enforces single-flight query execution per session id and the\n * cancel-before-context ordering: when a query is cancelled, the daemon is\n * told to stop (command_request{command:\"cancel\"}) BEFORE the local abort\n * signal is cancelled, on a detached timeout so the caller's cancellation\n * cannot block the wire send.\n *\n * The app-agnostic successor to triarch's AcquireQuery/CancelQuery/\n * sendLoopCancelCommand.\n */\n\n/** Returned when a session already has an in-flight query. */\nexport class ErrQueryBusy extends Error {\n constructor() {\n super(\"appkit: query already in progress for session\");\n this.name = \"ErrQueryBusy\";\n }\n}\n\ninterface QueryState {\n /** Local abort for the query's timeout context. */\n abort: AbortController;\n /** Daemon-cancel sender (sends command_request{cancel} for the loop). */\n sendCancel: ((signal: AbortSignal) => Promise<void>) | null;\n}\n\n/**\n * QueryGate enforces single-flight query execution per session id.\n */\nexport class QueryGate {\n private active = new Map<string, QueryState>();\n\n /** Constructs an empty gate. */\n constructor() {}\n\n /**\n * Reserves sessionID for one agent turn. Returns ErrQueryBusy if a query is\n * already in flight. `abort` is the AbortController for the query's timeout\n * context. `sendCancel` is the daemon-cancel sender; it is invoked from\n * `cancel()` on a detached 10s timeout.\n */\n acquire(\n sessionID: string,\n abort: AbortController,\n sendCancel: ((signal: AbortSignal) => Promise<void>) | null,\n ): void {\n if (this.active.has(sessionID)) {\n throw new ErrQueryBusy();\n }\n this.active.set(sessionID, { abort, sendCancel });\n }\n\n /**\n * Cooperatively stops a running query for sessionID. Sends the daemon cancel\n * (on a detached 10s-timeout abort so caller cancellation cannot block the\n * wire send) BEFORE aborting the local context. Returns silently if no query\n * is in flight (intent already satisfied).\n */\n async cancel(sessionID: string): Promise<void> {\n const state = this.active.get(sessionID);\n if (!state) return;\n this.active.delete(sessionID);\n\n if (state.sendCancel) {\n const detached = new AbortController();\n const timer = setTimeout(() => detached.abort(), 10_000);\n try {\n await state.sendCancel(detached.signal);\n } catch {\n // Log but proceed to local cancel; the query is still stopping locally.\n } finally {\n clearTimeout(timer);\n }\n }\n state.abort.abort();\n }\n\n /**\n * Clears the gate for sessionID without sending a daemon cancel. Call when a\n * query completes normally (success or local failure) so the next turn can\n * acquire.\n */\n release(sessionID: string): void {\n this.active.delete(sessionID);\n }\n\n /** Reports whether a query is in flight for sessionID. */\n isActive(sessionID: string): boolean {\n return this.active.has(sessionID);\n }\n}\n","/**\n * Per-session connection pool for appkit (RFC-629 Layer 1).\n *\n * Manages a pool of daemon connections, one active per session. Reuses an\n * active connection when still live, otherwise bootstraps a fresh loop\n * (loop_new + subscribe) or reattaches an existing one (loop_reattach +\n * subscribe + reattachAndProbe). Persistence of session↔loop mappings is\n * abstracted behind SessionStore.\n *\n * The app-agnostic successor to triarch's SoothePoolManager connection\n * mechanics.\n */\n\nimport { StaleLoopError } from \"../errors.js\";\nimport type { Config } from \"../config.js\";\nimport { defaultConfig } from \"../config.js\";\nimport type { DecodedMessage } from \"../protocol.js\";\nimport type { SessionStore } from \"./session_store.js\";\nimport {\n type BootstrapFunc,\n type ClientFactory,\n type ManagedClient,\n defaultBootstrapFunc,\n defaultClientFactory,\n} from \"./client.js\";\n\n/** Returned when no free connection slot is available. */\nexport class ErrPoolExhausted extends Error {\n constructor() {\n super(\"appkit: connection pool exhausted\");\n this.name = \"ErrPoolExhausted\";\n }\n}\n\n/** Configures a ConnectionPool. Zero values use defaults. */\nexport interface PoolConfig {\n poolSize: number;\n queryTimeout: number; // ms\n connectionTimeout: number; // ms\n maxIdleTime: number; // ms\n healthCheckInterval: number; // ms\n}\n\n/** Returns env-overridable defaults (mirrors triarch).\n * `maxIdleTime` is enforced on acquire; `healthCheckInterval` is reserved. */\nexport function defaultPoolConfig(): PoolConfig {\n return {\n poolSize: 1000,\n queryTimeout: 30 * 60 * 1000,\n connectionTimeout: 30_000,\n maxIdleTime: 10 * 60 * 1000,\n healthCheckInterval: 30_000,\n };\n}\n\n/** One connection slot in the pool. */\nexport class PooledConn {\n slotID: number;\n client: ManagedClient;\n eventStream: AsyncGenerator<DecodedMessage> | null = null;\n streamController: AbortController | null = null;\n sessionID = \"\";\n loopID = \"\";\n workspaceID = \"\";\n lastUsed = 0;\n\n constructor(slotID: number, client: ManagedClient) {\n this.slotID = slotID;\n this.client = client;\n }\n\n /** Reports whether the underlying client signalled a drop. */\n isDisconnected(): boolean {\n return this.client.isDisconnected();\n }\n\n isConnected(): boolean {\n return this.client.isConnected() && !this.isDisconnected();\n }\n\n getLoopID(): string {\n return this.loopID;\n }\n}\n\n/**\n * ConnectionPool manages a pool of daemon connections, one active per session.\n */\nexport class ConnectionPool {\n private cfg: PoolConfig;\n private scfg: Config;\n private factory: ClientFactory;\n private bootstrap: BootstrapFunc;\n private store: SessionStore;\n private pool: PooledConn[] = [];\n private activeSlots = new Map<string, PooledConn>();\n private nextSlotID = 1;\n private url: string;\n\n /**\n * Constructs a pool. `url` is the daemon WebSocket URL. If cfg is null,\n * defaultPoolConfig is used; if scfg is null, defaultConfig is used; nil\n * factory/bootstrap fall back to the defaults.\n */\n constructor(\n url: string,\n store: SessionStore,\n cfg?: PoolConfig | null,\n scfg?: Config | null,\n factory?: ClientFactory | null,\n ) {\n this.cfg = cfg ?? defaultPoolConfig();\n this.scfg = scfg ?? defaultConfig();\n this.factory = factory ?? defaultClientFactory();\n this.bootstrap = defaultBootstrapFunc();\n this.store = store;\n this.url = url;\n // Pre-seed the pool with up to poolSize slots.\n for (let i = 0; i < this.cfg.poolSize; i++) {\n this.pool.push(new PooledConn(this.nextSlotID++, this.factory(url, this.scfg)));\n }\n }\n\n /** Overrides the loop bootstrap function (useful for test fakes). */\n withBootstrap(f: BootstrapFunc): ConnectionPool {\n if (f) this.bootstrap = f;\n return this;\n }\n\n /**\n * Returns a live connection for sessionID, reusing an active slot or\n * bootstrapping/reattaching as needed. The caller must call `release()`\n * when done with the connection (a turn completes or the session is reset).\n */\n async acquire(\n sessionID: string,\n workspaceID: string,\n userID: string,\n _signal?: AbortSignal,\n ): Promise<PooledConn> {\n // 1. Reuse active connection when still live.\n const existing = this.activeSlots.get(sessionID);\n if (existing) {\n if (existing.isDisconnected() || !existing.isConnected()) {\n await this.release(sessionID);\n } else {\n const idleTooLong =\n this.cfg.maxIdleTime > 0 &&\n existing.lastUsed > 0 &&\n Date.now() - existing.lastUsed > this.cfg.maxIdleTime;\n if (idleTooLong) {\n await this.release(sessionID);\n } else {\n existing.lastUsed = Date.now();\n await this.store.updateLastUsed(sessionID).catch(() => {});\n return existing;\n }\n }\n }\n\n // 2. Pull a slot from the pool.\n const conn = this.pool.pop();\n if (!conn) throw new ErrPoolExhausted();\n this.activeSlots.set(sessionID, conn);\n\n const { loopID, ok } = await this.store\n .getLoopIDForSession(sessionID)\n .catch(() => ({ loopID: \"\", ok: false }));\n let finalLoopID = \"\";\n try {\n if (!ok || !loopID) {\n // Fresh bootstrap.\n await conn.client.connect();\n finalLoopID = await this.bootstrapNew(conn, workspaceID, userID);\n await this.store.createSession(workspaceID, sessionID, finalLoopID, \"\").catch(() => {});\n } else {\n // Reattach.\n try {\n await this.resumeAndReattach(conn, loopID);\n finalLoopID = loopID;\n } catch {\n // Reattach failed (incl. StaleLoopError) → fresh bootstrap.\n await conn.client.connect();\n finalLoopID = await this.bootstrapNew(conn, workspaceID, userID);\n await this.store.createSession(workspaceID, sessionID, finalLoopID, \"\").catch(() => {});\n }\n }\n } catch (err) {\n await this.release(sessionID);\n throw err;\n }\n\n conn.sessionID = sessionID;\n conn.loopID = finalLoopID;\n conn.workspaceID = workspaceID;\n conn.lastUsed = Date.now();\n await this.store.updateLastUsed(sessionID).catch(() => {});\n return conn;\n }\n\n /** Tears down the connection for sessionID and returns the slot. */\n async release(sessionID: string): Promise<void> {\n const conn = this.activeSlots.get(sessionID);\n if (!conn) return;\n this.activeSlots.delete(sessionID);\n if (conn.streamController) {\n conn.streamController.abort();\n conn.streamController = null;\n }\n try {\n conn.client.close();\n } catch {\n // ignore\n }\n conn.sessionID = \"\";\n conn.loopID = \"\";\n conn.eventStream = null;\n // Return a fresh slot to the pool (the closed client is spent).\n this.pool.push(new PooledConn(this.nextSlotID++, this.factory(this.url, this.scfg)));\n }\n\n /**\n * Tears down the connection for sessionID so the next acquire bootstraps\n * fresh. The store should archive the loop id so getLoopIDForSession returns\n * false next time.\n */\n async resetSession(sessionID: string): Promise<void> {\n await this.release(sessionID);\n }\n\n /** Gracefully shuts down all active connections. */\n stop(): void {\n for (const [sid, conn] of this.activeSlots) {\n if (conn.streamController) conn.streamController.abort();\n try {\n conn.client.close();\n } catch {\n // ignore\n }\n this.activeSlots.delete(sid);\n }\n }\n\n /** Stats snapshot for observability. */\n stats(): { active: number; idle: number } {\n return { active: this.activeSlots.size, idle: this.pool.length };\n }\n\n /** Bootstrap a fresh loop and start the reader. */\n private async bootstrapNew(\n conn: PooledConn,\n workspaceID: string,\n userID: string,\n ): Promise<string> {\n const loopID = await this.bootstrap(conn.client, workspaceID, userID, this.scfg);\n this.startReader(conn);\n return loopID;\n }\n\n /** Reconnect + reattach an existing loop, then start the reader. */\n private async resumeAndReattach(conn: PooledConn, loopID: string): Promise<void> {\n await conn.client.connect();\n try {\n await conn.client.reattachAndProbe(loopID);\n } catch (err) {\n if (err instanceof StaleLoopError) throw err;\n throw err;\n }\n this.startReader(conn);\n }\n\n /** Starts a receiveMessages generator and stores the stream + controller. */\n private startReader(conn: PooledConn): void {\n const controller = new AbortController();\n conn.streamController = controller;\n conn.eventStream = conn.client.receiveMessages(controller.signal);\n }\n}\n","/**\n * ManagedClient — the subset of the core Client that appkit's ConnectionPool\n * and TurnRunner depend on (RFC-629 Layer 1).\n *\n * The concrete `Client` satisfies it; tests supply a fake. Defining it as an\n * interface lets appkit be unit-tested without a live WebSocket daemon.\n */\n\nimport type { Client, InputOptions } from \"../client.js\";\nimport type { Config } from \"../config.js\";\nimport type { DecodedMessage } from \"../protocol.js\";\nimport type { DisconnectCause } from \"../errors.js\";\n\n/**\n * ManagedClient is the subset of the core Client that appkit depends on.\n * Methods are async (TS) rather than channel-based (Go).\n */\nexport interface ManagedClient {\n /** Dials and handshakes. */\n connect(): Promise<void>;\n /** Re-dials after a drop. */\n reconnect(): Promise<void>;\n /** Resumes a loop by id and probes liveness. */\n reattachAndProbe(loopID: string): Promise<void>;\n /** Sends a fire-and-forget notification (e.g. loop_input). */\n sendMessage(msg: unknown): Promise<void>;\n /** Sends user input to the daemon (loop_input notification). */\n sendInput(text: string, options?: InputOptions): Promise<void>;\n /** Starts the read loop, returning the event stream. */\n receiveMessages(signal?: AbortSignal): AsyncGenerator<DecodedMessage>;\n /** Returns whether the connection has dropped. */\n isDisconnected(): boolean;\n /** Returns the drop cause, or null if not dropped. */\n disconnectCause(): DisconnectCause | null;\n /** Reports connection liveness. */\n isConnected(): boolean;\n /** Tears down the connection. */\n close(): void;\n}\n\n/**\n * Builds a fresh ManagedClient for a daemon URL and config. ConnectionPool\n * calls it per pooled connection. Applications may supply a custom factory\n * (e.g. wrapping Client with logging/metrics).\n */\nexport type ClientFactory = (url: string, config?: Config) => ManagedClient;\n\nimport { defaultConfig } from \"../config.js\";\nimport { Client as CoreClient } from \"../client.js\";\n\n/** Returns a ClientFactory that builds a core Client. */\nexport function defaultClientFactory(): ClientFactory {\n return (url: string, config?: Config) => {\n return new CoreClient(url, config ?? defaultConfig()) as unknown as ManagedClient;\n };\n}\n\n/**\n * Creates a new loop (loop_new + subscribe) on a connected client and returns\n * the new loop id. The default implementation calls bootstrapLoopSession;\n * apps may override it.\n */\nexport type BootstrapFunc = (\n client: ManagedClient,\n workspaceID: string,\n userID: string,\n config?: Config,\n) => Promise<string>;\n\nimport { bootstrapLoopSession } from \"../session.js\";\nimport type { LoopNewOptions } from \"../protocol.js\";\n\n/** Default bootstrap: loop_new + subscribe(loop_events). */\nexport function defaultBootstrapFunc(): BootstrapFunc {\n return async (client: ManagedClient, workspaceID: string, userID: string, config?: Config) => {\n // bootstrapLoopSession expects a Client; cast through unknown.\n const c = client as unknown as Client;\n const opts: LoopNewOptions = {\n client_workspace: workspaceID,\n user_id: userID,\n client_workspace_id: workspaceID,\n };\n return bootstrapLoopSession(c, \"\", config, opts);\n };\n}\n","/**\n * Attachment image compaction for appkit (Go IG-651 / SIL-04 parity).\n *\n * When `sharp` is installed (optionalDependency), oversized image/* payloads\n * are downscaled. Without sharp, attachments pass through unchanged.\n */\n\nexport interface CompactImageOptions {\n /** Max width or height in pixels. Default 768. */\n maxDim?: number;\n /** JPEG encode quality 1–100. Default 85. */\n jpegQuality?: number;\n}\n\nfunction compactDefaults(opts?: CompactImageOptions | null): { maxDim: number; quality: number } {\n return {\n maxDim: opts?.maxDim && opts.maxDim > 0 ? opts.maxDim : 768,\n quality: opts?.jpegQuality && opts.jpegQuality > 0 ? opts.jpegQuality : 85,\n };\n}\n\ntype SharpModule = {\n default: (\n input: Buffer,\n options?: { failOn?: string },\n ) => {\n metadata: () => Promise<{ width?: number; height?: number }>;\n resize: (\n w: number,\n h: number,\n opts?: { fit?: string },\n ) => {\n png: () => { toBuffer: () => Promise<Buffer> };\n jpeg: (opts?: { quality?: number }) => { toBuffer: () => Promise<Buffer> };\n };\n };\n};\n\nlet sharpLoader: Promise<SharpModule | null> | null = null;\n\nasync function loadSharp(): Promise<SharpModule | null> {\n if (!sharpLoader) {\n sharpLoader = (async () => {\n try {\n const m = await (Function('return import(\"sharp\")')() as Promise<{ default: unknown }>);\n return m as unknown as SharpModule;\n } catch {\n return null;\n }\n })();\n }\n return sharpLoader;\n}\n\n/**\n * Downscales image/* payloads when either dimension exceeds MaxDim.\n * Non-images and decode failures pass through unchanged.\n * PNG stays PNG; other image types re-encode as JPEG when sharp is available.\n */\nexport async function compactImageAttachment(\n mimeType: string,\n dataB64: string,\n opts?: CompactImageOptions | null,\n): Promise<[string, string]> {\n if (!dataB64 || !mimeType.startsWith(\"image/\")) {\n return [mimeType, dataB64];\n }\n let raw: Buffer;\n try {\n raw = Buffer.from(dataB64, \"base64\");\n } catch {\n return [mimeType, dataB64];\n }\n if (raw.length === 0) return [mimeType, dataB64];\n\n const sharpMod = await loadSharp();\n if (!sharpMod) return [mimeType, dataB64];\n\n const { maxDim, quality } = compactDefaults(opts);\n try {\n const img = sharpMod.default(raw, { failOn: \"none\" });\n const meta = await img.metadata();\n const w = meta.width ?? 0;\n const h = meta.height ?? 0;\n if (w <= 0 || h <= 0 || (w <= maxDim && h <= maxDim)) {\n return [mimeType, dataB64];\n }\n let nw = w;\n let nh = h;\n if (w >= h) {\n if (w > maxDim) {\n nw = maxDim;\n nh = Math.max(1, Math.round((h * maxDim) / w));\n }\n } else if (h > maxDim) {\n nh = maxDim;\n nw = Math.max(1, Math.round((w * maxDim) / h));\n }\n const resized = img.resize(nw, nh, { fit: \"fill\" });\n if (mimeType === \"image/png\") {\n const buf = await resized.png().toBuffer();\n return [mimeType, buf.toString(\"base64\")];\n }\n const buf = await resized.jpeg({ quality }).toBuffer();\n return [\"image/jpeg\", buf.toString(\"base64\")];\n } catch {\n return [mimeType, dataB64];\n }\n}\n\n/**\n * Applies compactImageAttachment to each attachment map with mime_type + data.\n */\nexport async function compactAttachments(\n atts: Record<string, unknown>[],\n opts?: CompactImageOptions | null,\n): Promise<Record<string, unknown>[]> {\n if (!atts.length) return atts;\n const out: Record<string, unknown>[] = [];\n for (const att of atts) {\n const cp: Record<string, unknown> = { ...att };\n const mime = typeof cp.mime_type === \"string\" ? cp.mime_type : \"\";\n const data = typeof cp.data === \"string\" ? cp.data : \"\";\n if (mime && data) {\n const [outMime, outData] = await compactImageAttachment(mime, data, opts);\n cp.mime_type = outMime;\n cp.data = outData;\n }\n out.push(cp);\n }\n return out;\n}\n","/**\n * Turn runner for appkit (RFC-629 Layer 1).\n *\n * Executes one query turn end-to-end: acquire a pooled connection, enforce\n * single-flight, send loop_input, consume the event stream, classify events,\n * resolve the deliverable, persist the reply, and broadcast completion.\n *\n * Supports IG-651 / SIL-04 lifecycle knobs: idle timeout, soft-complete\n * policies, attachment compaction, and stream-close soft-complete.\n */\n\nimport type { PooledConn } from \"./pool.js\";\nimport { type ConnectionPool } from \"./pool.js\";\nimport { type EventClassifier, ChatEventTerminal } from \"./classifier.js\";\nimport { type QueryGate } from \"./query_gate.js\";\nimport { type SSEBroadcaster, SSEEvent } from \"./broadcaster.js\";\nimport type { SessionStore, SessionMessage } from \"./session_store.js\";\nimport type { LoopInputIntentHint } from \"../intent_hints.js\";\nimport { validateLoopInputIntentHint } from \"../intent_hints.js\";\nimport type { DecodedMessage } from \"../protocol.js\";\nimport { compactAttachments, type CompactImageOptions } from \"./attachments.js\";\n\n/** Returned when a turn exceeds the configured timeout and policy is Fail. */\nexport class ErrQueryTimeout extends Error {\n constructor() {\n super(\"appkit: query timeout\");\n this.name = \"ErrQueryTimeout\";\n }\n}\n\n/** Returned when no events arrive within IdleTimeout and policy is Fail. */\nexport class ErrIdleTimeout extends Error {\n constructor() {\n super(\"appkit: idle timeout\");\n this.name = \"ErrIdleTimeout\";\n }\n}\n\n/** Selects fail vs soft-complete behaviour for idle, query, and stream-close. */\nexport enum TimeoutPolicy {\n Fail = 0,\n SoftComplete = 1,\n}\n\nexport type StreamClosePolicy = TimeoutPolicy;\nexport const StreamCloseFail = TimeoutPolicy.Fail;\nexport const StreamCloseSoftComplete = TimeoutPolicy.SoftComplete;\n\n/** Configures a TurnRunner. */\nexport interface TurnConfig {\n /** Per-turn deadline in ms. Defaults to 30m. */\n queryTimeout: number;\n /** Max silence between classified events in ms. Zero disables (default). */\n idleTimeout?: number;\n /**\n * When > 0, raises idleTimeout for turns with attachments if idleTimeout\n * is positive but below this floor.\n */\n minIdleTimeoutWithAttachments?: number;\n /** Fail vs soft-complete when the idle watchdog fires. Default Fail. */\n onIdleTimeout?: TimeoutPolicy;\n /** Fail vs soft-complete when queryTimeout fires. Default Fail. */\n onQueryTimeout?: TimeoutPolicy;\n /** Fail vs soft-complete when the event stream closes. Default Fail. */\n onStreamClose?: StreamClosePolicy;\n /** Run compactAttachments before buildInput. Default false. */\n compactAttachmentsBeforeSend?: boolean;\n /** Overrides for compactAttachmentsBeforeSend. */\n compactImageOpts?: CompactImageOptions | null;\n}\n\n/** Carries optional daemon hints on a loop_input payload. */\nexport interface InputOpts {\n intentHint?: LoopInputIntentHint;\n preferredSubagent?: string;\n responseSchema?: Record<string, unknown>;\n responseSchemaName?: string;\n responseSchemaStrict?: boolean;\n}\n\n/** Optional attachment shape ({mime_type, data(base64)}). */\nexport type Attachment = Record<string, unknown>;\n\n/**\n * Builds a loop_input payload with optional attachments. Apps build this from\n * their product modes (e.g. triarch's ask/agent/deep-research).\n */\nexport function inputMessageForLoop(\n text: string,\n loopID: string,\n attachments?: Attachment[],\n opts?: InputOpts,\n): Record<string, unknown> {\n const msg: Record<string, unknown> = { type: \"loop_input\", content: text };\n if (loopID) msg.loop_id = loopID;\n if (attachments && attachments.length > 0) msg.attachments = attachments;\n if (opts) {\n if (opts.intentHint?.trim()) {\n const hintError = validateLoopInputIntentHint(opts.intentHint);\n if (hintError) {\n throw new Error(hintError);\n }\n msg.intent_hint = opts.intentHint.trim();\n }\n if (opts.preferredSubagent?.trim()) msg.preferred_subagent = opts.preferredSubagent.trim();\n if (opts.responseSchema && Object.keys(opts.responseSchema).length > 0) {\n msg.response_schema = opts.responseSchema;\n }\n if (opts.responseSchemaName?.trim()) msg.response_schema_name = opts.responseSchemaName.trim();\n if (opts.responseSchemaStrict !== undefined)\n msg.response_schema_strict = opts.responseSchemaStrict;\n }\n return msg;\n}\n\n/** Effective idle timeout for a turn (attachment floor applied). */\nexport function idleTimeoutForTurn(cfg: TurnConfig, hasAttachments: boolean): number {\n const idle = cfg.idleTimeout ?? 0;\n if (idle <= 0) return 0;\n const floor = cfg.minIdleTimeoutWithAttachments ?? 0;\n if (hasAttachments && floor > 0 && idle < floor) return floor;\n return idle;\n}\n\n/** Completion hook signature. */\nexport type OnComplete = (\n sessionID: string,\n loopID: string,\n content: string,\n completionEvent: string,\n elapsedMs: number,\n) => void;\n/** Error hook signature. */\nexport type OnError = (sessionID: string, loopID: string, err: Error) => void;\n\n/**\n * TurnRunner executes one query turn end-to-end.\n */\nexport class TurnRunner {\n private pool: ConnectionPool;\n private gate: QueryGate;\n private classifier: EventClassifier;\n private store: SessionStore;\n private broadcaster: SSEBroadcaster | null;\n private cfg: TurnConfig;\n private buildInput: typeof inputMessageForLoop = inputMessageForLoop;\n private onComplete: OnComplete | null = null;\n private onError: OnError | null = null;\n\n constructor(\n pool: ConnectionPool,\n gate: QueryGate,\n classifier: EventClassifier,\n store: SessionStore,\n broadcaster: SSEBroadcaster | null,\n cfg: TurnConfig,\n ) {\n this.pool = pool;\n this.gate = gate;\n this.classifier = classifier;\n this.store = store;\n this.broadcaster = broadcaster;\n this.cfg = {\n ...cfg,\n queryTimeout: cfg.queryTimeout > 0 ? cfg.queryTimeout : 30 * 60 * 1000,\n };\n }\n\n withInputBuilder(f: typeof inputMessageForLoop): TurnRunner {\n if (f) this.buildInput = f;\n return this;\n }\n\n withOnComplete(f: OnComplete): TurnRunner {\n this.onComplete = f;\n return this;\n }\n\n withOnError(f: OnError): TurnRunner {\n this.onError = f;\n return this;\n }\n\n async execute(\n sessionID: string,\n message: string,\n userID: string,\n workspaceID: string,\n attachments: Attachment[] | null,\n opts: InputOpts | null,\n signal?: AbortSignal,\n ): Promise<void> {\n let conn: PooledConn;\n try {\n conn = await this.pool.acquire(sessionID, workspaceID, userID, signal);\n } catch (err) {\n await this.persistFailed(sessionID, \"\", err as Error);\n this.broadcastError(sessionID, err as Error);\n this.onError?.(sessionID, \"\", err as Error);\n throw err;\n }\n const loopID = conn.getLoopID();\n\n const timeoutController = new AbortController();\n const timeoutMs = this.cfg.queryTimeout;\n const timer = setTimeout(() => timeoutController.abort(), timeoutMs);\n\n const sendCancel = async (detachedSignal: AbortSignal) => {\n await this.sendLoopCancel(detachedSignal, conn, loopID);\n };\n try {\n this.gate.acquire(sessionID, timeoutController, sendCancel);\n } catch (err) {\n clearTimeout(timer);\n await this.pool.release(sessionID);\n await this.persistFailed(sessionID, loopID, err as Error);\n this.broadcastError(sessionID, err as Error);\n this.onError?.(sessionID, loopID, err as Error);\n throw err;\n }\n\n let idleTimer: ReturnType<typeof setTimeout> | null = null;\n const clearIdle = () => {\n if (idleTimer) {\n clearTimeout(idleTimer);\n idleTimer = null;\n }\n };\n\n try {\n let atts = attachments ?? undefined;\n if (this.cfg.compactAttachmentsBeforeSend && atts && atts.length > 0) {\n atts = await compactAttachments(atts, this.cfg.compactImageOpts);\n }\n\n const inputMsg = this.buildInput(message, loopID, atts, opts ?? undefined);\n try {\n await conn.client.sendMessage(inputMsg);\n } catch (err) {\n await this.persistFailed(sessionID, loopID, err as Error);\n this.broadcastError(sessionID, err as Error);\n this.onError?.(sessionID, loopID, err as Error);\n throw err;\n }\n\n const eventStream = conn.eventStream;\n if (!eventStream) {\n const err = new Error(`missing event stream for session ${sessionID} (loop ${loopID})`);\n await this.persistFailed(sessionID, loopID, err);\n this.broadcastError(sessionID, err);\n this.onError?.(sessionID, loopID, err);\n throw err;\n }\n\n let assistantContent = \"\";\n const startedAt = Date.now();\n const idleForTurn = idleTimeoutForTurn(this.cfg, (attachments?.length ?? 0) > 0);\n\n type RaceTag = \"timeout\" | \"caller\" | \"idle\";\n let idleReject: (() => void) | null = null;\n\n const armIdle = (): Promise<\"idle\"> => {\n clearIdle();\n idleReject = null;\n if (idleForTurn <= 0) {\n return new Promise<\"idle\">(() => {});\n }\n return new Promise<\"idle\">(resolve => {\n idleReject = () => resolve(\"idle\");\n idleTimer = setTimeout(() => {\n idleReject?.();\n }, idleForTurn);\n });\n };\n\n let idleRace = armIdle();\n\n const abortRace = new Promise<RaceTag>(resolve => {\n const onTimeout = () => resolve(\"timeout\");\n timeoutController.signal.addEventListener(\"abort\", onTimeout, { once: true });\n if (signal) {\n const onCaller = () => resolve(\"caller\");\n signal.addEventListener(\"abort\", onCaller, { once: true });\n }\n });\n\n const iterator = eventStream[Symbol.asyncIterator]();\n\n while (true) {\n const next = iterator.next();\n const raced = await Promise.race([\n next.then(res => ({ tag: \"msg\" as const, res })),\n abortRace.then(tag => ({ tag })),\n idleRace.then(tag => ({ tag })),\n ]);\n\n if (\"tag\" in raced && raced.tag !== \"msg\") {\n if (raced.tag === \"caller\" || signal?.aborted) {\n clearIdle();\n const err = new Error(\"aborted\");\n await this.persistFailed(sessionID, loopID, err);\n this.broadcastError(sessionID, err);\n this.onError?.(sessionID, loopID, err);\n throw err;\n }\n if (raced.tag === \"idle\") {\n clearIdle();\n await this.sendLoopCancel(new AbortController().signal, conn, loopID).catch(() => {});\n await this.finishTimeout(\n sessionID,\n loopID,\n assistantContent,\n startedAt,\n new ErrIdleTimeout(),\n \"idle_timeout\",\n this.cfg.onIdleTimeout ?? TimeoutPolicy.Fail,\n );\n return;\n }\n clearIdle();\n await this.sendLoopCancel(new AbortController().signal, conn, loopID).catch(() => {});\n await this.finishTimeout(\n sessionID,\n loopID,\n assistantContent,\n startedAt,\n new ErrQueryTimeout(),\n \"query_timeout\",\n this.cfg.onQueryTimeout ?? TimeoutPolicy.Fail,\n );\n return;\n }\n\n const res = (raced as { tag: \"msg\"; res: IteratorResult<DecodedMessage> }).res;\n if (res.done) {\n clearIdle();\n if (\n (this.cfg.onStreamClose ?? TimeoutPolicy.Fail) === TimeoutPolicy.SoftComplete &&\n assistantContent.trim() !== \"\"\n ) {\n await this.completeTurn(\n sessionID,\n loopID,\n assistantContent,\n startedAt,\n \"stream_closed\",\n );\n return;\n }\n const err = new Error(\"event stream closed\");\n await this.persistFailed(sessionID, loopID, err);\n this.broadcastError(sessionID, err);\n this.onError?.(sessionID, loopID, err);\n throw err;\n }\n\n idleRace = armIdle();\n const msg = res.value;\n\n const eventResult = this.classifier.classify(msg, assistantContent);\n if (eventResult.err && eventResult.terminal === ChatEventTerminal.FailedComplete) {\n clearIdle();\n await this.persistFailed(sessionID, loopID, eventResult.err);\n this.broadcastError(sessionID, eventResult.err);\n this.onError?.(sessionID, loopID, eventResult.err);\n throw eventResult.err;\n }\n\n const step = (eventResult.thinkingStep ?? \"\").trim();\n if (step) this.broadcastThinkingStep(sessionID, step);\n\n if (eventResult.content) {\n if (eventResult.content.startsWith(assistantContent)) {\n assistantContent = eventResult.content;\n } else {\n assistantContent += eventResult.content;\n }\n }\n\n const [final, deliverable] = this.classifier.resolveDeliverableFinalContent(\n eventResult,\n assistantContent,\n );\n if (deliverable) {\n clearIdle();\n await this.completeTurn(\n sessionID,\n loopID,\n final,\n startedAt,\n eventResult.completionEvent ?? \"\",\n );\n return;\n }\n }\n } finally {\n clearIdle();\n clearTimeout(timer);\n this.gate.release(sessionID);\n }\n }\n\n private async finishTimeout(\n sessionID: string,\n loopID: string,\n content: string,\n startedAt: number,\n failErr: Error,\n completionEvent: string,\n policy: TimeoutPolicy,\n ): Promise<void> {\n if (policy === TimeoutPolicy.SoftComplete && content.trim() !== \"\") {\n await this.completeTurn(sessionID, loopID, content, startedAt, completionEvent);\n return;\n }\n await this.persistFailed(sessionID, loopID, failErr);\n this.broadcastError(sessionID, failErr);\n this.onError?.(sessionID, loopID, failErr);\n throw failErr;\n }\n\n private async completeTurn(\n sessionID: string,\n loopID: string,\n final: string,\n startedAt: number,\n completionEvent: string,\n ): Promise<void> {\n const elapsedMs = Date.now() - startedAt;\n await this.persistResponse(sessionID, loopID, final, startedAt, completionEvent);\n this.broadcastComplete(sessionID, final);\n this.onComplete?.(sessionID, loopID, final, completionEvent, elapsedMs);\n }\n\n private async sendLoopCancel(\n _signal: AbortSignal,\n conn: PooledConn,\n loopID: string,\n ): Promise<void> {\n const lid = (loopID ?? \"\").trim();\n if (!conn || !lid) return;\n const cancelMsg = { type: \"command_request\", command: \"cancel\", loop_id: lid };\n await conn.client.sendMessage(cancelMsg);\n }\n\n private async persistResponse(\n sessionID: string,\n loopID: string,\n content: string,\n startedAt: number,\n completionEvent: string,\n ): Promise<void> {\n const msg: SessionMessage = {\n role: \"assistant\",\n content,\n metadata: {\n started_at: startedAt,\n completed_at: Date.now(),\n duration_ms: Date.now() - startedAt,\n status: \"completed\",\n completion_event: completionEvent,\n deliverable: true,\n },\n };\n await this.store.appendMessage(sessionID, msg).catch(() => {});\n }\n\n private async persistFailed(sessionID: string, _loopID: string, err: Error): Promise<void> {\n const msg: SessionMessage = {\n role: \"error\",\n content: err.message,\n metadata: { status: \"failed\", error_message: err.message },\n };\n await this.store.appendMessage(sessionID, msg).catch(() => {});\n }\n\n private broadcastThinkingStep(sessionID: string, step: string): void {\n if (!this.broadcaster) return;\n this.broadcaster.broadcast(sessionID, { type: \"delta\", data: step + \"\\n\" } as SSEEvent);\n }\n\n private broadcastComplete(sessionID: string, content: string): void {\n this.broadcaster?.broadcast(sessionID, { type: \"complete\", data: content } as SSEEvent);\n }\n\n private broadcastError(sessionID: string, err: Error): void {\n this.broadcaster?.broadcast(sessionID, { type: \"query_error\", data: err.message } as SSEEvent);\n }\n}\n","/**\n * Dual-socket daemon loop session with turn streaming (Python DaemonSession parity).\n *\n * Owns a subscribed stream WebSocket plus an RPC sidecar so metadata calls do not\n * starve loop events. `iterTurnChunks` handles idle timeout, post-idle drain,\n * loop scoping, and connection-loss detection.\n */\n\nimport { Client } from \"../client.js\";\nimport { defaultConfig, type Config } from \"../config.js\";\nimport { StaleLoopError } from \"../errors.js\";\nimport { bootstrapLoopSession, connectWithRetries } from \"../session.js\";\nimport { STREAM_END, isTurnEndCustomData, isTurnProgressChunk } from \"../stream_terminal.js\";\nimport { shouldDropStreamChunkEarly } from \"./chunk_filter.js\";\nimport { unwrapNext } from \"./events.js\";\nimport { TurnEventStats } from \"./observability.js\";\n\nexport const DEFAULT_POST_IDLE_DRAIN_MS = 500;\n\nexport type EarlyDropFn = (namespace: unknown[], mode: string, data: unknown) => boolean;\nexport type StatsFactory = () => TurnEventStats;\nexport type StreamDeliveryResolver = () => string;\n\nexport interface DaemonSessionOptions {\n workspace?: string | null;\n streamDelivery?: string | StreamDeliveryResolver;\n postIdleDrainDeadlineMs?: number;\n earlyDropFn?: EarlyDropFn | null;\n statsFactory?: StatsFactory | null;\n config?: Config;\n}\n\nexport type TurnChunk = [namespace: unknown[], mode: string, data: unknown];\n\n/** Daemon-backed loop session with stream + RPC sockets. */\nexport class DaemonSession {\n private wsUrl: string;\n private workspace: string | null | undefined;\n private streamDelivery: string | StreamDeliveryResolver;\n private client: Client;\n private rpcClient: Client;\n private loopId: string | null = null;\n private readBusy = false;\n private rpcBusy = false;\n private rpcConnected = false;\n private streaming = false;\n private postIdleDrainDeadlineMs: number;\n private closed = false;\n private earlyDropFn: EarlyDropFn;\n private statsFactory: StatsFactory;\n private config: Config;\n\n turnEventStats: TurnEventStats;\n lastTurnEndState: string | null = null;\n lastTurnCancellationSeen = false;\n lastTurnErrorMessage: string | null = null;\n\n constructor(wsUrl: string, opts: DaemonSessionOptions = {}) {\n this.wsUrl = wsUrl;\n this.workspace = opts.workspace;\n this.streamDelivery = opts.streamDelivery ?? \"adaptive\";\n this.config = opts.config ?? defaultConfig();\n this.client = new Client(wsUrl, this.config);\n this.rpcClient = new Client(wsUrl, this.config);\n this.postIdleDrainDeadlineMs =\n opts.postIdleDrainDeadlineMs && opts.postIdleDrainDeadlineMs > 0\n ? opts.postIdleDrainDeadlineMs\n : DEFAULT_POST_IDLE_DRAIN_MS;\n this.earlyDropFn = opts.earlyDropFn ?? shouldDropStreamChunkEarly;\n this.statsFactory = opts.statsFactory ?? (() => new TurnEventStats());\n this.turnEventStats = this.statsFactory();\n }\n\n get streamClient(): Client {\n return this.client;\n }\n\n get rpcSideClient(): Client {\n return this.rpcClient;\n }\n\n get activeLoopId(): string | null {\n return this.loopId;\n }\n\n private resolveStreamDeliveryMode(): string {\n const delivery = this.streamDelivery;\n if (typeof delivery === \"function\") return String(delivery() || \"adaptive\");\n return String(delivery || \"adaptive\");\n }\n\n get streamDeliveryMode(): string {\n return this.resolveStreamDeliveryMode();\n }\n\n private shouldDrop(namespace: unknown[], mode: string, data: unknown): boolean {\n return Boolean(this.earlyDropFn(namespace, mode, data));\n }\n\n async connect(resumeLoopId?: string | null): Promise<Record<string, unknown>> {\n await connectWithRetries(this.client);\n return this.bootstrapLoop(resumeLoopId ?? null);\n }\n\n private async bootstrapLoop(resumeLoopId: string | null): Promise<Record<string, unknown>> {\n const loopNew = this.workspace\n ? { client_workspace: this.workspace, workspace: this.workspace }\n : undefined;\n const loopId = await bootstrapLoopSession(this.client, resumeLoopId, this.config, loopNew);\n this.loopId = loopId;\n return { type: \"status\", loop_id: loopId, state: \"ready\" };\n }\n\n async newLoop(): Promise<Record<string, unknown>> {\n return this.bootstrapLoop(null);\n }\n\n async switchLoop(loopId: string): Promise<Record<string, unknown>> {\n return this.bootstrapLoop(loopId);\n }\n\n async ensureConnected(): Promise<void> {\n if (this.client.isConnected() && !this.client.isDisconnected()) return;\n\n let resumeLoopId = this.loopId;\n if (this.rpcConnected) {\n this.rpcClient.close();\n this.rpcConnected = false;\n }\n\n try {\n await this.client.reconnect();\n } catch {\n this.client.close();\n await connectWithRetries(this.client);\n }\n\n if (resumeLoopId) {\n try {\n await this.client.reattachAndProbe(resumeLoopId);\n this.loopId = resumeLoopId;\n return;\n } catch (err) {\n if (!(err instanceof StaleLoopError)) throw err;\n resumeLoopId = null;\n }\n }\n\n await this.bootstrapLoop(resumeLoopId);\n }\n\n async close(): Promise<void> {\n if (this.closed) return;\n this.closed = true;\n this.client.close();\n this.rpcClient.close();\n this.rpcConnected = false;\n }\n\n async detach(): Promise<void> {\n if (!this.client.isConnected()) return;\n try {\n await this.client.notify(\"disconnect\", {});\n } catch {\n // ignore\n }\n }\n\n async sendTurn(\n text: string,\n options?: {\n autonomous?: boolean;\n maxIterations?: number;\n preferredSubagent?: string;\n model?: string;\n modelParams?: Record<string, unknown>;\n attachments?: Array<{ mime_type: string; data: string }>;\n clarificationMode?: string;\n clarificationAnswer?: boolean;\n intentHint?: string;\n },\n ): Promise<void> {\n if (!this.loopId) throw new Error(\"No active loop session\");\n await this.client.sendInput(text, {\n loopID: this.loopId,\n autonomous: options?.autonomous,\n maxIterations: options?.maxIterations,\n subagent: options?.preferredSubagent,\n model: options?.model,\n modelParams: options?.modelParams,\n attachments: options?.attachments,\n clarificationMode: options?.clarificationMode,\n clarificationAnswer: options?.clarificationAnswer,\n intentHint: options?.intentHint as\n import(\"../intent_hints.js\").LoopInputIntentHint | undefined,\n });\n }\n\n async cancelActiveTurn(): Promise<void> {\n await this.client.notify(\"slash_command\", { cmd: \"/cancel\" });\n }\n\n private async *drainStreamEventsAfterIdle(\n expectedLoopId: string | null,\n ): AsyncGenerator<TurnChunk> {\n const deadline = Date.now() + this.postIdleDrainDeadlineMs;\n let exp = expectedLoopId;\n while (Date.now() < deadline) {\n const event = await this.client.readEventWithTimeout(250);\n if (!event) break;\n let frame = event;\n let eventType = String(frame.type ?? \"\");\n if (eventType === \"next\") {\n frame = unwrapNext(frame) ?? frame;\n eventType = String(frame.type ?? \"\");\n }\n const eventLoopId = frame.loop_id;\n if (exp && typeof eventLoopId === \"string\" && eventLoopId && eventLoopId !== exp) {\n continue;\n }\n if (eventType === \"error\") {\n const errObj = (frame.error as { message?: string }) ?? {};\n throw new Error(String(errObj.message || frame.message || \"daemon error\"));\n }\n if (eventType === \"status\") {\n const loopEv = frame.loop_id;\n if (typeof loopEv === \"string\" && loopEv) {\n this.loopId = loopEv;\n exp = loopEv;\n }\n continue;\n }\n if (eventType !== \"event\") continue;\n const data = frame.data;\n const namespace = Array.isArray(frame.namespace) ? (frame.namespace as unknown[]) : [];\n const mode = String(frame.mode ?? \"\");\n if (this.shouldDrop(namespace, mode, data)) {\n this.turnEventStats.filteredEarly += 1;\n continue;\n }\n this.turnEventStats.postIdleDrained += 1;\n yield [namespace, mode, data];\n }\n }\n\n private async withRpcLock<T>(fn: () => Promise<T>): Promise<T> {\n while (this.rpcBusy) {\n await new Promise(r => setTimeout(r, 5));\n }\n this.rpcBusy = true;\n try {\n return await fn();\n } finally {\n this.rpcBusy = false;\n }\n }\n\n private async ensureRpcConnected(): Promise<void> {\n if (this.rpcConnected && this.rpcClient.isConnected()) return;\n await connectWithRetries(this.rpcClient);\n this.rpcConnected = true;\n }\n\n async listLoops(_limit = 20): Promise<Record<string, unknown>> {\n return this.withRpcLock(async () => {\n await this.ensureRpcConnected();\n return this.rpcClient.listLoops(15_000);\n });\n }\n\n async fetchLoopCards(loopId: string): Promise<{\n cards: unknown[];\n seq: number;\n contextTokens: number;\n success: boolean;\n }> {\n const lid = String(loopId || \"\").trim();\n if (!lid) return { cards: [], seq: 0, contextTokens: 0, success: false };\n return this.withRpcLock(async () => {\n await this.ensureRpcConnected();\n try {\n const resp = await this.rpcClient.fetchLoopCards(lid, 30_000);\n const rawCards = resp.cards;\n return {\n cards: Array.isArray(rawCards) ? rawCards : [],\n seq: Number(resp.seq ?? 0),\n contextTokens:\n typeof resp.context_tokens === \"number\" && resp.context_tokens >= 0\n ? resp.context_tokens\n : 0,\n success: true,\n };\n } catch {\n return { cards: [], seq: 0, contextTokens: 0, success: false };\n }\n });\n }\n\n async fetchLoopHistory(loopId: string): Promise<{\n goals: unknown[];\n liveCards: unknown[];\n liveGoalIndex: number | null;\n contextTokens: number;\n success: boolean;\n }> {\n const lid = String(loopId || \"\").trim();\n if (!lid) {\n return { goals: [], liveCards: [], liveGoalIndex: null, contextTokens: 0, success: false };\n }\n return this.withRpcLock(async () => {\n await this.ensureRpcConnected();\n try {\n const resp = await this.rpcClient.fetchLoopHistory(lid, 30_000);\n const liveGoalIndex = resp.live_goal_index;\n return {\n goals: Array.isArray(resp.goals) ? resp.goals : [],\n liveCards: Array.isArray(resp.live_cards) ? resp.live_cards : [],\n liveGoalIndex: typeof liveGoalIndex === \"number\" ? liveGoalIndex : null,\n contextTokens:\n typeof resp.context_tokens === \"number\" && resp.context_tokens >= 0\n ? resp.context_tokens\n : 0,\n success: Boolean(resp.success ?? true),\n };\n } catch {\n return {\n goals: [],\n liveCards: [],\n liveGoalIndex: null,\n contextTokens: 0,\n success: false,\n };\n }\n });\n }\n\n async fetchConversationLog(\n loopId: string,\n opts: { limit?: number; offset?: number; includeEvents?: boolean } = {},\n ): Promise<Record<string, unknown>[]> {\n const lid = String(loopId || \"\").trim();\n if (!lid) return [];\n return this.withRpcLock(async () => {\n await this.ensureRpcConnected();\n const resp = await this.rpcClient.getLoopMessages(\n lid,\n opts.limit ?? 100,\n opts.offset ?? 0,\n opts.includeEvents ?? false,\n );\n const raw = resp.messages;\n if (!Array.isArray(raw)) return [];\n return raw.filter((m): m is Record<string, unknown> => !!m && typeof m === \"object\");\n });\n }\n\n async *iterTurnChunks(opts: { maxWaitMs?: number } = {}): AsyncGenerator<TurnChunk> {\n this.turnEventStats = this.statsFactory();\n this.lastTurnEndState = null;\n this.lastTurnCancellationSeen = false;\n this.lastTurnErrorMessage = null;\n\n let queryStarted = false;\n let expectedLoopId = this.loopId;\n let streamPayloadSeen = false;\n let turnProgressSeen = false;\n this.streaming = true;\n const absoluteDeadline =\n opts.maxWaitMs !== undefined && opts.maxWaitMs > 0 ? Date.now() + opts.maxWaitMs : null;\n\n this.client.peelStalePendingControlEvents();\n\n while (this.readBusy) {\n await new Promise(r => setTimeout(r, 5));\n }\n this.readBusy = true;\n try {\n while (true) {\n if (absoluteDeadline !== null && Date.now() >= absoluteDeadline) {\n throw new Error(\n `Turn timed out after ${opts.maxWaitMs}ms (loop=${expectedLoopId ?? \"?\"})`,\n );\n }\n const event = await this.client.readEvent();\n if (!event) {\n if (queryStarted && !this.client.isConnectionAlive()) {\n this.lastTurnEndState = \"connection_lost\";\n throw new Error(\"Daemon connection lost\");\n }\n break;\n }\n\n let frame: Record<string, unknown> = event;\n let eventType = String(frame.type ?? \"\");\n if (eventType === \"next\") {\n frame = unwrapNext(frame) ?? frame;\n eventType = String(frame.type ?? \"\");\n }\n\n const eventLoopId = frame.loop_id;\n if (\n expectedLoopId &&\n typeof eventLoopId === \"string\" &&\n eventLoopId &&\n eventLoopId !== expectedLoopId\n ) {\n continue;\n }\n\n if (eventType === \"error\") {\n const errObj = (frame.error as { message?: string }) ?? {};\n throw new Error(String(errObj.message || frame.message || \"daemon error\"));\n }\n\n if (eventType === \"status\") {\n const loopEv = frame.loop_id;\n if (typeof loopEv === \"string\" && loopEv) {\n this.loopId = loopEv;\n expectedLoopId = loopEv;\n }\n const state = String(frame.state ?? \"\");\n if (state === \"running\") {\n queryStarted = true;\n } else if (queryStarted && state === \"stopped\") {\n this.lastTurnEndState = state;\n yield* this.drainStreamEventsAfterIdle(expectedLoopId);\n break;\n } else if (queryStarted && state === \"idle\") {\n if (!streamPayloadSeen && !this.lastTurnCancellationSeen) continue;\n this.lastTurnEndState = state;\n yield* this.drainStreamEventsAfterIdle(expectedLoopId);\n break;\n }\n continue;\n }\n\n if (eventType === \"command_response\") {\n const content = String(frame.content ?? \"\");\n if (content.includes(\"Cancellation requested\")) {\n this.lastTurnCancellationSeen = true;\n }\n continue;\n }\n\n if (eventType !== \"event\") continue;\n\n const data = frame.data;\n const namespace = Array.isArray(frame.namespace) ? (frame.namespace as unknown[]) : [];\n const mode = String(frame.mode ?? \"\");\n if (this.shouldDrop(namespace, mode, data)) {\n this.turnEventStats.filteredEarly += 1;\n continue;\n }\n\n if (mode === \"custom\" && isTurnEndCustomData(data)) {\n if (!queryStarted || !turnProgressSeen) continue;\n }\n\n streamPayloadSeen = true;\n if (isTurnProgressChunk(mode, data)) turnProgressSeen = true;\n yield [namespace, mode, data];\n\n if (mode === \"custom\" && isTurnEndCustomData(data)) {\n const customType = String((data as Record<string, unknown>).type ?? \"\").trim();\n this.lastTurnEndState = customType === STREAM_END ? \"stream_end\" : \"completed\";\n yield* this.drainStreamEventsAfterIdle(expectedLoopId);\n break;\n }\n }\n } catch (exc) {\n this.lastTurnErrorMessage = String(exc);\n throw exc;\n } finally {\n this.streaming = false;\n this.readBusy = false;\n }\n }\n}\n","/**\n * Early filters for daemon stream chunks (wire / dict-shaped payloads).\n */\n\nconst MSG_PAIR_LEN = 2;\n\n/** True when an updates chunk carries no LangGraph interrupt. */\nexport function updatesChunkIsNoop(data: unknown): boolean {\n if (!data || typeof data !== \"object\") return true;\n return !(\"__interrupt__\" in (data as Record<string, unknown>));\n}\n\nfunction wireBody(msg: Record<string, unknown>): Record<string, unknown> {\n for (const key of [\"kwargs\", \"data\"] as const) {\n const nested = msg[key];\n if (nested && typeof nested === \"object\") return nested as Record<string, unknown>;\n }\n return msg;\n}\n\nfunction dictHasToolInvocation(msg: Record<string, unknown>): boolean {\n const body = wireBody(msg);\n if (body.tool_calls || body.tool_call_chunks) return true;\n for (const key of [\"content\", \"content_blocks\"] as const) {\n const raw = body[key];\n if (Array.isArray(raw)) {\n for (const item of raw) {\n if (\n item &&\n typeof item === \"object\" &&\n [\"tool_call\", \"tool_call_chunk\", \"tool_use\"].includes(\n String((item as Record<string, unknown>).type ?? \"\"),\n )\n ) {\n return true;\n }\n }\n }\n }\n return false;\n}\n\nfunction plainText(msg: Record<string, unknown>): string {\n const body = wireBody(msg);\n const content = body.content ?? msg.content;\n if (typeof content === \"string\") return content;\n if (Array.isArray(content)) {\n const parts: string[] = [];\n for (const block of content) {\n if (typeof block === \"string\") parts.push(block);\n else if (block && typeof block === \"object\") {\n const text = (block as Record<string, unknown>).text;\n if (typeof text === \"string\") parts.push(text);\n }\n }\n return parts.join(\"\");\n }\n return \"\";\n}\n\n/** True when a wire messages pair has no tool, text, or loop phase payload. */\nexport function messageChunkIsNonActionable(data: unknown): boolean {\n if (!Array.isArray(data) || data.length !== MSG_PAIR_LEN) return false;\n const msg = data[0];\n if (msg === null || msg === undefined) return true;\n if (!msg || typeof msg !== \"object\") return false;\n const m = msg as Record<string, unknown>;\n const body = wireBody(m);\n const raw = String(body.type ?? m.type ?? \"\");\n if (raw === \"tool\" || raw === \"ToolMessage\" || raw.endsWith(\"ToolMessage\")) return false;\n if (dictHasToolInvocation(m)) return false;\n if (body.phase || m.phase) return false;\n return !plainText(m).trim();\n}\n\n/** Return true when the chunk can be skipped before the turn pipeline. */\nexport function shouldDropStreamChunkEarly(\n _namespace: unknown[],\n mode: string,\n data: unknown,\n): boolean {\n if (mode === \"updates\") return updatesChunkIsNoop(data);\n if (mode === \"messages\") return messageChunkIsNonActionable(data);\n return false;\n}\n","/**\n * Protocol-1 streaming frame helpers for application loops.\n */\n\n/** Unwrap a protocol-1 next envelope to its inner streaming frame. */\nexport function unwrapNext(\n event: Record<string, unknown> | null | undefined,\n): Record<string, unknown> | null | undefined {\n if (!event || typeof event !== \"object\") return event;\n if (event.type !== \"next\") return event;\n const payload = event.payload;\n if (!payload || typeof payload !== \"object\") return event;\n const data = (payload as Record<string, unknown>).data;\n return data && typeof data === \"object\" ? (data as Record<string, unknown>) : event;\n}\n\n/**\n * Return whether a daemon frame belongs to the active StrangeLoop session.\n */\nexport function isLoopScopedEvent(event: Record<string, unknown>, activeLoopId: string): boolean {\n let eventType = String(event.type ?? \"\");\n let frame = event;\n if (eventType === \"next\") {\n const inner = unwrapNext(event);\n if (inner && typeof inner === \"object\") {\n frame = inner;\n eventType = String(inner.type ?? \"\");\n return eventType !== \"status\" && eventType !== \"event\"\n ? true\n : String(inner.loop_id ?? \"\") === activeLoopId;\n }\n }\n if (eventType !== \"status\" && eventType !== \"event\") return true;\n return String(frame.loop_id ?? \"\") === activeLoopId;\n}\n","/**\n * Per-turn observability counters for daemon stream consumption.\n */\n\nexport class TurnEventStats {\n total = 0;\n messages = 0;\n updates = 0;\n custom = 0;\n skipped = 0;\n filteredEarly = 0;\n toolCalls = 0;\n toolResults = 0;\n textChunks = 0;\n heartbeatsDropped = 0;\n postIdleDrained = 0;\n inboundDropped = 0;\n}\n"],"mappings":"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","names":["DisconnectCause","VerbosityTier","WebSocket","msg","Client","ChatEventTerminal","dataType","dt","buf","TimeoutPolicy","res"]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/verbosity.ts","../src/config.ts","../src/protocol.ts","../src/intent_hints.ts","../src/events.ts","../src/multiplexer.ts","../src/stream_terminal.ts","../src/inbound_priority.ts","../src/client.ts","../src/index.ts","../src/command_client.ts","../src/session.ts","../src/helpers.ts","../src/appkit/broadcaster.ts","../src/appkit/classifier.ts","../src/appkit/thinking_step.ts","../src/appkit/query_gate.ts","../src/appkit/pool.ts","../src/appkit/client.ts","../src/appkit/attachments.ts","../src/appkit/turn_runner.ts","../src/appkit/daemon_session.ts","../src/appkit/chunk_filter.ts","../src/appkit/events.ts","../src/appkit/observability.ts"],"sourcesContent":["/**\n * Custom error types for the Soothe client.\n */\n\n/** Represents a WebSocket connection failure. */\nexport class ConnectionError extends Error {\n readonly url: string;\n readonly attempt: number;\n readonly cause: Error;\n\n constructor(url: string, attempt: number, cause: Error) {\n super(`connection error to ${url} (attempt ${attempt}): ${cause.message}`);\n this.name = \"ConnectionError\";\n this.url = url;\n this.attempt = attempt;\n this.cause = cause;\n }\n}\n\n/**\n * Represents an error reported by the Soothe daemon.\n *\n * The daemon's structured error object carries a numeric `code` from the\n * reserved ranges, a human-readable `message`, and optional `data`.\n */\nexport class DaemonError extends Error {\n /** Numeric error code from the daemon error registry. */\n readonly code: number;\n /** The daemon's error message text. */\n readonly daemonMessage: string;\n /** Optional machine-parseable error details. */\n readonly data: unknown;\n\n constructor(code: number, message: string, data?: unknown) {\n super(`daemon error [${code}]: ${message}`);\n this.name = \"DaemonError\";\n this.code = code;\n this.daemonMessage = message;\n this.data = data;\n }\n}\n\n/** Represents a timeout waiting for a daemon response. */\nexport class TimeoutError extends Error {\n readonly operation: string;\n readonly duration: string;\n\n constructor(operation: string, duration: string) {\n super(`timeout after ${duration} waiting for ${operation}`);\n this.name = \"TimeoutError\";\n this.operation = operation;\n this.duration = duration;\n }\n}\n\n/**\n * Distinguishes clean vs unclean connection loss.\n *\n * A clean drop follows a `disconnect` notification (loops keep running\n * server-side); an unclean drop is a read/write error or a missed pong\n * (in-flight queries are cancelled). Pair with the Client's `'disconnected'`\n * event: the cause is emitted exactly once when the connection drops.\n */\nexport enum DisconnectCause {\n /** Abrupt loss: read/write error or missed pong. */\n Unclean = 0,\n /** Graceful peer-initiated `disconnect` notification. */\n Clean = 1,\n}\n\n/** Human-readable cause name for logging. */\nexport function disconnectCauseName(cause: DisconnectCause): string {\n return cause === DisconnectCause.Clean ? \"clean\" : \"unclean\";\n}\n\n/** Indicates a failed reconnection attempt sequence. */\nexport class ReconnectError extends Error {\n readonly url: string;\n readonly attempts: number;\n readonly cause: Error;\n\n constructor(url: string, attempts: number, cause: Error) {\n super(`reconnect to ${url} failed after ${attempts} attempts: ${cause.message}`);\n this.name = \"ReconnectError\";\n this.url = url;\n this.attempts = attempts;\n this.cause = cause;\n }\n}\n\n/**\n * Returned by `reattachAndProbe` when a loop accepts the reattach handshake\n * but fails the `loop_get` liveness probe. Callers should fall back to a\n * fresh `loop_new` bootstrap.\n */\nexport class StaleLoopError extends Error {\n readonly loopID: string;\n readonly cause?: Error;\n\n constructor(loopID: string, cause?: Error) {\n const detail = cause ? `: ${cause.message}` : \"\";\n super(`stale loop ${loopID}: reattach accepted but liveness probe failed${detail}`);\n this.name = \"StaleLoopError\";\n this.loopID = loopID;\n this.cause = cause;\n }\n}\n","/**\n * Verbosity levels and tiers for event filtering.\n */\n\n/** User-configurable verbosity setting. */\nexport type VerbosityLevel = \"quiet\" | \"normal\" | \"debug\";\n\n/** Minimum verbosity level at which content is visible. */\nexport enum VerbosityTier {\n /** Always visible (errors, assistant text, final reports) */\n Quiet = 0,\n /** Standard progress (plan updates, milestones, agentic loop) */\n Normal = 1,\n /** Detailed internals (protocol events, tool calls, subagent activity) */\n Detailed = 2,\n /** Everything including internals (thinking, heartbeats) */\n Debug = 3,\n /** Never shown at any level (implementation details) */\n Internal = 99,\n}\n\nconst verbosityLevelValues: Record<VerbosityLevel, number> = {\n quiet: 0,\n normal: 1,\n debug: 3,\n};\n\n/** Returns true if content at the given tier is visible at the given verbosity. */\nexport function shouldShow(tier: VerbosityTier, verbosity: VerbosityLevel): boolean {\n if (tier === VerbosityTier.Internal) {\n return false;\n }\n const level = verbosityLevelValues[verbosity] ?? 1; // default to normal\n return tier <= level;\n}\n\n/** Checks whether a string is a valid verbosity level. */\nexport function isValidVerbosityLevel(s: string): s is VerbosityLevel {\n return s in verbosityLevelValues;\n}\n","/**\n * Client configuration for connecting to the Soothe daemon.\n */\n\nimport type { VerbosityLevel } from \"./verbosity.js\";\n\nexport interface Config {\n /** WebSocket URL for Soothe daemon */\n daemonURL: string;\n /** Event verbosity: quiet/minimal/normal/detailed/debug */\n verbosityLevel: VerbosityLevel;\n /** Maximum connection retry attempts */\n maxRetries: number;\n /** Initial reconnect delay in ms */\n reconnectDelay: number;\n /** Application-level heartbeat interval in ms */\n heartbeatInterval: number;\n /** Handshake: wait for connection_ack (readiness \"ready\") in ms */\n daemonReadyTimeout: number;\n /** Bootstrap: wait for status with loop_id in ms */\n loopStatusTimeout: number;\n /** After subscribe(method:\"loop_events\"): wait for confirmation in ms */\n subscriptionTimeout: number;\n\n // Mid-session reconnect.\n /** Max reconnection attempts on a mid-session drop (0 = infinite). */\n reconnectMaxAttempts: number;\n /** Initial backoff delay (ms) between reconnect attempts. */\n reconnectInitialDelay: number;\n /** Cap (ms) on exponential backoff delay between reconnect attempts. */\n reconnectMaxDelay: number;\n /** `loop_get` liveness probe timeout (ms) in reattachAndProbe. */\n reattachProbeTimeout: number;\n}\n\n/** Returns default configuration. */\nexport function defaultConfig(): Config {\n return {\n daemonURL: \"ws://localhost:8765\",\n verbosityLevel: \"normal\",\n maxRetries: 5,\n reconnectDelay: 2000,\n heartbeatInterval: 30000,\n daemonReadyTimeout: 20000,\n loopStatusTimeout: 60000,\n subscriptionTimeout: 10000,\n\n reconnectMaxAttempts: 10,\n reconnectInitialDelay: 500,\n reconnectMaxDelay: 10000,\n reattachProbeTimeout: 5000,\n };\n}\n\n/** Loads configuration from environment variables. */\nexport function loadConfigFromEnv(): Config {\n const config = defaultConfig();\n\n if (typeof process === \"undefined\") return config;\n\n const url = process.env.SOOTHE_DAEMON_URL;\n if (url) config.daemonURL = url;\n\n const verbosity = process.env.SOOTHE_VERBOSITY;\n if (verbosity) config.verbosityLevel = verbosity as VerbosityLevel;\n\n const retries = process.env.SOOTHE_MAX_RETRIES;\n if (retries) {\n const val = parseInt(retries, 10);\n if (!isNaN(val)) config.maxRetries = val;\n }\n\n const readyTimeout = process.env.SOOTHE_DAEMON_READY_TIMEOUT_SEC;\n if (readyTimeout) {\n const val = parseInt(readyTimeout, 10);\n if (val > 0) config.daemonReadyTimeout = val * 1000;\n }\n\n const statusTimeout = process.env.SOOTHE_LOOP_STATUS_TIMEOUT_SEC;\n if (statusTimeout) {\n const val = parseInt(statusTimeout, 10);\n if (val > 0) config.loopStatusTimeout = val * 1000;\n }\n\n const subTimeout = process.env.SOOTHE_SUBSCRIPTION_TIMEOUT_SEC;\n if (subTimeout) {\n const val = parseInt(subTimeout, 10);\n if (val > 0) config.subscriptionTimeout = val * 1000;\n }\n\n return config;\n}\n","/**\n * Protocol-1 wire envelope: message types, encode/decode, NDJSON splitting,\n * and factory functions for the Soothe daemon.\n *\n * The unified `{proto, type, method, params, id}` envelope combines\n * JSON-RPC 2.0's `method`/`params`/`id` structure with graphql-ws's `type`\n * semantics for message class distinction.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport type { LoopInputIntentHint } from \"./intent_hints.js\";\n\n/** Protocol version string. */\nexport const PROTO_VERSION = \"1\";\n\n/** Default client capabilities declared in the connection_init handshake. */\nexport const DEFAULT_CLIENT_CAPABILITIES = [\"streaming\", \"batch\", \"heartbeat\", \"receipts\"];\n\n/** Client version reported in the connection_init handshake. */\nexport const CLIENT_VERSION = \"0.4.1\";\n\n// ---------------------------------------------------------------------------\n// Envelope message classes\n// ---------------------------------------------------------------------------\n\nexport type MessageType =\n | \"connection_init\"\n | \"connection_ack\"\n | \"request\"\n | \"response\"\n | \"notification\"\n | \"subscribe\"\n | \"next\"\n | \"error\"\n | \"complete\"\n | \"unsubscribe\"\n | \"ping\"\n | \"pong\"\n | \"receipt_response\"\n | \"disconnect\"\n | \"status\";\n\n/** Method names carried in the envelope `method` field. */\nexport type MethodName =\n | \"loop_list\"\n | \"loop_get\"\n | \"loop_tree\"\n | \"loop_prune\"\n | \"loop_delete\"\n | \"loop_new\"\n | \"loop_reattach\"\n | \"loop_detach\"\n | \"loop_input\"\n | \"loop_messages\"\n | \"loop_state_get\"\n | \"loop_state_update\"\n | \"loop_cards_fetch\"\n | \"loop_history_fetch\"\n | \"loop_events\"\n | \"autopilot_events\"\n | \"job_create\"\n | \"job_status\"\n | \"job_pause\"\n | \"job_resume\"\n | \"job_cancel\"\n | \"job_dag\"\n | \"job_guidance\"\n | \"autopilot_status\"\n | \"autopilot_submit\"\n | \"autopilot_list_goals\"\n | \"autopilot_get_goal\"\n | \"autopilot_cancel_goal\"\n | \"autopilot_cancel_all\"\n | \"autopilot_wake\"\n | \"autopilot_dream\"\n | \"autopilot_resume\"\n | \"autopilot_list_jobs\"\n | \"autopilot_get_job\"\n | \"daemon_status\"\n | \"daemon_shutdown\"\n | \"config_get\"\n | \"config_reload\"\n | \"skills_list\"\n | \"invoke_skill\"\n | \"models_list\"\n | \"mcp_status\"\n | \"auth\"\n | \"auth_refresh\"\n | \"slash_command\"\n | \"rpc_command\"\n | \"delivery_ack\"\n | \"cron_add\"\n | \"cron_list\"\n | \"cron_show\"\n | \"cron_cancel\"\n | \"disconnect\";\n\n// ---------------------------------------------------------------------------\n// Envelope interfaces\n// ---------------------------------------------------------------------------\n\n/** Base fields shared by every protocol-1 message. */\nexport interface BaseEnvelope {\n proto: string;\n type: MessageType;\n}\n\n/** A client→server RPC request (expects a `response` correlated by `id`). */\nexport interface RequestEnvelope extends BaseEnvelope {\n type: \"request\";\n method: MethodName;\n params?: Record<string, unknown>;\n id: string;\n}\n\n/** A server→client RPC success response. */\nexport interface ResponseEnvelope extends BaseEnvelope {\n type: \"response\";\n result?: Record<string, unknown>;\n id?: string;\n}\n\n/** A fire-and-forget client→server notification (no `id`, no response). */\nexport interface NotificationEnvelope extends BaseEnvelope {\n type: \"notification\";\n method: MethodName;\n params?: Record<string, unknown>;\n /** Optional receipt id for delivery confirmation. */\n receipt?: string;\n}\n\n/** Start a subscription stream (events arrive as `next`). */\nexport interface SubscribeEnvelope extends BaseEnvelope {\n type: \"subscribe\";\n method: \"loop_events\" | \"autopilot_events\";\n params?: {\n loop_id?: string;\n verbosity?: string;\n /** Stream delivery mode: batch (coalesce until turn end), adaptive (small payloads passthrough), streaming (real-time chunks). */\n stream_delivery?: \"batch\" | \"adaptive\" | \"streaming\";\n /** Wire serialization tier: full (all fields), compact (essential fields only). */\n wire_tier?: \"full\" | \"compact\";\n } & Record<string, unknown>;\n id: string;\n}\n\n/** A stream event for an active subscription. */\nexport interface NextEnvelope extends BaseEnvelope {\n type: \"next\";\n payload?: Record<string, unknown>;\n id?: string;\n}\n\n/** Structured error response (terminates the operation). */\nexport interface ErrorEnvelope extends BaseEnvelope {\n type: \"error\";\n error: { code: number; message: string; data?: unknown };\n id?: string;\n}\n\n/** Explicit stream-completion signal. */\nexport interface CompleteEnvelope extends BaseEnvelope {\n type: \"complete\";\n id?: string;\n}\n\n/** Cancel a subscription by `id`. */\nexport interface UnsubscribeEnvelope extends BaseEnvelope {\n type: \"unsubscribe\";\n id: string;\n}\n\n/** Connection handshake (client→server, first message). */\nexport interface ConnectionInitEnvelope extends BaseEnvelope {\n type: \"connection_init\";\n params?: {\n client_version: string;\n client_name?: string;\n accept_proto?: string[];\n capabilities?: string[];\n };\n}\n\n/** Connection handshake response (server→client). */\nexport interface ConnectionAckEnvelope extends BaseEnvelope {\n type: \"connection_ack\";\n result?: {\n server_version?: string;\n protocol_version?: string;\n capabilities?: string[];\n readiness_state?: string;\n heartbeat_interval_ms?: number;\n };\n}\n\n/** Heartbeat ping (either direction). */\nexport interface PingEnvelope extends BaseEnvelope {\n type: \"ping\";\n}\n\n/** Heartbeat pong response. */\nexport interface PongEnvelope extends BaseEnvelope {\n type: \"pong\";\n}\n\n/** Delivery confirmation for a notification that carried a `receipt`. */\nexport interface ReceiptResponseEnvelope extends BaseEnvelope {\n type: \"receipt_response\";\n receipt: string;\n}\n\n/** Clean connection close (daemon keeps loops running). */\nexport interface DisconnectEnvelope extends BaseEnvelope {\n type: \"disconnect\";\n}\n\n/**\n * A daemon status frame. `status` is a defined protocol-1 top-level type:\n * it passes through the daemon's legacy→`next` translator unchanged, so it\n * is NOT wrapped in a `next` envelope.\n */\nexport interface StatusFrame extends BaseEnvelope {\n type: \"status\";\n state?: string;\n loop_id?: string;\n workspace?: string;\n input_history?: string[];\n conversation_history?: unknown[];\n [key: string]: unknown;\n}\n\n/** Discriminated union of all decoded protocol-1 messages. */\nexport type DecodedMessage =\n | RequestEnvelope\n | ResponseEnvelope\n | NotificationEnvelope\n | SubscribeEnvelope\n | NextEnvelope\n | ErrorEnvelope\n | CompleteEnvelope\n | UnsubscribeEnvelope\n | ConnectionInitEnvelope\n | ConnectionAckEnvelope\n | PingEnvelope\n | PongEnvelope\n | ReceiptResponseEnvelope\n | DisconnectEnvelope\n | StatusFrame\n | Record<string, unknown>;\n\n// ---------------------------------------------------------------------------\n// Typed request/notification payload interfaces (params shapes)\n// ---------------------------------------------------------------------------\n\nexport interface LoopInputParams {\n loop_id: string;\n content: string;\n autonomous?: boolean;\n max_iterations?: number;\n preferred_subagent?: string;\n /** @deprecated Ignored by daemon; loop_input always uses non-interactive autonomous mode. */\n interactive?: boolean;\n model?: string;\n model_params?: Record<string, unknown>;\n attachments?: Record<string, unknown>[];\n intent_hint?: LoopInputIntentHint;\n response_schema?: Record<string, unknown>;\n response_schema_name?: string;\n response_schema_strict?: boolean;\n clarification_mode?: string;\n clarification_answer?: boolean;\n clarification_answers?: string[];\n}\n\n/** Options for `loop_new` workspace fields. */\nexport interface LoopNewOptions {\n client_workspace?: string;\n client_workspace_id?: string;\n user_id?: string;\n is_ephemeral?: boolean;\n /** @deprecated Use `client_workspace`. */\n workspace?: string;\n}\n\n// ---------------------------------------------------------------------------\n// Stream-event payload helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Shape of a `next` payload when the daemon wraps a legacy free-form frame.\n * The original frame type becomes `mode`; `data` carries the frame body with\n * `loop_id` preserved.\n */\nexport interface StreamEventPayload {\n namespace?: unknown;\n mode?: string;\n data?: Record<string, unknown>;\n}\n\n// ---------------------------------------------------------------------------\n// Encode / Decode\n// ---------------------------------------------------------------------------\n\n/** Encodes a message as JSON with a newline delimiter (NDJSON frame). */\nexport function encodeMessage(msg: unknown): string {\n return JSON.stringify(msg) + \"\\n\";\n}\n\n/**\n * Decodes a JSON message and returns a typed object. Unknown types return a\n * raw map. The decoder is permissive: it accepts protocol-1 envelopes and\n * surfaces `response.result` / `next.payload` for consumers that read them,\n * but always returns the full envelope so callers can inspect `type`/`id`.\n */\nexport function decodeMessage(data: string): DecodedMessage | null {\n if (!data || data.length === 0) return null;\n\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(data);\n } catch {\n throw new Error(`invalid JSON: ${data}`);\n }\n\n if (!parsed || typeof parsed !== \"object\") return parsed;\n\n const type = parsed.type as MessageType | undefined;\n if (!type) return parsed;\n\n switch (type) {\n case \"connection_init\":\n return { ...parsed } as unknown as ConnectionInitEnvelope;\n case \"connection_ack\":\n return { ...parsed } as unknown as ConnectionAckEnvelope;\n case \"request\":\n return { ...parsed } as unknown as RequestEnvelope;\n case \"response\":\n return { ...parsed } as unknown as ResponseEnvelope;\n case \"notification\":\n return { ...parsed } as unknown as NotificationEnvelope;\n case \"subscribe\":\n return { ...parsed } as unknown as SubscribeEnvelope;\n case \"next\":\n return { ...parsed } as unknown as NextEnvelope;\n case \"error\":\n return { ...parsed } as unknown as ErrorEnvelope;\n case \"complete\":\n return { ...parsed } as unknown as CompleteEnvelope;\n case \"unsubscribe\":\n return { ...parsed } as unknown as UnsubscribeEnvelope;\n case \"ping\":\n return { ...parsed } as unknown as PingEnvelope;\n case \"pong\":\n return { ...parsed } as unknown as PongEnvelope;\n case \"receipt_response\":\n return { ...parsed } as unknown as ReceiptResponseEnvelope;\n case \"disconnect\":\n return { ...parsed } as unknown as DisconnectEnvelope;\n case \"status\":\n return { ...parsed } as unknown as StatusFrame;\n default:\n return parsed;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Envelope factory helpers\n// ---------------------------------------------------------------------------\n\n/** Builds a `request` envelope. */\nexport function requestEnvelope(\n method: MethodName,\n params?: Record<string, unknown>,\n id?: string,\n): RequestEnvelope {\n return {\n proto: PROTO_VERSION,\n type: \"request\",\n method,\n params,\n id: id ?? newRequestID(),\n };\n}\n\n/** Builds a `notification` envelope (no `id`). */\nexport function notificationEnvelope(\n method: MethodName,\n params?: Record<string, unknown>,\n): NotificationEnvelope {\n return { proto: PROTO_VERSION, type: \"notification\", method, params };\n}\n\n/** Builds a `subscribe` envelope. */\nexport function subscribeEnvelope(\n method: \"loop_events\" | \"autopilot_events\",\n params?: Record<string, unknown>,\n id?: string,\n): SubscribeEnvelope {\n return {\n proto: PROTO_VERSION,\n type: \"subscribe\",\n method,\n params,\n id: id ?? newRequestID(),\n };\n}\n\n/** Builds an `unsubscribe` envelope. */\nexport function unsubscribeEnvelope(id: string): UnsubscribeEnvelope {\n return { proto: PROTO_VERSION, type: \"unsubscribe\", id };\n}\n\n/** Builds a `connection_init` handshake envelope. */\nexport function connectionInitEnvelope(opts?: {\n client_version?: string;\n client_name?: string;\n accept_proto?: string[];\n capabilities?: string[];\n}): ConnectionInitEnvelope {\n return {\n proto: PROTO_VERSION,\n type: \"connection_init\",\n params: {\n client_version: opts?.client_version ?? CLIENT_VERSION,\n client_name: opts?.client_name ?? \"soothe-client-ts\",\n accept_proto: opts?.accept_proto ?? [PROTO_VERSION],\n capabilities: opts?.capabilities ?? DEFAULT_CLIENT_CAPABILITIES,\n },\n };\n}\n\n/** Builds a `ping` heartbeat envelope. */\nexport function pingEnvelope(): PingEnvelope {\n return { proto: PROTO_VERSION, type: \"ping\" };\n}\n\n/** Builds a `pong` heartbeat envelope. */\nexport function pongEnvelope(): PongEnvelope {\n return { proto: PROTO_VERSION, type: \"pong\" };\n}\n\n/** Builds a `disconnect` notification envelope. */\nexport function disconnectEnvelope(): DisconnectEnvelope {\n return { proto: PROTO_VERSION, type: \"disconnect\" };\n}\n\n// ---------------------------------------------------------------------------\n// NDJSON splitting\n// ---------------------------------------------------------------------------\n\n/** Splits a single WebSocket text payload into individual JSON lines. */\nexport function splitWirePayload(data: string): string[] {\n const trimmed = data.trim();\n if (trimmed === \"\") return [];\n\n const lines = trimmed\n .split(\"\\n\")\n .map(l => l.trim())\n .filter(l => l !== \"\");\n return lines.length > 0 ? lines : [data];\n}\n\n// ---------------------------------------------------------------------------\n// Event/loop extraction helpers\n// ---------------------------------------------------------------------------\n\n/**\n * Returns the StrangeLoop id when present in a message.\n *\n * Under protocol-1, loop-scoped stream events arrive as `next` envelopes\n * whose `payload.data` carries the original frame (with `loop_id`). Raw\n * `status` frames carry `loop_id` at the top level. This helper inspects\n * both shapes.\n */\nexport function extractSootheLoopID(msg: unknown): [string, boolean] {\n if (!msg || typeof msg !== \"object\") return [\"\", false];\n const m = msg as Record<string, unknown>;\n\n // `next` envelope: dig into payload.data.loop_id.\n if (m.type === \"next\") {\n const payload = m.payload as Record<string, unknown> | undefined;\n if (payload && typeof payload === \"object\") {\n const data = payload.data as Record<string, unknown> | undefined;\n if (data && typeof data === \"object\") {\n const id = data.loop_id as string | undefined;\n if (id && id !== \"\") return [id, true];\n }\n // Some payloads carry loop_id directly.\n const pid = payload.loop_id as string | undefined;\n if (pid && pid !== \"\") return [pid, true];\n }\n return [\"\", false];\n }\n\n if (m.type === \"status\") {\n const id = m.loop_id as string | undefined;\n if (id && id !== \"\") return [id, true];\n return [\"\", false];\n }\n\n // Generic fallback: top-level loop_id.\n const generic = m.loop_id as string | undefined;\n if (generic && generic !== \"\") return [generic, true];\n\n return [\"\", false];\n}\n// ---------------------------------------------------------------------------\n// Message factory functions\n// ---------------------------------------------------------------------------\n\n/** Generates a new UUID correlation ID. */\nexport function newRequestID(): string {\n return randomUUID();\n}\n\n/** Creates a `loop_input` notification envelope. */\nexport function newLoopInputMessage(loopID: string, content: string): NotificationEnvelope {\n return notificationEnvelope(\"loop_input\", {\n loop_id: loopID,\n content,\n autonomous: false,\n });\n}\n\n/** Creates a `loop_new` request envelope. */\nexport function newLoopNewMessage(opts?: LoopNewOptions | string): RequestEnvelope {\n const options: LoopNewOptions =\n typeof opts === \"string\" ? { client_workspace: opts } : (opts ?? {});\n const clientWorkspace = options.client_workspace ?? options.workspace;\n const params: Record<string, unknown> = {};\n if (clientWorkspace?.trim()) {\n params.client_workspace = clientWorkspace.trim();\n }\n if (options.user_id?.trim()) {\n params.user_id = options.user_id.trim();\n }\n if (options.client_workspace_id?.trim()) {\n params.client_workspace_id = options.client_workspace_id.trim();\n }\n if (options.is_ephemeral) {\n params.is_ephemeral = true;\n }\n return requestEnvelope(\"loop_new\", params);\n}\n\n/** Creates a `loop_events` subscribe envelope. */\nexport function newLoopSubscribeMessage(\n loopID: string,\n verbosity: string,\n streamDelivery?: \"batch\" | \"adaptive\" | \"streaming\",\n): SubscribeEnvelope {\n const params: Record<string, unknown> = { loop_id: loopID, verbosity };\n if (streamDelivery) {\n params.stream_delivery = streamDelivery;\n }\n return subscribeEnvelope(\"loop_events\", params);\n}\n","/**\n * Daemon ``loop_input`` intent_hint values (direct model turns, no agent graph).\n */\n\n/** Text-only chat completion via the configured ``default`` role. */\nexport const INTENT_HINT_TEXT_COMPLETION = \"text_completion\" as const;\n\n/** Vision / image understanding via the configured ``image`` role (attachments required). */\nexport const INTENT_HINT_IMAGE_TO_TEXT = \"image_to_text\" as const;\n\n/** OCR via the configured ``ocr`` role (attachments required). */\nexport const INTENT_HINT_OCR = \"ocr\" as const;\n\n/** Embedding via the configured ``embedding`` role (text-only; JSON vector response). */\nexport const INTENT_HINT_EMBED = \"embed\" as const;\n\n/** Supported daemon direct-model intent hints. */\nexport type IntentHint =\n | typeof INTENT_HINT_TEXT_COMPLETION\n | typeof INTENT_HINT_IMAGE_TO_TEXT\n | typeof INTENT_HINT_OCR\n | typeof INTENT_HINT_EMBED;\n\n/** Legacy intent_hint values removed from the daemon wire contract. */\nexport const REMOVED_INTENT_HINTS = [\"direct_llm\", \"quiz\"] as const;\n\nexport type RemovedIntentHint = (typeof REMOVED_INTENT_HINTS)[number];\n\nconst REMOVED_INTENT_HINT_MESSAGES: Record<RemovedIntentHint, string> = {\n direct_llm:\n \"intent_hint direct_llm is removed; use text_completion (text-only) or image_to_text (with attachments)\",\n quiz: \"intent_hint quiz is removed; omit intent_hint and let intake classify the turn\",\n};\n\n/**\n * Wire ``loop_input.intent_hint``: direct model hints or agent-path pass-through\n * (e.g. ``resume_clarification``, ``skill:foo``). Legacy ``direct_llm`` and\n * ``quiz`` are rejected before send.\n */\nexport type LoopInputIntentHint = IntentHint | (string & {});\n\n/** Returns an error message when ``hint`` is a removed legacy value; otherwise null. */\nexport function validateLoopInputIntentHint(hint: string): string | null {\n const key = hint.trim().toLowerCase();\n if (key === \"direct_llm\" || key === \"quiz\") {\n return REMOVED_INTENT_HINT_MESSAGES[key];\n }\n return null;\n}\n\n/** Phases emitted on ``mode=messages`` for user-visible loop assistant output. */\nexport const LOOP_ASSISTANT_OUTPUT_PHASES = [\n \"goal_completion\",\n \"quiz\",\n \"autonomous_goal\",\n \"direct_model\",\n \"text_completion\",\n \"image_to_text\",\n \"ocr\",\n \"embed\",\n \"plan_direct\",\n] as const;\n\nexport type LoopAssistantOutputPhase = (typeof LOOP_ASSISTANT_OUTPUT_PHASES)[number];\n\n/** Default deliverable phases for triarch-style apps (direct hints + agent outputs). */\nexport const DEFAULT_DELIVERABLE_PHASES: ReadonlySet<string> = new Set([\n \"quiz\",\n \"goal_completion\",\n \"direct_model\",\n \"text_completion\",\n \"image_to_text\",\n \"ocr\",\n \"embed\",\n]);\n","/**\n * Client-facing event namespace constants for the Soothe daemon wire protocol.\n *\n * Internal catalog types (`soothe.internal.*`) are server-only and are never\n * broadcast to WebSocket clients. Do not add them here.\n *\n * Format: soothe.<domain>.<component>.<action>\n */\n\nimport { VerbosityTier } from \"./verbosity.js\";\n\n// Plan events (client UX)\nexport const EventPlanCreated = \"soothe.cognition.plan.created\";\n\n// Explore subagent events\nexport const EventExploreStarted = \"soothe.subagent.explore.started\";\nexport const EventExploreMilestone = \"soothe.subagent.explore.milestone\";\nexport const EventExploreStepCompleted = \"soothe.subagent.explore.step.completed\";\nexport const EventExploreCompleted = \"soothe.subagent.explore.completed\";\n\n// Tacitus subagent events\nexport const EventTacitusStarted = \"soothe.subagent.tacitus.started\";\nexport const EventTacitusGatherSummary = \"soothe.subagent.tacitus.gather.summary\";\nexport const EventTacitusCompleted = \"soothe.subagent.tacitus.completed\";\n\n// Control-plane wire envelopes (not soothe.* catalog events)\nexport const EventReplayComplete = \"replay_complete\";\nexport const EventLoopReattachedWire = \"loop_reattached\";\n\n// Card ledger replay frames\nexport const EventCardReplayBegin = \"card.replay_begin\";\nexport const EventCardCreated = \"card.created\";\nexport const EventCardReplayEnd = \"card.replay_end\";\n\n// Tool events\nexport const EventToolStarted = \"soothe.tool.execution.started\";\nexport const EventToolCompleted = \"soothe.tool.execution.completed\";\nexport const EventToolError = \"soothe.tool.execution.error\";\n\n// Stream tool call events\nexport const EventStreamToolCallUpdate = \"soothe.stream.tool_call.update\";\nexport const EventToolCallUpdatesBatch = \"tool_call_updates_batch\";\n\n// StrangeLoop events (cognition domain)\nexport const EventStrangeLoopStarted = \"soothe.cognition.strange_loop.started\";\nexport const EventStrangeLoopCompleted = \"soothe.cognition.strange_loop.completed\";\nexport const EventStrangeLoopPlanDecision = \"soothe.cognition.strange_loop.plan.decision\";\nexport const EventStrangeLoopReasoned = \"soothe.cognition.strange_loop.reasoned\";\nexport const EventStrangeLoopStepStarted = \"soothe.cognition.strange_loop.step.started\";\nexport const EventStrangeLoopStepQueued = \"soothe.cognition.strange_loop.step.queued\";\nexport const EventStrangeLoopStepCompleted = \"soothe.cognition.strange_loop.step.completed\";\nexport const EventStrangeLoopContextCompacted = \"soothe.cognition.strange_loop.context.compacted\";\n\n// Message protocol events (client stream metadata)\nexport const EventMessageReceived = \"soothe.protocol.message.received\";\nexport const EventMessageSent = \"soothe.protocol.message.sent\";\n\n// Output events\nexport const EventFinalReport = \"soothe.output.autonomous.final_report.reported\";\n\n// Autopilot events\nexport const EventAutopilotGoalStatus = \"soothe.autopilot.goal.status\";\nexport const EventAutopilotGoalProgress = \"soothe.autopilot.goal.progress\";\nexport const EventAutopilotGoalCreated = \"soothe.autopilot.goal.created\";\nexport const EventAutopilotGoalCompleted = \"soothe.autopilot.goal.completed\";\nexport const EventAutopilotWorkerAssigned = \"soothe.autopilot.worker.assigned\";\nexport const EventAutopilotWorkerUnassigned = \"soothe.autopilot.worker.unassigned\";\n\n// Error events\nexport const EventGeneralFailed = \"soothe.error.general.failed\";\n\n// ---------------------------------------------------------------------------\n// Namespace parsing\n// ---------------------------------------------------------------------------\n\n/** Splits a 4-segment event namespace into domain, component, and action. */\nexport function parseNamespace(\n ns: string,\n): { domain: string; component: string; action: string } | null {\n const parts = splitNamespace(ns);\n if (parts.length < 4 || parts[0] !== \"soothe\") {\n return null;\n }\n if (parts[1] === \"internal\") {\n return null;\n }\n return { domain: parts[1], component: parts[2], action: parts[3] };\n}\n\nfunction splitNamespace(ns: string): string[] {\n const parts: string[] = [];\n let start = 0;\n for (let i = 0; i < ns.length; i++) {\n if (ns[i] === \".\") {\n parts.push(ns.slice(start, i));\n start = i + 1;\n }\n }\n parts.push(ns.slice(start));\n return parts;\n}\n\n// ---------------------------------------------------------------------------\n// Classification\n// ---------------------------------------------------------------------------\n\n/** Returns the VerbosityTier for a given event type string. */\nexport function classifyEventVerbosity(eventTypeOrNamespace: string): VerbosityTier {\n const parsed = parseNamespace(eventTypeOrNamespace);\n if (!parsed) {\n return classifyByEventTypeString(eventTypeOrNamespace);\n }\n return classifyByDomainAndComponent(parsed.domain, parsed.component, eventTypeOrNamespace);\n}\n\nfunction classifyByDomainAndComponent(\n domain: string,\n _component: string,\n full: string,\n): VerbosityTier {\n switch (domain) {\n case \"cognition\":\n return VerbosityTier.Normal;\n case \"protocol\":\n return VerbosityTier.Detailed;\n case \"tool\":\n return VerbosityTier.Internal;\n case \"subagent\":\n return classifySubagentEvent(full);\n case \"autopilot\":\n return VerbosityTier.Normal;\n case \"output\":\n case \"error\":\n return VerbosityTier.Quiet;\n default:\n return VerbosityTier.Normal;\n }\n}\n\nfunction classifySubagentEvent(full: string): VerbosityTier {\n const parsed = parseNamespace(full);\n if (!parsed) return VerbosityTier.Normal;\n switch (parsed.action) {\n case \"started\":\n case \"completed\":\n return VerbosityTier.Normal;\n default:\n return VerbosityTier.Detailed;\n }\n}\n\nfunction classifyByEventTypeString(eventType: string): VerbosityTier {\n if (eventType === EventFinalReport || eventType === EventGeneralFailed) {\n return VerbosityTier.Quiet;\n }\n if (eventType === EventToolStarted) {\n return VerbosityTier.Internal;\n }\n return VerbosityTier.Normal;\n}\n\n// ---------------------------------------------------------------------------\n// Event classification helpers\n// ---------------------------------------------------------------------------\n\n/** Event types that represent completion milestones. */\nexport function isCompletionEvent(eventType: string): boolean {\n return (\n eventType.endsWith(\".completed\") ||\n eventType.endsWith(\".failed\") ||\n eventType === EventGeneralFailed\n );\n}\n\n/** Lifecycle subagent events (started/completed) for progress UI. */\nexport function isSubagentProgressEvent(eventType: string): boolean {\n const parsed = parseNamespace(eventType);\n if (!parsed || parsed.domain !== \"subagent\") {\n return false;\n }\n return parsed.action === \"started\" || parsed.action === \"completed\";\n}\n","/**\n * Inbound-frame multiplexer for the protocol-1 client.\n *\n * Routes inbound protocol-1 frames to the correct waiter by `(type, id)`\n * instead of discarding non-matching events. This makes the Client safe for\n * concurrent RPCs and lets an active subscription stream coexist with RPC\n * waits without starvation.\n *\n * Routing rules:\n * - `response`/`error` with `id` in pending RPCs → pending RPC waiter\n * - `next`/`complete` with `id` in pending subs → pending subscription waiter\n * - `receipt_response` with `receipt` in receipts → receipt waiter\n * - everything else → not consumed (flows to\n * the application event\n * stream / resolver queue)\n *\n * `ping`/`pong`/`connection_ack` are id-less lifecycle frames handled by the\n * Client before reaching the multiplexer; the multiplexer leaves them\n * un-consumed so the Client's existing handlers still see them.\n *\n * A frame routed to a waiter is consumed (returns `true`) and must NOT be\n * forwarded to the resolver queue / event stream.\n */\n\nimport { DaemonError } from \"./errors.js\";\n\n/** A single in-flight RPC wait. */\ninterface PendingCall {\n /** Resolve with the `result` object on `response`; reject with DaemonError on `error`. */\n resolve: (result: Record<string, unknown>) => void;\n reject: (err: Error) => void;\n}\n\n/** A single in-flight subscription stream. */\ninterface PendingSubscription {\n /** Push `next`/`complete` frames to the subscriber. */\n push: (frame: Record<string, unknown>) => void;\n /** Resolves when the waiter has gone away (unsubscribed/timed out). */\n done: Promise<void>;\n /** Internal — resolves `done`. */\n resolveDone: () => void;\n /** Whether the waiter is still registered. */\n settled: boolean;\n}\n\n/**\n * Multiplexer holds pending RPC, subscription, and receipt waiters keyed by\n * their correlation id. The Client consults `route()` for each inbound frame\n * before pushing it to the resolver queue.\n */\nexport class Multiplexer {\n private rpcs = new Map<string, PendingCall>();\n private subs = new Map<string, PendingSubscription>();\n private receipts = new Map<string, (frame: Record<string, unknown>) => void>();\n\n /**\n * Installs a pending RPC wait keyed by `id`. Returns the pending call and an\n * unregister function that MUST be called when the wait ends (success,\n * timeout, or cancel) to avoid leaks. If a late response arrives after the\n * caller has unregistered, it is dropped (log-and-drop) — no leak.\n */\n registerRPC(id: string): {\n call: Promise<Record<string, unknown>>;\n unregister: () => void;\n } {\n let callResolve!: (result: Record<string, unknown>) => void;\n let callReject!: (err: Error) => void;\n const call = new Promise<Record<string, unknown>>((resolve, reject) => {\n callResolve = resolve;\n callReject = reject;\n });\n const pending: PendingCall = { resolve: callResolve, reject: callReject };\n this.rpcs.set(id, pending);\n const unregister = () => {\n // Only delete if still our entry (a later registration with the same id\n // should not be clobbered).\n if (this.rpcs.get(id) === pending) {\n this.rpcs.delete(id);\n }\n };\n return { call, unregister };\n }\n\n /**\n * Installs a pending subscription stream keyed by `id`. Returns the stream\n * channel (an async-iterable-like push sink), a `done` signal, and an\n * unregister function. The Client pushes `next`/`complete` frames via\n * `push`; the application reads from the channel.\n */\n registerSubscription(id: string): {\n push: (frame: Record<string, unknown>) => void;\n done: Promise<void>;\n unregister: () => void;\n } {\n let resolveDone!: () => void;\n const done = new Promise<void>(resolve => {\n resolveDone = resolve;\n });\n const pending: PendingSubscription = {\n push: () => {\n // Overridden by the caller via the returned push closure below.\n },\n done,\n resolveDone,\n settled: false,\n };\n // Wire the push closure to the subscription's push so unregister can\n // short-circuit later deliveries.\n const push = (frame: Record<string, unknown>) => {\n if (pending.settled) return;\n pending.push(frame);\n };\n // Default push is a no-op until the caller installs a real sink. The\n // Client wires a real sink after registering; this guards against a race\n // where a frame arrives between register and sink-install.\n pending.push = () => {};\n this.subs.set(id, pending);\n const unregister = () => {\n if (this.subs.get(id) === pending) {\n pending.settled = true;\n this.subs.delete(id);\n resolveDone();\n }\n };\n return { push, done, unregister };\n }\n\n /**\n * Installs a pending receipt wait keyed by `receipt`. Returns an unregister\n * function.\n */\n registerReceipt(receipt: string): {\n wait: Promise<Record<string, unknown>>;\n unregister: () => void;\n } {\n let resolveWait!: (frame: Record<string, unknown>) => void;\n const wait = new Promise<Record<string, unknown>>(resolve => {\n resolveWait = resolve;\n });\n this.receipts.set(receipt, resolveWait);\n const unregister = () => {\n this.receipts.delete(receipt);\n };\n return { wait, unregister };\n }\n\n /**\n * Wires a real sink for a registered subscription's `push`. Called by the\n * Client right after `registerSubscription` to install the channel/queue the\n * application reads from.\n */\n setSubscriptionSink(id: string, sink: (frame: Record<string, unknown>) => void): void {\n const sub = this.subs.get(id);\n if (sub) sub.push = sink;\n }\n\n /**\n * Inspects one decoded frame, delivers it to a matching waiter if one\n * exists, and returns `true` (consumed). Returns `false` for frames with no\n * matching waiter — these flow on to the resolver queue / event stream.\n * Safe to call from the message handler.\n */\n route(frame: Record<string, unknown>): boolean {\n if (!frame || typeof frame !== \"object\") return false;\n const typ = frame.type as string | undefined;\n const id = frame.id as string | undefined;\n\n if (typ === \"response\" || typ === \"error\") {\n if (!id) return false;\n const pc = this.rpcs.get(id);\n if (!pc) return false;\n if (typ === \"error\") {\n const errObj =\n (frame.error as {\n code?: number;\n message?: string;\n data?: unknown;\n }) ?? {};\n const code = typeof errObj.code === \"number\" ? errObj.code : -32603;\n const message = errObj.message ?? \"daemon error\";\n pc.reject(new DaemonError(code, message, errObj.data));\n } else {\n const result = (frame.result as Record<string, unknown> | undefined) ?? frame;\n pc.resolve(result);\n }\n // Waiter is single-shot; remove so a duplicate late frame is dropped.\n this.rpcs.delete(id);\n return true;\n }\n\n if (typ === \"next\" || typ === \"complete\") {\n if (!id) return false;\n const ps = this.subs.get(id);\n if (!ps) return false;\n if (ps.settled) return true; // waiter gone; consume to avoid re-forwarding\n ps.push(frame);\n return true;\n }\n\n if (typ === \"receipt_response\") {\n const rid = frame.receipt as string | undefined;\n if (!rid) return false;\n const ch = this.receipts.get(rid);\n if (!ch) return false;\n ch(frame);\n this.receipts.delete(rid);\n return true;\n }\n\n return false;\n }\n\n /** Reports whether an RPC waiter is registered for `id`. */\n hasRPCWaiter(id: string): boolean {\n return this.rpcs.has(id);\n }\n}\n","/**\n * Shared stream/turn terminal frame helpers for Client and DaemonSession.\n *\n * Keeps peel-at-turn-start and turn-end detection on one vocabulary so leftover\n * prior-goal terminals cannot blank the next query.\n */\n\nimport {\n EventCardCreated,\n EventCardReplayBegin,\n EventCardReplayEnd,\n EventPlanCreated,\n EventStrangeLoopCompleted,\n EventStrangeLoopStepCompleted,\n EventStrangeLoopStepQueued,\n EventStrangeLoopStepStarted,\n} from \"./events.js\";\n\n/** Daemon turn-scoped stream end custom type. */\nexport const STREAM_END = \"soothe.stream.end\";\n\nexport const TURN_END_CUSTOM_TYPES: ReadonlySet<string> = new Set([\n STREAM_END,\n EventStrangeLoopCompleted,\n]);\n\nconst TURN_PROGRESS_CUSTOM_TYPES: ReadonlySet<string> = new Set([\n EventPlanCreated,\n EventStrangeLoopStepStarted,\n EventStrangeLoopStepQueued,\n EventStrangeLoopStepCompleted,\n]);\n\n/** Handshake / card-replay / subscription leftovers safe to drop at turn start. */\nexport const STALE_TURN_PENDING_TYPES: ReadonlySet<string> = new Set([\n \"connection_ack\",\n EventCardReplayBegin,\n EventCardReplayEnd,\n EventCardCreated,\n \"complete\",\n]);\n\n/** True when `data` is a turn-scoped terminal custom payload. */\nexport function isTurnEndCustomData(data: unknown): data is Record<string, unknown> {\n if (!data || typeof data !== \"object\") return false;\n const customType = String((data as Record<string, unknown>).type ?? \"\").trim();\n if (!TURN_END_CUSTOM_TYPES.has(customType)) return false;\n if (customType === STREAM_END) {\n const scope = String((data as Record<string, unknown>).scope ?? \"turn\")\n .trim()\n .toLowerCase();\n return scope === \"\" || scope === \"turn\";\n }\n return true;\n}\n\n/**\n * True when a chunk proves the active turn has non-intake progress.\n * Used so late prior-goal stream.end cannot close a turn that has only seen\n * intake lifecycle (e.g. plan.phase).\n */\nexport function isTurnProgressChunk(mode: string, data: unknown): boolean {\n if (mode === \"messages\" || mode === \"updates\") return true;\n if (mode !== \"custom\" || !data || typeof data !== \"object\") return false;\n if (isTurnEndCustomData(data)) return false;\n const customType = String((data as Record<string, unknown>).type ?? \"\").trim();\n if (TURN_PROGRESS_CUSTOM_TYPES.has(customType)) return true;\n if (customType.startsWith(\"soothe.cognition.strange_loop.step\")) return true;\n return false;\n}\n\n/** Return a peel label when `event` is safe to drop at turn start. */\nexport function stalePendingFrameLabel(event: Record<string, unknown>): string | null {\n const eventType = String(event.type ?? \"\");\n if (STALE_TURN_PENDING_TYPES.has(eventType)) return eventType;\n\n if (eventType === \"next\") {\n const payload = event.payload;\n if (!payload || typeof payload !== \"object\") return null;\n const p = payload as Record<string, unknown>;\n const staleMode = String(p.mode ?? \"\");\n if (STALE_TURN_PENDING_TYPES.has(staleMode)) return staleMode;\n const inner = p.data;\n if (inner && typeof inner === \"object\") {\n return stalePendingFrameLabel(inner as Record<string, unknown>);\n }\n return null;\n }\n\n if (eventType === \"event\") {\n const mode = String(event.mode ?? \"\");\n const data = event.data;\n if (mode === \"custom\" && isTurnEndCustomData(data)) {\n return String((data as Record<string, unknown>).type ?? \"\").trim();\n }\n }\n return null;\n}\n\n/** True when the client should bump delivery_ack sequence for this frame. */\nexport function inboundNeedsDeliveryAck(event: Record<string, unknown>): boolean {\n const eventType = String(event.type ?? \"\");\n if (eventType === \"complete\") return true;\n if (eventType === \"next\") {\n const payload = event.payload;\n if (!payload || typeof payload !== \"object\") return false;\n const p = payload as Record<string, unknown>;\n const inner = p.data;\n if (!inner || typeof inner !== \"object\") return false;\n if (String(p.mode ?? \"\") === \"event\") {\n return inboundNeedsAckFromEventShape(inner as Record<string, unknown>);\n }\n return false;\n }\n if (eventType === \"event\") return inboundNeedsAckFromEventShape(event);\n return false;\n}\n\nfunction inboundNeedsAckFromEventShape(event: Record<string, unknown>): boolean {\n const mode = String(event.mode ?? \"\");\n const data = event.data;\n if (mode === \"custom\" && isTurnEndCustomData(data)) return true;\n if (mode === \"messages\" && Array.isArray(data) && data.length > 0) {\n const body = data[0];\n if (!body || typeof body !== \"object\") return false;\n const t = String((body as Record<string, unknown>).type ?? \"\");\n return t === STREAM_END || t.includes(\"stream.end\");\n }\n return false;\n}\n\n/** Extract loop_id from a frame or nested next payload. */\nexport function extractLoopIdFromInbound(event: Record<string, unknown>): string {\n const direct = String(event.loop_id ?? \"\").trim();\n if (direct) return direct;\n if (String(event.type ?? \"\") !== \"next\") return \"\";\n const payload = event.payload;\n if (!payload || typeof payload !== \"object\") return \"\";\n const p = payload as Record<string, unknown>;\n const fromPayload = String(p.loop_id ?? \"\").trim();\n if (fromPayload) return fromPayload;\n const inner = p.data;\n if (inner && typeof inner === \"object\") {\n return String((inner as Record<string, unknown>).loop_id ?? \"\").trim();\n }\n return \"\";\n}\n","/**\n * Inbound drop priorities (lower = keep). Python WebSocketClient parity.\n */\n\nimport { STREAM_END, isTurnEndCustomData } from \"./stream_terminal.js\";\n\nexport const DROP_PRIORITY_CRITICAL = 0;\nexport const DROP_PRIORITY_HIGH = 1;\nexport const DROP_PRIORITY_NORMAL = 2;\n\n/** Pending / messageBuffer cap (Python inbound queue parity). */\nexport const DEFAULT_INBOUND_MAX_SIZE = 20_000;\n\n/** Return drop priority for an inbound frame. */\nexport function inboundFrameDropPriority(event: Record<string, unknown> | null | undefined): number {\n if (!event) return DROP_PRIORITY_CRITICAL;\n let eventType = String(event.type ?? \"\");\n if (eventType === \"event_batch\" || eventType === \"tool_call_updates_batch\") {\n return DROP_PRIORITY_HIGH;\n }\n if (eventType === \"next\") {\n const payload = event.payload;\n if (payload && typeof payload === \"object\") {\n const p = payload as Record<string, unknown>;\n const innerMode = String(p.mode ?? \"\");\n const innerData = p.data;\n if (innerMode === \"messages\") {\n if (messagesWireTerminal(innerData)) return DROP_PRIORITY_CRITICAL;\n if (Array.isArray(innerData) && innerData[0] && typeof innerData[0] === \"object\") {\n if (String((innerData[0] as Record<string, unknown>).phase ?? \"\") === \"goal_completion\") {\n return DROP_PRIORITY_CRITICAL;\n }\n }\n }\n if (String(p.type ?? \"\") === \"complete\") return DROP_PRIORITY_CRITICAL;\n if (innerData && typeof innerData === \"object\") {\n return inboundFrameDropPriority(innerData as Record<string, unknown>);\n }\n eventType = String(p.type ?? \"\");\n }\n }\n if (eventType === \"complete\" || eventType === \"error\" || eventType === \"connection_ack\") {\n return DROP_PRIORITY_CRITICAL;\n }\n if (eventType === \"status\") {\n const state = String(event.state ?? \"\");\n if ([\"idle\", \"running\", \"stopped\", \"detached\"].includes(state)) {\n return DROP_PRIORITY_CRITICAL;\n }\n }\n if (eventType === \"event\") {\n const mode = String(event.mode ?? \"\");\n const data = event.data;\n if (mode === \"custom\") {\n if (isTurnEndCustomData(data)) return DROP_PRIORITY_CRITICAL;\n if (data && typeof data === \"object\") {\n const customType = String((data as Record<string, unknown>).type ?? \"\");\n if (customType.startsWith(\"soothe.cognition.\")) return DROP_PRIORITY_HIGH;\n if (customType.startsWith(\"soothe.error.\") || customType === \"stream_degraded\") {\n return DROP_PRIORITY_CRITICAL;\n }\n if (customType === \"soothe.ux.stream_tool_wire.tool_call_updates_batch\") {\n return DROP_PRIORITY_HIGH;\n }\n }\n }\n if (mode === \"messages\") {\n if (messagesWireTerminal(data)) return DROP_PRIORITY_CRITICAL;\n if (Array.isArray(data) && data[0] && typeof data[0] === \"object\") {\n if (String((data[0] as Record<string, unknown>).phase ?? \"\") === \"goal_completion\") {\n return DROP_PRIORITY_CRITICAL;\n }\n }\n }\n }\n return DROP_PRIORITY_NORMAL;\n}\n\nfunction messagesWireTerminal(data: unknown): boolean {\n if (!Array.isArray(data) || data.length === 0) return false;\n const body = data[0];\n if (!body || typeof body !== \"object\") return false;\n const t = String((body as Record<string, unknown>).type ?? \"\");\n return t === STREAM_END || t.includes(\"stream.end\");\n}\n","/**\n * Client manages a WebSocket session with the Soothe daemon.\n *\n * After close(), a new Client must be created to reconnect. The connection\n * begins with a bidirectional connection_init/connection_ack handshake; no\n * requests are accepted until the daemon reports readiness_state \"ready\".\n */\n\nimport { EventEmitter } from \"node:events\";\nimport WebSocket from \"ws\";\nimport type { Config } from \"./config.js\";\nimport { defaultConfig } from \"./config.js\";\nimport { DaemonError, DisconnectCause, ReconnectError, StaleLoopError } from \"./errors.js\";\nimport { Multiplexer } from \"./multiplexer.js\";\nimport type { LoopInputIntentHint } from \"./intent_hints.js\";\nimport { validateLoopInputIntentHint } from \"./intent_hints.js\";\nimport { extractLoopIdFromInbound, inboundNeedsDeliveryAck, stalePendingFrameLabel } from \"./stream_terminal.js\";\nimport {\n DEFAULT_INBOUND_MAX_SIZE,\n DROP_PRIORITY_NORMAL,\n inboundFrameDropPriority,\n} from \"./inbound_priority.js\";\nimport {\n CLIENT_VERSION,\n DEFAULT_CLIENT_CAPABILITIES,\n PROTO_VERSION,\n connectionInitEnvelope,\n decodeMessage,\n disconnectEnvelope,\n newLoopNewMessage,\n newRequestID,\n notificationEnvelope,\n pingEnvelope,\n pongEnvelope,\n requestEnvelope,\n splitWirePayload,\n subscribeEnvelope,\n unsubscribeEnvelope,\n type ConnectionAckEnvelope,\n type DecodedMessage,\n type LoopNewOptions,\n type MethodName,\n} from \"./protocol.js\";\n\n/** Input options for `sendInput` (loop_input). */\nexport interface InputOptions {\n /** Subscribed StrangeLoop id (required for loop_input). */\n loopID?: string;\n autonomous?: boolean;\n maxIterations?: number;\n subagent?: string;\n /** @deprecated Ignored by daemon; loop_input always uses non-interactive autonomous mode. */\n interactive?: boolean;\n model?: string;\n modelParams?: Record<string, unknown>;\n attachments?: Record<string, unknown>[];\n /** Daemon direct-model hint or agent-path pass-through (resume_clarification, skill:foo). */\n intentHint?: LoopInputIntentHint;\n /** JSON Schema for structured output (text_completion or image_to_text). */\n responseSchema?: Record<string, unknown>;\n /** Provider schema name for structured output. */\n responseSchemaName?: string;\n /** Strict mode for JSON schema (default true). */\n responseSchemaStrict?: boolean;\n /** Clarification relay mode (\"auto\" / \"manual\"). */\n clarificationMode?: string;\n /** Treat this input as answer to pending clarification interrupt. */\n clarificationAnswer?: boolean;\n /** Per-question answers for multi-question clarifications. */\n clarificationAnswers?: string[];\n}\n\n/** Capability set negotiated with the daemon. */\nexport type NegotiatedCapabilities = ReadonlySet<string>;\n\nexport class Client extends EventEmitter {\n private url: string;\n private config: Config;\n private ws: WebSocket | null = null;\n private messageBuffer: DecodedMessage[] = [];\n private inboundMaxSize = DEFAULT_INBOUND_MAX_SIZE;\n private inboundDroppedCount = 0;\n private onStreamDegraded: ((dropped: number, reason: string) => void) | null = null;\n private resolvers: Array<(value: DecodedMessage | null) => void> = [];\n // Protocol-1 handshake state\n private handshakeComplete = false;\n private negotiatedCapabilities: NegotiatedCapabilities = new Set();\n private protocolVersion: string | null = null;\n private readinessState: string | null = null;\n private heartbeatIntervalMs = 0;\n private heartbeatTimer: NodeJS.Timeout | null = null;\n private lastPongMonotonic = 0;\n // Mid-session drop signal. The 'disconnected' event is\n // emitted exactly once when the connection drops, carrying a DisconnectCause\n // that distinguishes clean (peer `disconnect`) from unclean (read/write\n // error or missed pong). `disconnFired` guards the once-only delivery.\n private disconnFired = false;\n // Pending-request/subscription multiplexer. Routes\n // inbound frames by (type, id) instead of discarding non-matching events.\n private mux = new Multiplexer();\n private deliveryRecvSeq = new Map<string, number>();\n private deliveryAckedSeq = new Map<string, number>();\n\n constructor(url: string, config?: Config) {\n super();\n this.url = url;\n this.config = config ?? defaultConfig();\n }\n\n // ---------------------------------------------------------------------------\n // Connection lifecycle\n // ---------------------------------------------------------------------------\n\n /**\n * Dials the Soothe daemon WebSocket and completes the protocol-1 handshake\n * (connection_init → connection_ack with readiness_state \"ready\").\n */\n connect(): Promise<void> {\n return new Promise((resolve, reject) => {\n const ws = new WebSocket(this.url, {\n handshakeTimeout: 10_000,\n });\n\n ws.on(\"open\", () => {\n this.ws = ws;\n // Reset the drop signal and multiplexer for a fresh connection so\n // reconnect() on the same Client starts with a clean slate.\n this.disconnFired = false;\n this._lastCause = null;\n this.mux = new Multiplexer();\n // Kick off the protocol-1 handshake; resolve connect() once ready.\n this._performHandshake()\n .then(ack => {\n this.handshakeComplete = true;\n this.readinessState = ack.result?.readiness_state ?? \"ready\";\n this._startHeartbeat();\n resolve();\n })\n .catch(err => {\n // Handshake failed — tear down the underlying socket so server\n // close() does not hang on a lingering connection.\n this._stopHeartbeat();\n this.ws = null;\n this.handshakeComplete = false;\n try {\n ws.close(1011, \"handshake failed\");\n } catch {\n // ignore\n }\n reject(err);\n });\n });\n\n ws.on(\"error\", err => {\n // A write/read error indicates a broken connection — signal an unclean\n // drop so consumers (e.g. ConnectionPool) can reconnect + reattach.\n // Idempotent if the close handler already fired.\n this._signalDisconnect(DisconnectCause.Unclean);\n if (!this.ws) {\n reject(new Error(`soothe dial: ${err.message}`));\n }\n });\n\n ws.on(\"message\", (data: WebSocket.RawData) => {\n const text = data.toString();\n for (const frame of splitWirePayload(text)) {\n let msg: DecodedMessage | null;\n try {\n msg = decodeMessage(frame);\n } catch {\n continue;\n }\n if (msg === null) continue;\n\n // Intercept heartbeat frames.\n const m = msg as Record<string, unknown>;\n if (m.type === \"ping\") {\n this._sendRaw(pongEnvelope());\n continue;\n }\n if (m.type === \"pong\") {\n this.lastPongMonotonic = Date.now();\n continue;\n }\n // A `disconnect` notification is a clean peer-initiated drop\n //; loops keep running server-side.\n if (m.type === \"disconnect\") {\n this._signalDisconnect(DisconnectCause.Clean);\n // Still surface it to listeners (existing behavior) before close.\n }\n\n // Route solicited frames (response/error/next/complete/receipt with\n // a matching pending multiplexer waiter) to their waiters; do not\n // forward to the resolver queue.\n if (this.mux.route(m)) {\n this._trackInboundDeliveryAck(m);\n continue;\n }\n\n this._trackInboundDeliveryAck(m);\n\n // If a reader is waiting, deliver directly; otherwise buffer for\n // later readEvent/receiveMessages calls. Never do both — a single\n // inbound frame must be consumed exactly once.\n const resolver = this.resolvers.shift();\n if (resolver) {\n resolver(msg);\n } else {\n this.enqueueMessageBuffer(msg);\n }\n this.emit(\"message\", msg);\n }\n });\n\n ws.on(\"close\", () => {\n this.ws = null;\n this._stopHeartbeat();\n this.handshakeComplete = false;\n // Signal an unclean drop (a close without a `disconnect` notification\n // is an abrupt loss). Idempotent if a clean signal already fired.\n this._signalDisconnect(DisconnectCause.Unclean);\n this.emit(\"close\");\n // Resolve any pending readEvent calls with null.\n for (const resolver of this.resolvers) {\n resolver(null);\n }\n this.resolvers = [];\n });\n });\n }\n\n /** Sends a `disconnect` notification and closes the WebSocket. */\n close(): void {\n this._stopHeartbeat();\n if (!this.ws) return;\n try {\n // Best-effort clean disconnect (daemon keeps loops running).\n if (this.ws.readyState === WebSocket.OPEN) {\n this.ws.send(JSON.stringify(disconnectEnvelope()));\n }\n this.ws.close(1000, \"\");\n } catch {\n // ignore close errors\n }\n this.ws = null;\n this.handshakeComplete = false;\n }\n\n /** Returns whether the client has an active, handshaked WebSocket connection. */\n isConnected(): boolean {\n return this.ws !== null && this.ws.readyState === WebSocket.OPEN && this.handshakeComplete;\n }\n\n // ---------------------------------------------------------------------------\n // Mid-session drop signal + reconnect/reattach\n // ---------------------------------------------------------------------------\n\n /**\n * Returns whether the connection has dropped (the `'disconnected'` event has\n * fired). Pair with the `'disconnected'` event for the signal. Use\n * `disconnectCause()` to read the cause.\n */\n isDisconnected(): boolean {\n return this.disconnFired;\n }\n\n /**\n * Returns the cause of the most recent drop, or `null` if the connection has\n * not dropped. Clean follows a `disconnect` notification (loops keep running\n * server-side); unclean is a read/write error or missed pong.\n */\n disconnectCause(): DisconnectCause | null {\n if (!this.disconnFired) return null;\n return this._lastCause ?? DisconnectCause.Unclean;\n }\n\n private _lastCause: DisconnectCause | null = null;\n\n /**\n * Delivers the disconnect cause exactly once via the `'disconnected'` event.\n * Safe to call from any path; subsequent calls are no-ops. Listeners receive\n * the cause as the event argument.\n */\n private _signalDisconnect(cause: DisconnectCause): void {\n if (this.disconnFired) return;\n this.disconnFired = true;\n this._lastCause = cause;\n // Emit synchronously so a listener wired during the same message-handler\n // tick receives it. Callers that attach a listener after the drop can poll\n // isDisconnected()/disconnectCause() instead — mirroring Go's closed\n // buffered channel, which unblocks late readers immediately.\n try {\n this.emit(\"disconnected\", cause);\n } catch {\n // Listener errors must not propagate into the read loop.\n }\n }\n\n /**\n * Re-dials the daemon and re-handshakes after a connection drop.\n * Does not re-establish loop subscriptions; follow with\n * `reattachAndProbe()` to resume a loop session. The caller should invoke\n * this after the `'disconnected'` event fires. Reuses the same Client,\n * resetting the drop signal and multiplexer.\n *\n * Performs bounded-retry backoff using the configured reconnect knobs.\n */\n async reconnect(): Promise<void> {\n const maxAttempts = this.config.reconnectMaxAttempts || 10;\n const initialDelay = this.config.reconnectInitialDelay || 500;\n const maxDelay = this.config.reconnectMaxDelay || 10_000;\n\n let lastErr: Error | null = null;\n let delay = initialDelay;\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n try {\n // connect() resets disconnFired / mux and performs the\n // connection_init/connection_ack handshake with readiness retry.\n await this.connect();\n return;\n } catch (err) {\n lastErr = err as Error;\n }\n if (attempt < maxAttempts) {\n await new Promise(resolve => setTimeout(resolve, delay));\n delay = Math.min(delay * 2, maxDelay);\n }\n }\n throw new ReconnectError(this.url, maxAttempts, lastErr ?? new Error(\"unknown error\"));\n }\n\n /**\n * Resumes an existing loop after a reconnect: issues `loop_reattach`,\n * re-subscribes to `loop_events`, then runs a `loop_get` liveness probe to\n * detect stale loops that accept the handshake but silently drop input.\n * Returns a `StaleLoopError` when the probe fails; callers should fall back\n * to a fresh `loop_new` bootstrap.\n *\n * Note: connection-level readiness is the handshake's readiness_state\n * (+ daemon_status); loop_get is a loop-scoped probe only, not a readiness\n * probe.\n */\n async reattachAndProbe(loopID: string): Promise<void> {\n if (!loopID || !loopID.trim()) {\n throw new Error(\"soothe: reattachAndProbe requires a loop id\");\n }\n const lid = loopID.trim();\n\n // 1. loop_reattach: reconstruct event history and replay.\n const reattachTimeout = this.config.loopStatusTimeout || 15_000;\n try {\n await this.requestResponse(\n \"loop_reattach\" as unknown as MethodName,\n { loop_id: lid },\n \"loop_reattach\",\n reattachTimeout,\n );\n } catch (err) {\n throw new Error(`loop_reattach: ${(err as Error).message}`);\n }\n\n // 2. Re-subscribe to the loop event stream (: subscribe +\n // method:\"loop_events\"). Confirmation arrives as a `next` frame.\n const subTimeout = this.config.subscriptionTimeout || 10_000;\n try {\n await this.subscribe(\n \"loop_events\",\n { loop_id: lid, verbosity: this.config.verbosityLevel },\n subTimeout,\n );\n } catch (err) {\n throw new Error(`loop events subscription failed: ${(err as Error).message}`);\n }\n\n // 3. loop_get liveness probe — side-effect-free read.\n // A LOOP_NOT_FOUND (-32200) or timeout means the loop is stale: it\n // accepted the reattach handshake but is not actually live.\n const probeTimeout = this.config.reattachProbeTimeout || 5_000;\n try {\n await this.getLoop(lid, probeTimeout);\n } catch (err) {\n if (err instanceof DaemonError && err.code === -32200) {\n throw new StaleLoopError(lid, err);\n }\n // Timeout or other error during probe → treat as stale.\n throw new StaleLoopError(lid, err as Error);\n }\n }\n\n // ---------------------------------------------------------------------------\n // Protocol-1 handshake\n // ---------------------------------------------------------------------------\n\n /** Send connection_init and wait for connection_ack with readiness \"ready\". */\n private async _performHandshake(): Promise<ConnectionAckEnvelope> {\n const init = connectionInitEnvelope({\n client_version: CLIENT_VERSION,\n client_name: \"soothe-client-ts\",\n accept_proto: [PROTO_VERSION],\n capabilities: DEFAULT_CLIENT_CAPABILITIES,\n });\n await this.sendMessage(init);\n\n const deadline = Date.now() + this.config.daemonReadyTimeout;\n while (Date.now() < deadline) {\n const remaining = deadline - Date.now();\n if (remaining <= 0) break;\n const ev = (await this.readEventWithTimeout(remaining)) as Record<string, unknown> | null;\n if (ev === null) {\n throw new Error(\"connection closed during handshake\");\n }\n // Discard the initial `status` frame; keep other frames for later.\n if (ev.type === \"status\") {\n continue;\n }\n if (ev.type !== \"connection_ack\") {\n continue;\n }\n const ack = ev as unknown as ConnectionAckEnvelope;\n const result = ack.result ?? {};\n const state = result.readiness_state ?? \"ready\";\n this.protocolVersion = result.protocol_version ?? PROTO_VERSION;\n this.negotiatedCapabilities = new Set(result.capabilities ?? []);\n this.heartbeatIntervalMs = result.heartbeat_interval_ms ?? 0;\n\n if (state === \"incompatible\") {\n throw new Error(`protocol version incompatible: daemon returned ${this.protocolVersion}`);\n }\n if (state === \"ready\") {\n return ack;\n }\n if (state === \"error\") {\n throw new Error(\"daemon startup failed\");\n }\n if (state === \"degraded\") {\n throw new Error(\"daemon is degraded\");\n }\n // starting / warming — bounded retry by re-sending connection_init.\n await this._sleep(50);\n await this.sendMessage(init);\n }\n throw new Error(`timeout after ${this.config.daemonReadyTimeout}ms waiting for connection_ack`);\n }\n\n // ---------------------------------------------------------------------------\n // Heartbeat\n // ---------------------------------------------------------------------------\n\n private _startHeartbeat(): void {\n if (!this.negotiatedCapabilities.has(\"heartbeat\")) return;\n const interval = this.heartbeatIntervalMs;\n if (interval <= 0) return;\n this.lastPongMonotonic = Date.now();\n this.heartbeatTimer = setInterval(() => this._heartbeatTick(interval), interval);\n }\n\n private _stopHeartbeat(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n }\n\n private _heartbeatTick(intervalMs: number): void {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;\n const timeoutMs = Math.max(10_000, intervalMs * 2);\n const now = Date.now();\n if (now - (this.lastPongMonotonic || now) > intervalMs + timeoutMs) {\n // Dead connection — signal an unclean drop\n // and force close so consumers can reconnect + reattach.\n this._signalDisconnect(DisconnectCause.Unclean);\n try {\n this.ws.close(1001, \"heartbeat timeout\");\n } catch {\n // ignore\n }\n return;\n }\n try {\n this.ws.send(JSON.stringify(pingEnvelope()));\n } catch {\n // ignore transient send failures\n }\n }\n\n private _sleep(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n\n // ---------------------------------------------------------------------------\n // Core messaging\n // ---------------------------------------------------------------------------\n\n /** Serializes msg as JSON and sends it as a WebSocket text frame. */\n sendMessage(msg: unknown): Promise<void> {\n return new Promise((resolve, reject) => {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {\n reject(new Error(\"soothe: not connected\"));\n return;\n }\n const payload = JSON.stringify(msg);\n this.ws.send(payload, err => {\n if (err) {\n // Write failure indicates a broken connection — signal an unclean\n // drop so consumers can reconnect. Idempotent if the read loop\n // already fired.\n this._signalDisconnect(DisconnectCause.Unclean);\n reject(err);\n } else {\n resolve();\n }\n });\n });\n }\n\n /** Low-level send that does not reject on a missing connection (best-effort). */\n private _sendRaw(msg: unknown): void {\n if (!this.ws || this.ws.readyState !== WebSocket.OPEN) return;\n try {\n this.ws.send(JSON.stringify(msg));\n } catch {\n // ignore\n }\n }\n\n /** Returns an async iterable of decoded messages. Ends when connection closes. */\n async *receiveMessages(signal?: AbortSignal): AsyncGenerator<DecodedMessage> {\n while (true) {\n if (signal?.aborted) return;\n\n // Drain buffer first.\n while (this.messageBuffer.length > 0) {\n const msg = this.messageBuffer.shift()!;\n yield msg;\n }\n\n // Wait for next message or close.\n const msg = await new Promise<DecodedMessage | null>(resolve => {\n if (!this.ws) {\n resolve(null);\n return;\n }\n this.resolvers.push(resolve);\n });\n\n if (msg === null) return;\n yield msg;\n }\n }\n\n /** Reads a single event from the daemon. Returns null on connection close. */\n async readEvent(): Promise<Record<string, unknown> | null> {\n if (this.messageBuffer.length > 0) {\n const msg = this.messageBuffer.shift()!;\n return msg as Record<string, unknown>;\n }\n if (!this.ws) return null;\n const msg = await new Promise<DecodedMessage | null>(resolve => {\n this.resolvers.push(resolve);\n });\n if (msg === null) return null;\n return msg as Record<string, unknown>;\n }\n\n /** Reads a single event with a timeout. Returns null on timeout or close. */\n readEventWithTimeout(timeout: number): Promise<Record<string, unknown> | null> {\n if (this.messageBuffer.length > 0) {\n const msg = this.messageBuffer.shift()!;\n return Promise.resolve(msg as Record<string, unknown>);\n }\n if (!this.ws) return Promise.resolve(null);\n\n return new Promise<Record<string, unknown> | null>(resolve => {\n const timer = setTimeout(() => {\n const idx = this.resolvers.indexOf(resolver);\n if (idx >= 0) this.resolvers.splice(idx, 1);\n resolve(null);\n }, timeout);\n\n const resolver = (val: DecodedMessage | null) => {\n clearTimeout(timer);\n resolve(val as Record<string, unknown> | null);\n };\n\n this.resolvers.push(resolver);\n });\n }\n\n /**\n * Remove stale handshake/terminal frames left in `messageBuffer` before a turn.\n * Returns labels of removed frames (in order).\n */\n peelStalePendingControlEvents(): string[] {\n if (this.messageBuffer.length === 0) return [];\n const kept: DecodedMessage[] = [];\n const removed: string[] = [];\n while (this.messageBuffer.length > 0) {\n const event = this.messageBuffer.shift()! as Record<string, unknown>;\n const label = stalePendingFrameLabel(event);\n if (label !== null) {\n removed.push(label);\n continue;\n }\n kept.push(event as DecodedMessage);\n }\n this.messageBuffer = kept;\n return removed;\n }\n\n /** True when the underlying socket is still open (may not be handshaked). */\n isConnectionAlive(): boolean {\n return this.ws !== null && this.ws.readyState === WebSocket.OPEN;\n }\n\n /** Override pending buffer cap (tests / tuning). */\n setInboundMaxSize(n: number): void {\n if (n > 0) this.inboundMaxSize = n;\n }\n\n /** How many NORMAL-priority frames were dropped under backpressure. */\n inboundDropped(): number {\n return this.inboundDroppedCount;\n }\n\n /** Hook invoked on the first inbound overflow drop. */\n setStreamDegradedCallback(fn: ((dropped: number, reason: string) => void) | null): void {\n this.onStreamDegraded = fn;\n }\n\n private enqueueMessageBuffer(msg: DecodedMessage): void {\n const max = this.inboundMaxSize > 0 ? this.inboundMaxSize : DEFAULT_INBOUND_MAX_SIZE;\n if (this.messageBuffer.length < max) {\n this.messageBuffer.push(msg);\n return;\n }\n const ev = msg as Record<string, unknown>;\n let dropIdx = -1;\n let dropPri = -1;\n for (let i = 0; i < this.messageBuffer.length; i++) {\n const p = inboundFrameDropPriority(this.messageBuffer[i] as Record<string, unknown>);\n if (p > dropPri) {\n dropPri = p;\n dropIdx = i;\n }\n }\n const incomingPri = inboundFrameDropPriority(ev);\n if (dropIdx >= 0 && dropPri >= DROP_PRIORITY_NORMAL) {\n this.messageBuffer.splice(dropIdx, 1);\n this.messageBuffer.push(msg);\n this.noteInboundDrop();\n return;\n }\n if (incomingPri >= DROP_PRIORITY_NORMAL) {\n this.noteInboundDrop();\n return;\n }\n if (this.messageBuffer.length > 0) {\n this.messageBuffer.shift();\n this.noteInboundDrop();\n }\n this.messageBuffer.push(msg);\n }\n\n private noteInboundDrop(): void {\n this.inboundDroppedCount += 1;\n if (this.onStreamDegraded && this.inboundDroppedCount === 1) {\n try {\n this.onStreamDegraded(1, \"inbound_queue_overflow\");\n } catch {\n // ignore callback errors\n }\n }\n }\n\n // ---------------------------------------------------------------------------\n // Protocol-1 RPC primitives\n // ---------------------------------------------------------------------------\n\n /**\n * Reads the next frame directly from the live socket (via a resolver),\n * bypassing `messageBuffer`. Used by RPC waits so that stream events\n * previously buffered for `readEvent()`/`receiveMessages()` consumers are\n * not re-cycled through the RPC wait loop (which would stall behind a\n * continuous subscription stream). Non-RPC frames read here are pushed to\n * `messageBuffer` for the stream readers.\n */\n private readLiveEventWithTimeout(timeout: number): Promise<Record<string, unknown> | null> {\n if (!this.ws) return Promise.resolve(null);\n return new Promise<Record<string, unknown> | null>(resolve => {\n const timer = setTimeout(() => {\n const idx = this.resolvers.indexOf(resolver);\n if (idx >= 0) this.resolvers.splice(idx, 1);\n resolve(null);\n }, timeout);\n\n const resolver = (val: DecodedMessage | null) => {\n clearTimeout(timer);\n resolve(val as Record<string, unknown> | null);\n };\n\n this.resolvers.push(resolver);\n });\n }\n\n /**\n * Sends a `request` envelope and waits for the matching `response` (or\n * `error`) correlated by `id`. Returns the `result` object.\n *\n * Multiplexer-aware: registers a pending RPC wait\n * keyed by the request id so that, even when a `receiveMessages()` reader\n * is concurrently active, the matching `response`/`error` is routed to\n * this caller instead of being discarded or buffered behind a stream.\n * Non-matching frames are routed to their own waiters by the multiplexer\n * or flow on to the resolver queue for stream readers.\n */\n async requestResponse(\n method: MethodName,\n params: Record<string, unknown>,\n responseType?: string,\n timeout: number = 15_000,\n ): Promise<Record<string, unknown>> {\n const req = requestEnvelope(method, params);\n const rid = req.id;\n // Register the RPC waiter BEFORE sending so a fast echo response is not\n // routed before the waiter exists.\n const { call, unregister } = this.mux.registerRPC(rid);\n const label = responseType ?? method;\n try {\n await this.sendMessage(req);\n const result = await this._raceRPC(call, timeout, label);\n return result;\n } finally {\n unregister();\n }\n }\n\n /**\n * Races the multiplexer's RPC promise against a timeout and the connection\n * drop signal. Resolves with the `result` on `response`; rejects with a\n * `DaemonError` on `error`; rejects with a timeout/close error otherwise.\n * The disconnect listener is always removed to avoid accumulating handlers.\n */\n private async _raceRPC(\n call: Promise<Record<string, unknown>>,\n timeout: number,\n label: string,\n ): Promise<Record<string, unknown>> {\n let timer: NodeJS.Timeout | undefined;\n let cleanupDisconnect: () => void = () => {};\n const timeoutP = new Promise<never>((_, reject) => {\n timer = setTimeout(\n () => reject(new Error(`timeout after ${timeout}ms waiting for ${label}`)),\n timeout,\n );\n });\n const closedP = new Promise<never>((_, reject) => {\n if (this.disconnFired) {\n reject(new Error(`connection closed waiting for ${label}`));\n return;\n }\n const onDisconnect = () => {\n reject(new Error(`connection closed waiting for ${label}`));\n };\n this.once(\"disconnected\", onDisconnect);\n cleanupDisconnect = () => this.removeListener(\"disconnected\", onDisconnect);\n });\n try {\n return await Promise.race([call, timeoutP, closedP]);\n } finally {\n if (timer) clearTimeout(timer);\n cleanupDisconnect();\n }\n }\n\n /**\n * Sends a pre-built envelope (e.g. `unsubscribe`) that carries an `id` and\n * waits for the matching `response`/`error`. Used for envelope types that\n * are not `request` (e.g. `unsubscribe` → `autopilot_unsubscribe`) but still\n * expect a correlated response from the daemon.\n */\n private async _requestResponseForEnvelope(\n env: { id: string; proto?: string; type?: string },\n label: string,\n timeout: number,\n ): Promise<Record<string, unknown>> {\n const rid = env.id;\n const { call, unregister } = this.mux.registerRPC(rid);\n try {\n await this.sendMessage(env);\n return await this._raceRPC(call, timeout, label);\n } finally {\n unregister();\n }\n }\n\n /** Sends a fire-and-forget `notification` envelope (no response expected). */\n notify(method: MethodName, params: Record<string, unknown>): Promise<void> {\n return this.sendMessage(notificationEnvelope(method, params));\n }\n\n private _trackInboundDeliveryAck(event: Record<string, unknown>): void {\n if (String(event.type ?? \"\") === \"event_batch\") {\n const events = event.events;\n if (Array.isArray(events)) {\n for (const sub of events) {\n if (sub && typeof sub === \"object\") {\n this._trackInboundDeliveryAck(sub as Record<string, unknown>);\n }\n }\n }\n return;\n }\n if (!inboundNeedsDeliveryAck(event)) return;\n const loopId = extractLoopIdFromInbound(event);\n if (!loopId) return;\n const next = (this.deliveryRecvSeq.get(loopId) ?? 0) + 1;\n this.deliveryRecvSeq.set(loopId, next);\n void this._sendDeliveryAck(loopId, next);\n }\n\n private async _sendDeliveryAck(loopId: string, seq: number): Promise<void> {\n const acked = this.deliveryAckedSeq.get(loopId) ?? 0;\n if (seq <= acked) return;\n this.deliveryAckedSeq.set(loopId, seq);\n if (!this.isConnected()) return;\n try {\n await this.notify(\"delivery_ack\", { loop_id: loopId, seq });\n } catch {\n // best-effort; daemon drain may retry\n }\n }\n\n /**\n * Starts a subscription stream. Returns the subscription `id` for later\n * correlation and `unsubscribe()`. Stream events arrive as `next` frames\n * carrying the same `id`.\n */\n async subscribe(\n method: \"loop_events\" | \"autopilot_events\",\n params: Record<string, unknown>,\n timeout: number = 5_000,\n ): Promise<string> {\n const req = subscribeEnvelope(method, params);\n const subId = req.id;\n await this.sendMessage(req);\n\n // Wait briefly for either a subscription-confirmation `next` or an `error`\n // with the matching id. If neither arrives, assume accepted. Read from the\n // live socket so buffered stream events do not stall the confirmation wait.\n const deadline = Date.now() + timeout;\n while (Date.now() < deadline) {\n const remaining = deadline - Date.now();\n if (remaining <= 0) break;\n const ev = await this.readLiveEventWithTimeout(remaining);\n if (ev === null) break;\n const evId = ev.id as string | undefined;\n if (evId !== subId) {\n this.enqueueMessageBuffer(ev as DecodedMessage);\n continue;\n }\n const typ = ev.type as string;\n if (typ === \"error\") {\n const errObj = (ev.error as { code?: number; message?: string; data?: unknown }) ?? {};\n throw new DaemonError(\n errObj.code ?? -32603,\n errObj.message ?? \"subscription rejected\",\n errObj.data,\n );\n }\n if (typ === \"next\" || typ === \"complete\") {\n // Subscription confirmed (next) or already complete. Re-buffer for the\n // stream reader so it sees the first event.\n this.messageBuffer.unshift(ev as DecodedMessage);\n break;\n }\n }\n return subId;\n }\n\n /** Cancels an active subscription by id. */\n unsubscribe(subscriptionId: string): Promise<void> {\n return this.sendMessage(unsubscribeEnvelope(subscriptionId));\n }\n\n /**\n * Reads the next stream event from a subscription. For `next` frames the\n * `payload` is returned; for `complete`/`error` the full envelope is\n * returned so the caller can inspect termination.\n */\n async next(): Promise<Record<string, unknown> | null> {\n const ev = await this.readEvent();\n if (ev === null) return null;\n if (ev.type === \"next\") {\n return (ev.payload as Record<string, unknown>) ?? {};\n }\n return ev;\n }\n\n // ---------------------------------------------------------------------------\n // High-level API methods\n // ---------------------------------------------------------------------------\n\n /** Sends user input to the daemon (loop_input notification; requires loopID). */\n sendInput(text: string, options?: InputOptions): Promise<void> {\n const loopId = (options?.loopID ?? \"\").trim();\n if (!loopId) {\n return Promise.reject(new Error(\"sendInput requires options.loopID\"));\n }\n const params: Record<string, unknown> = {\n loop_id: loopId,\n content: text,\n autonomous: options?.autonomous ?? false,\n };\n if (options?.maxIterations !== undefined) params.max_iterations = options.maxIterations;\n if (options?.subagent) params.preferred_subagent = options.subagent;\n if (options?.model) params.model = options.model;\n if (options?.modelParams) params.model_params = options.modelParams;\n if (options?.attachments) params.attachments = options.attachments;\n if (options?.intentHint) {\n const hintError = validateLoopInputIntentHint(options.intentHint);\n if (hintError) {\n return Promise.reject(new Error(hintError));\n }\n params.intent_hint = options.intentHint;\n }\n if (options?.responseSchema) params.response_schema = options.responseSchema;\n if (options?.responseSchemaName) params.response_schema_name = options.responseSchemaName;\n if (options?.responseSchemaStrict !== undefined)\n params.response_schema_strict = options.responseSchemaStrict;\n if (options?.clarificationMode) params.clarification_mode = options.clarificationMode;\n if (options?.clarificationAnswer) params.clarification_answer = true;\n if (options?.clarificationAnswers) params.clarification_answers = options.clarificationAnswers;\n return this.notify(\"loop_input\", params);\n }\n\n /** Sends a slash command to the daemon (slash_command notification). */\n sendCommand(cmd: string): Promise<void> {\n return this.notify(\"slash_command\", { cmd });\n }\n\n // ---------------------------------------------------------------------------\n // Loop lifecycle methods\n // ---------------------------------------------------------------------------\n\n /** Requests the daemon to create a new StrangeLoop and waits for the response. */\n sendLoopNew(opts?: LoopNewOptions | string): Promise<void> {\n return this.sendMessage(newLoopNewMessage(opts));\n }\n\n /** Subscribes to events for a loop (subscribe → loop_events). */\n async sendLoopSubscribe(\n loopID: string,\n verbosity: string,\n streamDelivery?: \"batch\" | \"adaptive\" | \"streaming\",\n ): Promise<void> {\n await this.subscribe(\"loop_events\", {\n loop_id: loopID,\n verbosity,\n stream_delivery: streamDelivery,\n });\n }\n\n /** Detaches from a loop (unsubscribe by subscription id). */\n sendLoopDetach(loopID: string): Promise<void> {\n // To preserve the loopID-based signature we send an unsubscribe envelope\n // carrying the loop-derived subscription id.\n return this.sendMessage(unsubscribeEnvelope(loopID));\n }\n\n /** Notifies the daemon that this client is leaving (disconnect notification). */\n sendDetach(): Promise<void> {\n return this.sendMessage(disconnectEnvelope());\n }\n\n /** Requests daemon status check. */\n sendDaemonStatus(): Promise<void> {\n return this.sendMessage(requestEnvelope(\"daemon_status\", {}));\n }\n\n /** Requests daemon shutdown. */\n sendDaemonShutdown(): Promise<void> {\n return this.sendMessage(requestEnvelope(\"daemon_shutdown\", {}));\n }\n\n /** Requests a config section from the daemon. */\n sendConfigGet(section: string): Promise<void> {\n return this.sendMessage(requestEnvelope(\"config_get\", { section }));\n }\n\n // ---------------------------------------------------------------------------\n // Convenience RPC methods (blocking request/response)\n // ---------------------------------------------------------------------------\n\n /** Requests the skills catalog and waits for the response. */\n listSkills(timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\"skills_list\", {}, \"skills_list\", timeout ?? 15_000);\n }\n\n /** Requests the models catalog and waits for the response. */\n listModels(timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\"models_list\", {}, \"models_list\", timeout ?? 15_000);\n }\n\n /** Invokes a skill on the daemon host and receives echo. */\n invokeSkill(skill: string, args?: string, timeout?: number): Promise<Record<string, unknown>> {\n const params: Record<string, unknown> = { skill, args: args ?? \"\" };\n return this.requestResponse(\"invoke_skill\", params, \"invoke_skill\", timeout ?? 120_000);\n }\n\n /** Requests loop list and waits for response. */\n listLoops(timeout?: number, workspace?: string): Promise<Record<string, unknown>> {\n const params: Record<string, unknown> = {};\n if (workspace) params.filter = { workspace };\n return this.requestResponse(\"loop_list\", params, \"loop_list\", timeout ?? 15_000);\n }\n\n /** Requests loop details and waits for response. */\n getLoop(loopID: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\"loop_get\", { loop_id: loopID }, \"loop_get\", timeout ?? 15_000);\n }\n\n /** Requests loop tree and waits for response. */\n getLoopTree(loopID: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\"loop_tree\", { loop_id: loopID }, \"loop_tree\", timeout ?? 15_000);\n }\n\n /** Requests loop deletion and waits for response. */\n deleteLoop(loopID: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\n \"loop_delete\",\n { loop_id: loopID },\n \"loop_delete\",\n timeout ?? 15_000,\n );\n }\n\n /** Requests persisted conversation/activity rows. */\n sendLoopMessages(\n loopID: string,\n limit?: number,\n offset?: number,\n includeEvents?: boolean,\n ): Promise<void> {\n const params: Record<string, unknown> = { loop_id: loopID };\n if (limit !== undefined) params.limit = limit;\n if (offset !== undefined) params.offset = offset;\n if (includeEvents) params.include_events = true;\n return this.sendMessage(requestEnvelope(\"loop_messages\", params));\n }\n\n /** Requests LangGraph checkpoint channel values. */\n sendLoopStateGet(loopID: string): Promise<void> {\n return this.sendMessage(requestEnvelope(\"loop_state_get\", { loop_id: loopID }));\n }\n\n /** Applies partial checkpoint values. */\n sendLoopStateUpdate(\n loopID: string,\n values: Record<string, unknown>,\n asNode?: string,\n ): Promise<void> {\n const params: Record<string, unknown> = { loop_id: loopID, values };\n if (asNode) params.as_node = asNode;\n return this.sendMessage(requestEnvelope(\"loop_state_update\", params));\n }\n\n /** Requests display card ledger snapshot. */\n sendLoopCardsFetch(loopID: string): Promise<void> {\n return this.sendMessage(requestEnvelope(\"loop_cards_fetch\", { loop_id: loopID }));\n }\n\n /** Requests the full loop history. */\n sendLoopHistoryFetch(loopID: string): Promise<void> {\n return this.sendMessage(requestEnvelope(\"loop_history_fetch\", { loop_id: loopID }));\n }\n\n /** Requests MCP server status. */\n sendMCPStatus(): Promise<void> {\n return this.sendMessage(requestEnvelope(\"mcp_status\", {}));\n }\n\n /** Requests daemon config reload. */\n sendConfigReload(): Promise<void> {\n return this.sendMessage(requestEnvelope(\"config_reload\", {}));\n }\n\n /** Submits credentials for daemon-side authentication. */\n sendAuth(accessKey: string, secretKey: string): Promise<void> {\n return this.sendMessage(\n requestEnvelope(\"auth\", { access_key: accessKey, secret_key: secretKey }),\n );\n }\n\n /** Refreshes the daemon-side auth token. */\n sendAuthRefresh(refreshToken: string): Promise<void> {\n return this.sendMessage(requestEnvelope(\"auth_refresh\", { refresh_token: refreshToken }));\n }\n\n /** Requests persisted messages and waits for response. */\n getLoopMessages(\n loopID: string,\n limit?: number,\n offset?: number,\n includeEvents?: boolean,\n timeout?: number,\n ): Promise<Record<string, unknown>> {\n const params: Record<string, unknown> = { loop_id: loopID };\n if (limit !== undefined) params.limit = limit;\n if (offset !== undefined) params.offset = offset;\n if (includeEvents) params.include_events = true;\n return this.requestResponse(\"loop_messages\", params, \"loop_messages\", timeout ?? 15_000);\n }\n\n /** Requests loop state and waits for response. */\n getLoopState(loopID: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\n \"loop_state_get\",\n { loop_id: loopID },\n \"loop_state_get\",\n timeout ?? 15_000,\n );\n }\n\n /** Updates loop state and waits for response. */\n updateLoopState(\n loopID: string,\n values: Record<string, unknown>,\n asNode?: string,\n timeout?: number,\n ): Promise<Record<string, unknown>> {\n const params: Record<string, unknown> = { loop_id: loopID, values };\n if (asNode) params.as_node = asNode;\n return this.requestResponse(\n \"loop_state_update\",\n params,\n \"loop_state_update\",\n timeout ?? 15_000,\n );\n }\n\n /** Requests display cards and waits for response. */\n fetchLoopCards(loopID: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\n \"loop_cards_fetch\",\n { loop_id: loopID },\n \"loop_cards_fetch\",\n timeout ?? 15_000,\n );\n }\n\n /** Requests MCP status and waits for response. */\n getMCPStatus(timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\"mcp_status\", {}, \"mcp_status\", timeout ?? 15_000);\n }\n\n /** Requests loop history and waits for response. */\n fetchLoopHistory(loopID: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\n \"loop_history_fetch\",\n { loop_id: loopID },\n \"loop_history_fetch\",\n timeout ?? 15_000,\n );\n }\n\n /** Requests daemon config reload and waits for response. */\n reloadConfig(timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\"config_reload\", {}, \"config_reload\", timeout ?? 15_000);\n }\n\n /** Submits credentials for daemon-side authentication and waits for response. */\n authenticate(\n accessKey: string,\n secretKey: string,\n timeout?: number,\n ): Promise<Record<string, unknown>> {\n return this.requestResponse(\n \"auth\",\n { access_key: accessKey, secret_key: secretKey },\n \"auth\",\n timeout ?? 15_000,\n );\n }\n\n /** Refreshes the daemon-side auth token and waits for response. */\n refreshAuthToken(refreshToken: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\n \"auth_refresh\",\n { refresh_token: refreshToken },\n \"auth_refresh\",\n timeout ?? 15_000,\n );\n }\n\n // ---------------------------------------------------------------------------\n // Job IPC methods\n // ---------------------------------------------------------------------------\n\n /** Creates an autopilot job and waits for the response. */\n createJob(\n goal: string,\n verificationRules?: string,\n workspace?: string,\n timeout?: number,\n ): Promise<Record<string, unknown>> {\n const params: Record<string, unknown> = { goal };\n if (verificationRules) params.verification_rules = verificationRules;\n if (workspace) params.workspace = workspace;\n return this.requestResponse(\"job_create\", params, \"job_create\", timeout ?? 15_000);\n }\n\n /** Queries job status and waits for the response. */\n getJobStatus(jobId: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\"job_status\", { job_id: jobId }, \"job_status\", timeout ?? 15_000);\n }\n\n /** Pauses a running job. */\n pauseJob(jobId: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\"job_pause\", { job_id: jobId }, \"job_pause\", timeout ?? 15_000);\n }\n\n /** Resumes a paused job. */\n resumeJob(jobId: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\"job_resume\", { job_id: jobId }, \"job_resume\", timeout ?? 15_000);\n }\n\n /** Cancels a job. */\n cancelJob(jobId: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\"job_cancel\", { job_id: jobId }, \"job_cancel\", timeout ?? 15_000);\n }\n\n /** Requests the DAG visualization for a job. */\n getJobDag(jobId: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\"job_dag\", { job_id: jobId }, \"job_dag\", timeout ?? 15_000);\n }\n\n /** Sends guidance to a job or specific goal. */\n sendJobGuidance(\n jobId: string,\n text: string,\n goalId?: string,\n timeout?: number,\n ): Promise<Record<string, unknown>> {\n const params: Record<string, unknown> = { job_id: jobId, content: text };\n if (goalId) params.goal_id = goalId;\n return this.requestResponse(\"job_guidance\", params, \"job_guidance\", timeout ?? 30_000);\n }\n\n // ---------------------------------------------------------------------------\n // Autopilot goal RPCs (protocol-1 request methods)\n // ---------------------------------------------------------------------------\n\n /** Return autopilot scheduler status (running / dreaming / pool). */\n autopilotStatus(timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\"autopilot_status\", {}, \"autopilot_status\", timeout ?? 15_000);\n }\n\n /** Submit a new autopilot goal (returns goal_id). */\n autopilotSubmit(\n description: string,\n opts?: { priority?: number; workspace?: string; timeout?: number },\n ): Promise<Record<string, unknown>> {\n const params: Record<string, unknown> = {\n description,\n priority: opts?.priority ?? 50,\n };\n if (opts?.workspace) params.workspace = opts.workspace;\n return this.requestResponse(\n \"autopilot_submit\",\n params,\n \"autopilot_submit\",\n opts?.timeout ?? 15_000,\n );\n }\n\n /** List all goals (including non-root children). */\n autopilotListGoals(timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\n \"autopilot_list_goals\",\n {},\n \"autopilot_list_goals\",\n timeout ?? 15_000,\n );\n }\n\n /** Fetch one goal by id. */\n autopilotGetGoal(goalId: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\n \"autopilot_get_goal\",\n { goal_id: goalId },\n \"autopilot_get_goal\",\n timeout ?? 15_000,\n );\n }\n\n /** Cancel a goal and its non-terminal descendants. */\n autopilotCancelGoal(goalId: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\n \"autopilot_cancel_goal\",\n { goal_id: goalId },\n \"autopilot_cancel_goal\",\n timeout ?? 15_000,\n );\n }\n\n /** Cancel every open (non-terminal) goal. */\n autopilotCancelAll(timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\n \"autopilot_cancel_all\",\n {},\n \"autopilot_cancel_all\",\n timeout ?? 15_000,\n );\n }\n\n /** Exit dreaming mode and resume scheduling. */\n autopilotWake(timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\"autopilot_wake\", {}, \"autopilot_wake\", timeout ?? 15_000);\n }\n\n /** Force dreaming mode. */\n autopilotDream(timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\"autopilot_dream\", {}, \"autopilot_dream\", timeout ?? 15_000);\n }\n\n /** Resume a suspended or blocked goal. */\n autopilotResume(goalId: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\n \"autopilot_resume\",\n { goal_id: goalId },\n \"autopilot_resume\",\n timeout ?? 15_000,\n );\n }\n\n /** List root goals only (jobs). Prefer createJob / getJobStatus for job control. */\n autopilotListJobs(timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\n \"autopilot_list_jobs\",\n {},\n \"autopilot_list_jobs\",\n timeout ?? 15_000,\n );\n }\n\n /** Get a root job with DAG snapshot. Prefer getJobStatus / getJobDag. */\n autopilotGetJob(jobId: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\n \"autopilot_get_job\",\n { job_id: jobId },\n \"autopilot_get_job\",\n timeout ?? 15_000,\n );\n }\n\n /** Subscribes to autopilot worker events. */\n autopilotSubscribe(timeout?: number): Promise<string> {\n return this.subscribe(\"autopilot_events\", {}, timeout ?? 15_000);\n }\n\n /** Unsubscribes from autopilot worker events. */\n autopilotUnsubscribe(timeout?: number): Promise<Record<string, unknown>> {\n // Send an unsubscribe envelope (no loop_id in params → daemon infers\n // autopilot_unsubscribe). The daemon sends a `response` correlated by\n // the envelope id; wait for it via requestResponse semantics.\n const req = unsubscribeEnvelope(newRequestID());\n return this._requestResponseForEnvelope(req, \"autopilot_unsubscribe\", timeout ?? 15_000);\n }\n\n // ---------------------------------------------------------------------------\n // Cron IPC methods\n // ---------------------------------------------------------------------------\n\n /** Creates a scheduled job from natural language. */\n cronAdd(text: string, priority?: number, timeout?: number): Promise<Record<string, unknown>> {\n const params: Record<string, unknown> = { text };\n if (priority !== undefined) params.priority = priority;\n return this.requestResponse(\n \"cron_add\",\n params,\n \"cron_add\",\n timeout ?? 30_000, // Longer timeout for NL extraction\n );\n }\n\n /** Lists scheduled jobs. */\n cronList(status?: string, timeout?: number): Promise<Record<string, unknown>> {\n const params: Record<string, unknown> = {};\n if (status !== undefined) params.status = status;\n return this.requestResponse(\"cron_list\", params, \"cron_list\", timeout ?? 15_000);\n }\n\n /** Shows a specific scheduled job. */\n cronShow(jobId: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\"cron_show\", { job_id: jobId }, \"cron_show\", timeout ?? 15_000);\n }\n\n /** Cancels a scheduled job. */\n cronCancel(jobId: string, timeout?: number): Promise<Record<string, unknown>> {\n return this.requestResponse(\"cron_cancel\", { job_id: jobId }, \"cron_cancel\", timeout ?? 15_000);\n }\n\n // ---------------------------------------------------------------------------\n // Wait helpers\n /**\n * Waits for the connection_ack to report readiness (already done in\n * connect(); kept for callers that reconnect manually). Resolves\n * immediately if the handshake is already complete.\n */\n async waitForDaemonReady(timeout?: number): Promise<Record<string, unknown>> {\n if (this.handshakeComplete) {\n return { readiness_state: this.readinessState ?? \"ready\" };\n }\n const t = timeout ?? 10_000;\n const deadline = Date.now() + t;\n while (Date.now() < deadline) {\n const remaining = deadline - Date.now();\n if (remaining <= 0) break;\n const ev = await this.readEventWithTimeout(remaining);\n if (ev === null) break;\n if (ev.type !== \"connection_ack\") continue;\n const result = (ev.result as Record<string, unknown> | undefined) ?? {};\n const state = result.readiness_state as string | undefined;\n if (state === \"ready\") return ev;\n throw new Error(`daemon not ready: state=${state ?? \"unknown\"}`);\n }\n throw new Error(`timeout after ${t}ms waiting for connection_ack`);\n }\n}\n","/**\n * Soothe WebSocket Client - TypeScript\n *\n * A WebSocket client for the Soothe daemon,\n * providing the unified `{proto, type, method, params, id}` envelope, session\n * bootstrap, and convenience RPC helpers.\n */\n\n// Errors\nexport {\n ConnectionError,\n DaemonError,\n TimeoutError,\n ReconnectError,\n StaleLoopError,\n DisconnectCause,\n disconnectCauseName,\n} from \"./errors.js\";\n\n// Verbosity\nexport { VerbosityTier, shouldShow, isValidVerbosityLevel } from \"./verbosity.js\";\nexport type { VerbosityLevel } from \"./verbosity.js\";\n\n// Config\nexport { defaultConfig, loadConfigFromEnv } from \"./config.js\";\nexport type { Config } from \"./config.js\";\n\n// Protocol\nexport {\n PROTO_VERSION,\n DEFAULT_CLIENT_CAPABILITIES,\n CLIENT_VERSION,\n encodeMessage,\n decodeMessage,\n splitWirePayload,\n extractSootheLoopID,\n newRequestID,\n requestEnvelope,\n notificationEnvelope,\n subscribeEnvelope,\n unsubscribeEnvelope,\n connectionInitEnvelope,\n pingEnvelope,\n pongEnvelope,\n disconnectEnvelope,\n newLoopInputMessage,\n newLoopNewMessage,\n newLoopSubscribeMessage,\n} from \"./protocol.js\";\nexport type {\n MessageType,\n MethodName,\n BaseEnvelope,\n RequestEnvelope,\n ResponseEnvelope,\n NotificationEnvelope,\n SubscribeEnvelope,\n NextEnvelope,\n ErrorEnvelope,\n CompleteEnvelope,\n UnsubscribeEnvelope,\n ConnectionInitEnvelope,\n ConnectionAckEnvelope,\n PingEnvelope,\n PongEnvelope,\n ReceiptResponseEnvelope,\n DisconnectEnvelope,\n StatusFrame,\n DecodedMessage,\n LoopInputParams,\n LoopNewOptions,\n StreamEventPayload,\n} from \"./protocol.js\";\nexport type {\n IntentHint,\n LoopAssistantOutputPhase,\n LoopInputIntentHint,\n RemovedIntentHint,\n} from \"./intent_hints.js\";\nexport {\n DEFAULT_DELIVERABLE_PHASES,\n INTENT_HINT_EMBED,\n INTENT_HINT_IMAGE_TO_TEXT,\n INTENT_HINT_OCR,\n INTENT_HINT_TEXT_COMPLETION,\n LOOP_ASSISTANT_OUTPUT_PHASES,\n REMOVED_INTENT_HINTS,\n validateLoopInputIntentHint,\n} from \"./intent_hints.js\";\n\n// Events\nexport {\n EventPlanCreated,\n EventExploreStarted,\n EventExploreMilestone,\n EventExploreStepCompleted,\n EventExploreCompleted,\n EventTacitusStarted,\n EventTacitusGatherSummary,\n EventTacitusCompleted,\n EventReplayComplete,\n EventLoopReattachedWire,\n EventCardReplayBegin,\n EventCardCreated,\n EventCardReplayEnd,\n EventStrangeLoopStarted,\n EventStrangeLoopCompleted,\n EventStrangeLoopPlanDecision,\n EventStrangeLoopReasoned,\n EventStrangeLoopStepStarted,\n EventStrangeLoopStepQueued,\n EventStrangeLoopStepCompleted,\n EventStrangeLoopContextCompacted,\n EventToolStarted,\n EventToolCompleted,\n EventToolError,\n EventStreamToolCallUpdate,\n EventToolCallUpdatesBatch,\n EventMessageReceived,\n EventMessageSent,\n EventFinalReport,\n EventAutopilotGoalStatus,\n EventAutopilotGoalProgress,\n EventAutopilotGoalCreated,\n EventAutopilotGoalCompleted,\n EventAutopilotWorkerAssigned,\n EventAutopilotWorkerUnassigned,\n EventGeneralFailed,\n parseNamespace,\n classifyEventVerbosity,\n isCompletionEvent,\n isSubagentProgressEvent,\n} from \"./events.js\";\n\n// Client\nexport { Client } from \"./client.js\";\nexport type { InputOptions, NegotiatedCapabilities } from \"./client.js\";\n\n// Ephemeral one-shot RPCs (jobs / cron / autopilot)\nexport { CommandClient } from \"./command_client.js\";\n\n// Helpers\nexport {\n checkDaemonStatus,\n isDaemonLive,\n requestDaemonShutdown,\n requestDaemonConfigReload,\n fetchSkillsCatalog,\n fetchConfigSection,\n fetchLoopHistory,\n fetchLoopCards,\n fetchLoopMessages,\n authenticate,\n refreshAuthToken,\n connectedWebsocket,\n protocol1Rpc,\n} from \"./helpers.js\";\n\n// Session\nexport {\n bootstrapLoopSession,\n waitDaemonReady,\n waitLoopStatusWithID,\n waitSubscriptionConfirmed,\n connectWithRetries,\n} from \"./session.js\";\n\n// Stream terminal helpers (used by DaemonSession consumers)\nexport {\n STREAM_END,\n isTurnEndCustomData,\n isTurnProgressChunk,\n inboundNeedsDeliveryAck,\n} from \"./stream_terminal.js\";\n\n// appkit — slim surface matching Python\nexport {\n DaemonSession,\n ConnectionPool,\n TurnRunner,\n QueryGate,\n EventClassifier,\n ChatEventTerminal,\n SSEBroadcaster,\n ErrPoolExhausted,\n ErrQueryBusy,\n ErrIdleTimeout,\n ErrQueryTimeout,\n TimeoutPolicy,\n StreamCloseFail,\n StreamCloseSoftComplete,\n defaultPoolConfig,\n PooledConn,\n compactAttachments,\n compactImageAttachment,\n extractThinkingStep,\n DEFAULT_THINKING_STEP_EVENTS,\n idleTimeoutForTurn,\n inputMessageForLoop,\n TurnEventStats,\n DEFAULT_POST_IDLE_DRAIN_MS,\n} from \"./appkit/index.js\";\nexport type {\n SessionStore,\n SessionEntry,\n SessionMessage,\n SSEEvent,\n ChatEventResult,\n ClassifierConfig,\n PoolConfig,\n TurnConfig,\n InputOpts,\n Attachment,\n OnComplete,\n OnError,\n StreamClosePolicy,\n DaemonSessionOptions,\n TurnChunk,\n CompactImageOptions,\n} from \"./appkit/index.js\";\n","/**\n * Ephemeral one-shot RPC client for jobs / cron / autopilot.\n * Mirrors Python AsyncCommandClient / CommandClient.\n */\n\nimport { Client } from \"./client.js\";\nimport { defaultConfig, type Config } from \"./config.js\";\nimport type { MethodName } from \"./protocol.js\";\nimport { connectWithRetries } from \"./session.js\";\n\nexport class CommandClient {\n readonly url: string;\n readonly timeoutMs: number;\n private readonly config: Config;\n\n constructor(url: string, opts?: { timeoutMs?: number; config?: Config }) {\n this.url = url;\n this.timeoutMs = opts?.timeoutMs && opts.timeoutMs > 0 ? opts.timeoutMs : 30_000;\n this.config = opts?.config ?? defaultConfig();\n }\n\n private async withClient<T>(fn: (client: Client) => Promise<T>): Promise<T> {\n const client = new Client(this.url, this.config);\n try {\n await connectWithRetries(client, 5, 250);\n return await fn(client);\n } finally {\n client.close();\n }\n }\n\n /** Generic one-shot RPC. */\n async request(\n method: MethodName,\n params: Record<string, unknown> = {},\n ): Promise<Record<string, unknown>> {\n return this.withClient(client =>\n client.requestResponse(method, params, undefined, this.timeoutMs),\n );\n }\n\n async jobCreate(goal: string, workspace = \"\"): Promise<Record<string, unknown>> {\n const params: Record<string, unknown> = { goal };\n if (workspace) params.workspace = workspace;\n return this.request(\"job_create\", params);\n }\n\n async jobStatus(jobId: string): Promise<Record<string, unknown>> {\n return this.request(\"job_status\", { job_id: jobId });\n }\n\n async jobCancel(jobId: string): Promise<Record<string, unknown>> {\n return this.request(\"job_cancel\", { job_id: jobId });\n }\n\n /** Return autopilot scheduler status (running / dreaming / pool). */\n async autopilotStatus(): Promise<Record<string, unknown>> {\n return this.request(\"autopilot_status\");\n }\n\n /** Submit a new autopilot goal (returns goal_id). */\n async autopilotSubmit(\n description: string,\n opts?: { priority?: number; workspace?: string },\n ): Promise<Record<string, unknown>> {\n const params: Record<string, unknown> = {\n description,\n priority: opts?.priority ?? 50,\n };\n if (opts?.workspace) params.workspace = opts.workspace;\n return this.request(\"autopilot_submit\", params);\n }\n\n /** List all goals (including non-root children). */\n async autopilotListGoals(): Promise<Record<string, unknown>> {\n return this.request(\"autopilot_list_goals\");\n }\n\n /** Fetch one goal by id. */\n async autopilotGetGoal(goalId: string): Promise<Record<string, unknown>> {\n return this.request(\"autopilot_get_goal\", { goal_id: goalId });\n }\n\n /** Cancel a goal and its non-terminal descendants. */\n async autopilotCancelGoal(goalId: string): Promise<Record<string, unknown>> {\n return this.request(\"autopilot_cancel_goal\", { goal_id: goalId });\n }\n\n /** Cancel every open (non-terminal) goal. */\n async autopilotCancelAll(): Promise<Record<string, unknown>> {\n return this.request(\"autopilot_cancel_all\");\n }\n\n /** Exit dreaming mode and resume scheduling. */\n async autopilotWake(): Promise<Record<string, unknown>> {\n return this.request(\"autopilot_wake\");\n }\n\n /** Force dreaming mode. */\n async autopilotDream(): Promise<Record<string, unknown>> {\n return this.request(\"autopilot_dream\");\n }\n\n /** Resume a suspended or blocked goal. */\n async autopilotResume(goalId: string): Promise<Record<string, unknown>> {\n return this.request(\"autopilot_resume\", { goal_id: goalId });\n }\n\n /** List root goals only (jobs). Prefer job* for job control. */\n async autopilotListJobs(): Promise<Record<string, unknown>> {\n return this.request(\"autopilot_list_jobs\");\n }\n\n /** Get a root job with DAG snapshot. Prefer jobStatus / getJobDag. */\n async autopilotGetJob(jobId: string): Promise<Record<string, unknown>> {\n return this.request(\"autopilot_get_job\", { job_id: jobId });\n }\n\n async cronAdd(text: string, priority = 0): Promise<Record<string, unknown>> {\n const params: Record<string, unknown> = { text };\n if (priority > 0) params.priority = priority;\n return this.request(\"cron_add\", params);\n }\n\n async cronList(status = \"\"): Promise<Record<string, unknown>> {\n const params: Record<string, unknown> = {};\n if (status) params.status = status;\n return this.request(\"cron_list\", params);\n }\n}\n","/**\n * Session bootstrap flows, wait helpers, and connect-with-retries.\n *\n * Under protocol-1 the connection handshake (connection_init /\n * connection_ack) is performed by `client.connect()`. Bootstrap therefore\n * jumps straight to loop_new + subscribe(loop_events).\n */\n\nimport type { Client } from \"./client.js\";\nimport type { Config } from \"./config.js\";\nimport { defaultConfig } from \"./config.js\";\nimport { newLoopNewMessage } from \"./protocol.js\";\nimport { DaemonError } from \"./errors.js\";\n\n// ---------------------------------------------------------------------------\n// Bootstrap flows\n// ---------------------------------------------------------------------------\n\n/**\n * loop_new (or reuse id) → subscribe(loop_events); returns the loop id.\n * The protocol-1 handshake is assumed to have completed in `client.connect()`.\n */\nexport async function bootstrapLoopSession(\n client: Client,\n resumeLoopId: string | null | undefined,\n config?: Config,\n loopNew?: import(\"./protocol.js\").LoopNewOptions,\n): Promise<string> {\n const cfg = config ?? defaultConfig();\n\n let loopId = (resumeLoopId ?? \"\").trim();\n if (!loopId) {\n const env = newLoopNewMessage(loopNew);\n const newResp = await client.requestResponse(\n env.method,\n env.params ?? {},\n \"loop_new\",\n cfg.loopStatusTimeout,\n );\n loopId = String(newResp.loop_id ?? \"\").trim();\n if (!loopId) {\n throw new Error(\"loop_new response missing loop_id\");\n }\n }\n\n // Subscribe to the loop event stream. Confirmation arrives as a `next`\n // frame; client.subscribe() handles the initial ack/error window.\n await client.subscribe(\n \"loop_events\",\n { loop_id: loopId, verbosity: cfg.verbosityLevel },\n cfg.subscriptionTimeout,\n );\n\n return loopId;\n}\n\n// ---------------------------------------------------------------------------\n// Wait helpers (use client's readEventWithTimeout internally)\n// ---------------------------------------------------------------------------\n\n/**\n * Blocks until connection_ack reports readiness \"ready\". Resolves immediately\n * if the handshake already completed during connect().\n */\nexport async function waitDaemonReady(client: Client, timeout: number): Promise<void> {\n if (client.isConnected()) return;\n const deadline = Date.now() + timeout;\n while (Date.now() < deadline) {\n const remaining = deadline - Date.now();\n if (remaining <= 0) break;\n const ev = (await client.readEventWithTimeout(remaining)) as Record<string, unknown> | null;\n if (ev === null) break;\n if (ev.type === \"connection_ack\") {\n const result = (ev.result as Record<string, unknown> | undefined) ?? {};\n const state = result.readiness_state as string | undefined;\n if (state === \"ready\") return;\n throw new Error(`daemon not ready: state=${JSON.stringify(state ?? \"unknown\")}`);\n }\n }\n throw new Error(`timeout after ${timeout}ms waiting for connection_ack (ready)`);\n}\n\n/** Waits for a status message with a non-empty loop_id. */\nexport async function waitLoopStatusWithID(\n client: Client,\n timeout: number,\n): Promise<Record<string, unknown>> {\n const deadline = Date.now() + timeout;\n while (Date.now() < deadline) {\n const remaining = deadline - Date.now();\n if (remaining <= 0) break;\n const ev = (await client.readEventWithTimeout(remaining)) as Record<string, unknown> | null;\n if (ev === null) break;\n\n if (ev.type === \"error\") {\n const errObj = (ev.error as { code?: number; message?: string }) ?? {};\n throw new DaemonError(errObj.code ?? -32603, errObj.message ?? \"daemon error\");\n }\n\n if (ev.type === \"status\") {\n const lid = ev.loop_id as string | undefined;\n if (lid && lid !== \"\") {\n return ev;\n }\n }\n }\n throw new Error(`timeout after ${timeout}ms waiting for status with loop_id`);\n}\n\n/** Waits for a subscription confirmation `next` matching loop id. */\nexport async function waitSubscriptionConfirmed(\n client: Client,\n wantLoopID: string,\n _wantVerbosity: string,\n timeout: number,\n): Promise<void> {\n const deadline = Date.now() + timeout;\n while (Date.now() < deadline) {\n const remaining = deadline - Date.now();\n if (remaining <= 0) break;\n const ev = (await client.readEventWithTimeout(remaining)) as Record<string, unknown> | null;\n if (ev === null) break;\n if (ev.type === \"next\") {\n const payload = (ev.payload as Record<string, unknown> | undefined) ?? {};\n const lid = String(payload.loop_id ?? \"\");\n if (lid === wantLoopID && payload.success === true) return;\n continue;\n }\n if (ev.type === \"error\") {\n const errObj = (ev.error as { message?: string }) ?? {};\n throw new Error(`daemon error: ${errObj.message ?? \"subscription failed\"}`);\n }\n }\n throw new Error(`timeout after ${timeout}ms waiting for subscription confirmation`);\n}\n\n// ---------------------------------------------------------------------------\n// Connect with retries\n// ---------------------------------------------------------------------------\n\n/** Attempts to connect to the Soothe daemon with bounded retries. */\nexport async function connectWithRetries(\n client: Client,\n maxRetries?: number,\n retryDelay?: number,\n): Promise<void> {\n const retries = maxRetries && maxRetries > 0 ? maxRetries : 40;\n const delay = retryDelay && retryDelay > 0 ? retryDelay : 250;\n\n let lastErr: Error | null = null;\n for (let attempt = 0; attempt < retries; attempt++) {\n try {\n await client.connect();\n return;\n } catch (err) {\n lastErr = err as Error;\n }\n await new Promise(resolve => setTimeout(resolve, delay));\n }\n throw new Error(\n `failed to connect after ${retries} attempts: ${lastErr?.message ?? \"unknown error\"}`,\n );\n}\n","/**\n * Convenience RPC helper functions for the Soothe client.\n */\n\nimport type { Client } from \"./client.js\";\nimport { defaultConfig } from \"./config.js\";\n\n/** Checks daemon status via RPC. */\nexport async function checkDaemonStatus(\n client: Client,\n timeout?: number,\n): Promise<Record<string, unknown>> {\n return client.requestResponse(\"daemon_status\", {}, \"daemon_status\", timeout ?? 5_000);\n}\n\n/** Performs a composite health check: connect + handshake + status RPC. */\nexport async function isDaemonLive(wsURL: string, timeout?: number): Promise<boolean> {\n const { Client } = await import(\"./client.js\");\n const t = timeout ?? 5_000;\n const client = new Client(wsURL, defaultConfig());\n\n try {\n await client.connect();\n } catch {\n return false;\n }\n\n try {\n await checkDaemonStatus(client, t);\n return true;\n } catch {\n return false;\n } finally {\n client.close();\n }\n}\n\n/** Requests daemon shutdown via RPC. */\nexport async function requestDaemonShutdown(client: Client, timeout?: number): Promise<void> {\n const resp = await client.requestResponse(\n \"daemon_shutdown\",\n {},\n \"daemon_shutdown\",\n timeout ?? 10_000,\n );\n if (resp.status !== \"acknowledged\") {\n throw new Error(`shutdown not acknowledged: ${JSON.stringify(resp)}`);\n }\n}\n\n/** Fetches the skills catalog via RPC. */\nexport async function fetchSkillsCatalog(\n client: Client,\n timeout?: number,\n): Promise<Record<string, unknown>[]> {\n const resp = await client.requestResponse(\"skills_list\", {}, \"skills_list\", timeout ?? 15_000);\n const skillsRaw = resp.skills;\n if (!skillsRaw || !Array.isArray(skillsRaw)) return [];\n return skillsRaw.filter((s): s is Record<string, unknown> => typeof s === \"object\" && s !== null);\n}\n\n/** Fetches a daemon config section via RPC. */\nexport async function fetchConfigSection(\n client: Client,\n section: string,\n timeout?: number,\n): Promise<Record<string, unknown>> {\n const resp = await client.requestResponse(\n \"config_get\",\n { section },\n \"config_get\",\n timeout ?? 5_000,\n );\n const sec = resp[section];\n if (sec && typeof sec === \"object\") {\n return sec as Record<string, unknown>;\n }\n return resp;\n}\n\n/** Requests daemon config reload via RPC. */\nexport async function requestDaemonConfigReload(\n client: Client,\n timeout?: number,\n): Promise<Record<string, unknown>> {\n return client.requestResponse(\"config_reload\", {}, \"config_reload\", timeout ?? 15_000);\n}\n\n/** Requests loop history and waits for the response. */\nexport async function fetchLoopHistory(\n client: Client,\n loopID: string,\n timeout?: number,\n): Promise<Record<string, unknown>> {\n return client.requestResponse(\n \"loop_history_fetch\",\n { loop_id: loopID },\n \"loop_history_fetch\",\n timeout ?? 15_000,\n );\n}\n\n/** Submits credentials for daemon-side authentication and waits for the response. */\nexport async function authenticate(\n client: Client,\n accessKey: string,\n secretKey: string,\n timeout?: number,\n): Promise<Record<string, unknown>> {\n return client.requestResponse(\n \"auth\",\n { access_key: accessKey, secret_key: secretKey },\n \"auth\",\n timeout ?? 15_000,\n );\n}\n\n/** Refreshes the daemon-side auth token and waits for the response. */\nexport async function refreshAuthToken(\n client: Client,\n refreshToken: string,\n timeout?: number,\n): Promise<Record<string, unknown>> {\n return client.requestResponse(\n \"auth_refresh\",\n { refresh_token: refreshToken },\n \"auth_refresh\",\n timeout ?? 15_000,\n );\n}\n\n/** Fetch bound display-card snapshot for a loop. */\nexport async function fetchLoopCards(\n client: Client,\n loopID: string,\n timeout?: number,\n): Promise<Record<string, unknown>> {\n return client.fetchLoopCards(loopID, timeout);\n}\n\n/** Fetch persisted conversation/activity rows for a loop. */\nexport async function fetchLoopMessages(\n client: Client,\n loopID: string,\n opts?: { limit?: number; offset?: number; includeEvents?: boolean; timeout?: number },\n): Promise<Record<string, unknown>> {\n return client.getLoopMessages(\n loopID,\n opts?.limit,\n opts?.offset,\n opts?.includeEvents,\n opts?.timeout,\n );\n}\n\n/**\n * Connect, handshake, and yield a ready Client. Always closes in finally.\n */\nexport async function connectedWebsocket<T>(\n wsUrl: string,\n fn: (client: Client) => Promise<T>,\n timeoutMs = 30_000,\n): Promise<T> {\n const { Client } = await import(\"./client.js\");\n const client = new Client(wsUrl, defaultConfig());\n const deadline = Date.now() + timeoutMs;\n try {\n await client.connect();\n while (!client.isConnected() && Date.now() < deadline) {\n await new Promise(r => setTimeout(r, 25));\n }\n if (!client.isConnected()) {\n throw new Error(\"Timed out waiting for daemon handshake\");\n }\n return await fn(client);\n } finally {\n client.close();\n }\n}\n\n/**\n * One-shot protocol-1 RPC / notify / subscribe with dict-style error contract.\n * Callers check `if (\"error\" in response)`.\n */\nexport async function protocol1Rpc(\n wsUrl: string,\n method: string,\n params: Record<string, unknown> | null = null,\n opts: { mode?: \"request\" | \"notify\" | \"subscribe\"; timeoutMs?: number } = {},\n): Promise<Record<string, unknown>> {\n const mode = opts.mode ?? \"request\";\n const timeoutMs = opts.timeoutMs ?? 30_000;\n try {\n return await connectedWebsocket(\n wsUrl,\n async client => {\n if (mode === \"notify\") {\n await client.notify(method as import(\"./protocol.js\").MethodName, params ?? {});\n return {};\n }\n if (mode === \"subscribe\") {\n const subId = await client.subscribe(\n method as \"loop_events\" | \"autopilot_events\",\n params ?? {},\n timeoutMs,\n );\n return { subscription_id: subId };\n }\n const result = await client.requestResponse(\n method as import(\"./protocol.js\").MethodName,\n params ?? {},\n method,\n timeoutMs,\n );\n return result && typeof result === \"object\" ? result : { result };\n },\n timeoutMs,\n );\n } catch (exc) {\n const msg = exc instanceof Error ? exc.message : String(exc);\n if (msg.toLowerCase().includes(\"timed out\") || msg.toLowerCase().includes(\"timeout\")) {\n return { error: \"Timed out waiting for daemon response\" };\n }\n if (msg.toLowerCase().includes(\"connect\") || msg.toLowerCase().includes(\"dial\")) {\n return { error: `Connection error: ${msg}` };\n }\n return { error: msg };\n }\n}\n","/**\n * SSE-style pub/sub fan-out for appkit.\n *\n * Generic, string-keyed pub/sub for SSE-style event delivery. The\n * application-agnostic successor to a domain-keyed broadcaster: applications\n * convert from their domain key type to `string` at their own boundary.\n *\n * Slow consumers do not stall the broadcaster: each subscriber has a bounded\n * queue and overflowing events are dropped (drop-on-full).\n */\n\n/** One Server-Sent Event payload. The Type vocabulary is app-defined. */\nexport interface SSEEvent {\n type: string;\n data: unknown;\n}\n\n/** Per-subscriber bounded queue. Events past the cap are dropped. */\nconst SUBSCRIBER_QUEUE_CAP = 100;\n\ninterface Subscriber {\n queue: SSEEvent[];\n /** Resolvers waiting for the next event. */\n waiters: Array<(ev: SSEEvent | null) => void>;\n closed: boolean;\n}\n\n/**\n * SSEBroadcaster fans events out to all subscribers for a session id.\n * Non-blocking: a full subscriber queue drops the event so one slow consumer\n * cannot block the others.\n */\nexport class SSEBroadcaster {\n private subscribers = new Map<string, Map<string, Subscriber>>();\n private nextSubID = 0;\n\n /** Creates an empty broadcaster. */\n constructor() {}\n\n /**\n * Registers a new subscriber channel for a session id. Returns an async\n * iterable the subscriber reads events from. Unsubscribe via\n * `unsubscribe()` or `close()`.\n */\n subscribe(sessionID: string): { iterable: AsyncIterable<SSEEvent>; id: string } {\n const subID = String(this.nextSubID++);\n const sub: Subscriber = { queue: [], waiters: [], closed: false };\n let subs = this.subscribers.get(sessionID);\n if (!subs) {\n subs = new Map();\n this.subscribers.set(sessionID, subs);\n }\n subs.set(subID, sub);\n\n const iterable: AsyncIterable<SSEEvent> = {\n [Symbol.asyncIterator]() {\n return {\n next(): Promise<IteratorResult<SSEEvent>> {\n if (sub.queue.length > 0) {\n return Promise.resolve({ value: sub.queue.shift()!, done: false });\n }\n if (sub.closed) {\n return Promise.resolve({ value: undefined as unknown as SSEEvent, done: true });\n }\n return new Promise<IteratorResult<SSEEvent>>(resolve => {\n sub.waiters.push(ev => {\n if (ev === null) {\n resolve({ value: undefined as unknown as SSEEvent, done: true });\n } else {\n resolve({ value: ev, done: false });\n }\n });\n });\n },\n };\n },\n };\n return { iterable, id: subID };\n }\n\n /** Removes a subscriber by id and closes its iterable. Safe if unknown. */\n unsubscribe(sessionID: string, subID: string): void {\n const subs = this.subscribers.get(sessionID);\n if (!subs) return;\n const sub = subs.get(subID);\n if (!sub) return;\n sub.closed = true;\n for (const w of sub.waiters) w(null);\n sub.waiters = [];\n subs.delete(subID);\n if (subs.size === 0) this.subscribers.delete(sessionID);\n }\n\n /**\n * Sends an event to all subscribers for a session id. Non-blocking: a full\n * subscriber queue is skipped (drop-on-full) so one slow consumer cannot\n * block the others.\n */\n broadcast(sessionID: string, event: SSEEvent): void {\n const subs = this.subscribers.get(sessionID);\n if (!subs) return;\n for (const sub of subs.values()) {\n if (sub.closed) continue;\n if (sub.waiters.length > 0) {\n const w = sub.waiters.shift()!;\n w(event);\n } else if (sub.queue.length < SUBSCRIBER_QUEUE_CAP) {\n sub.queue.push(event);\n }\n // else: drop-on-full.\n }\n }\n\n /** Closes all subscribers for a session id and removes the entry. */\n close(sessionID: string): void {\n const subs = this.subscribers.get(sessionID);\n if (!subs) return;\n for (const sub of subs.values()) {\n sub.closed = true;\n for (const w of sub.waiters) w(null);\n sub.waiters = [];\n }\n this.subscribers.delete(sessionID);\n }\n\n /** Closes every subscriber channel across all sessions. */\n closeAll(): void {\n for (const [sessionID, subs] of this.subscribers) {\n for (const sub of subs.values()) {\n sub.closed = true;\n for (const w of sub.waiters) w(null);\n sub.waiters = [];\n }\n this.subscribers.delete(sessionID);\n }\n }\n}\n","/**\n * Event classifier for appkit.\n *\n * Maps a stream of decoded daemon events into deliverable/streaming/terminal\n * outcomes, keyed on (namespace, mode, phase). The app-agnostic successor to\n * product-specific ProcessChatEvent helpers, with the deliverable phase set\n * promoted from hardcoded constants to configuration.\n *\n * Event shape: a protocol-1 `next` envelope carries\n * `{type:\"next\", payload:{namespace, mode, data, loop_id}}`. The daemon\n * wraps legacy free-form frames as `{payload:{namespace, mode:<orig type>,\n * data:<orig frame>}}`. The classifier inspects the payload's\n * `mode`/`data`/`namespace` and the inner message's `phase`/`type`/`content`.\n */\n\nimport { DaemonError } from \"../errors.js\";\nimport { EventFinalReport } from \"../events.js\";\nimport { DEFAULT_THINKING_STEP_EVENTS, extractThinkingStep } from \"./thinking_step.js\";\n\n/** How a processed event should end the query loop. */\nexport enum ChatEventTerminal {\n /** Accumulate content; the query is still running. */\n Continue = 0,\n /** A user-visible final reply; persist it. */\n DeliverableComplete = 1,\n /** The query failed; persist an error. */\n FailedComplete = 2,\n}\n\n/** The structured outcome of classifying one daemon event. */\nexport interface ChatEventResult {\n content?: string;\n /** User-visible progress line (not a final reply). */\n thinkingStep?: string;\n terminal: ChatEventTerminal;\n /** soothe wire event type when terminal === DeliverableComplete. */\n completionEvent?: string;\n err?: Error;\n}\n\n/**\n * Product-specific decisions an EventClassifier needs. The DeliverablePhases\n * set is the key product knob: which message `phase` values count as\n * user-facing deliverables (triarch uses quiz, goal_completion, direct_model, and\n * direct intent_hint phases text_completion, image_to_text, ocr, embed;\n * other apps pass their own).\n */\nexport interface ClassifierConfig {\n /** Recognizes loop-tagged message phases that may end a query with\n * user-facing text. Required. */\n deliverablePhases: ReadonlySet<string>;\n /** Minimum trimmed rune count for a reply to be persisted as final\n * (avoids finishing on stub ACKs like \"...\"). Defaults to 8. */\n minDeliverableRunes?: number;\n /** Optional app override of the default thinking-step event allowlist. */\n thinkingStepEvents?: ReadonlySet<string>;\n /**\n * When true, a status frame with state=idle and non-empty accumulated\n * assistant text is DeliverableComplete (typical for direct-model turns).\n * Default false keeps Continue-on-status behaviour.\n */\n treatStatusIdleAsComplete?: boolean;\n}\n\n/** Event type of the daemon's replay completion signal (internal). */\nconst EVENT_LOOP_HISTORY_REPLAYED = \"soothe.lifecycle.loop.history.replayed\";\n\n/** Maps a stream of decoded daemon events into deliverable/streaming/terminal outcomes. */\nexport class EventClassifier {\n private deliverablePhases: ReadonlySet<string>;\n private minDeliverableRunes: number;\n private thinkingStepEvents?: ReadonlySet<string>;\n private treatStatusIdleAsComplete: boolean;\n\n constructor(cfg: ClassifierConfig) {\n if (!cfg.deliverablePhases) {\n throw new Error(\"appkit: ClassifierConfig.deliverablePhases must not be nil\");\n }\n this.deliverablePhases = cfg.deliverablePhases;\n this.minDeliverableRunes =\n cfg.minDeliverableRunes && cfg.minDeliverableRunes > 0 ? cfg.minDeliverableRunes : 8;\n this.thinkingStepEvents = cfg.thinkingStepEvents;\n this.treatStatusIdleAsComplete = Boolean(cfg.treatStatusIdleAsComplete);\n }\n\n /**\n * Inspects one decoded event and returns its outcome. `accumulated` is the\n * running assistant text so far, used to pick the final reply when a\n * deliverable event arrives.\n */\n classify(msg: unknown, accumulated: string): ChatEventResult {\n return this.processChatEvent(msg, accumulated);\n }\n\n /**\n * Reports whether a persisted completion_event is user-facing. Uses the\n * configured deliverable phase set; recognizes the protocol output namespace\n * and final_report component as deliverable.\n */\n isDeliverableCompletionEvent(eventType: string): boolean {\n if (!eventType) return false;\n switch (eventType) {\n case \"status.idle\":\n case \"idle_timeout\":\n case \"query_timeout\":\n case \"stream_closed\":\n return true;\n }\n if (eventType === EventFinalReport) return true;\n if (eventType.startsWith(\"soothe.protocol.message.\")) {\n const phase = eventType.slice(\"soothe.protocol.message.\".length);\n return this.isDeliverableLoopPhase(phase);\n }\n return eventType.includes(\"soothe.output\") && eventType.includes(\"responded\");\n }\n\n isDeliverableLoopPhase(phase: string): boolean {\n return this.deliverablePhases.has(phase);\n }\n\n private deliverableResult(content: string, completionEvent: string): ChatEventResult {\n return { content, terminal: ChatEventTerminal.DeliverableComplete, completionEvent };\n }\n\n private continueResult(content: string): ChatEventResult {\n return { content, terminal: ChatEventTerminal.Continue };\n }\n\n private failedResult(err: Error): ChatEventResult {\n return { terminal: ChatEventTerminal.FailedComplete, err };\n }\n\n /** Reports whether trimmed assistant text is long enough to persist as final. */\n isSubstantiveAssistantReply(content: string): boolean {\n return [...content.trim()].length >= this.minDeliverableRunes;\n }\n\n /**\n * Picks the user-visible reply for a completed query. Only a deliverable\n * terminal result with a recognized completion event yields a final reply.\n */\n resolveDeliverableFinalContent(\n eventResult: ChatEventResult,\n _accumulated: string,\n ): [string, boolean] {\n if (eventResult.terminal !== ChatEventTerminal.DeliverableComplete) return [\"\", false];\n if (!this.isDeliverableCompletionEvent(eventResult.completionEvent ?? \"\")) return [\"\", false];\n const final = (eventResult.content ?? \"\").trim();\n if (final) return [final, true];\n return [\"\", false];\n }\n\n /** The event→outcome mapper, ported from triarch's ProcessChatEvent. */\n private processChatEvent(msg: unknown, accumulated: string): ChatEventResult {\n if (!msg || typeof msg !== \"object\") {\n return { terminal: ChatEventTerminal.Continue };\n }\n const m = msg as Record<string, unknown>;\n const typ = m.type as string | undefined;\n\n // Protocol-1 `next` envelope: the daemon wraps legacy frames in payload.\n if (typ === \"next\") {\n return this.classifyNextEnvelope(m, accumulated);\n }\n\n // Protocol-1 RPC responses / subscription confirmations arrive as\n // response/next/complete envelopes. An `error` envelope is a daemon\n // failure; everything else is a protocol-level ack (not a deliverable).\n if (\n typ === \"response\" ||\n typ === \"complete\" ||\n typ === \"receipt_response\" ||\n typ === \"connection_ack\"\n ) {\n return { terminal: ChatEventTerminal.Continue };\n }\n if (typ === \"status\") {\n if (\n this.treatStatusIdleAsComplete &&\n String(m.state ?? \"\")\n .trim()\n .toLowerCase() === \"idle\" &&\n this.isSubstantiveAssistantReply(accumulated)\n ) {\n return this.deliverableResult(accumulated.trim(), \"status.idle\");\n }\n return { terminal: ChatEventTerminal.Continue };\n }\n if (typ === \"error\") {\n const errObj = (m.error as { code?: number; message?: string; data?: unknown }) ?? {};\n const code = typeof errObj.code === \"number\" ? errObj.code : -32603;\n return this.failedResult(\n new DaemonError(code, errObj.message ?? \"daemon error\", errObj.data),\n );\n }\n\n // Legacy flat-form `event` frame (mode/data at top level).\n if (typ === \"event\") {\n return this.classifyEventPayload(\n (m.namespace as unknown) ?? null,\n (m.mode as string) ?? \"\",\n m.data,\n );\n }\n\n return { terminal: ChatEventTerminal.Continue };\n }\n\n /** Classifies a `next` envelope by projecting its payload. */\n private classifyNextEnvelope(env: Record<string, unknown>, accumulated: string): ChatEventResult {\n const payload = (env.payload as Record<string, unknown> | undefined) ?? {};\n // The inner event frame lives in payload.data, with its own mode/data.\n const innerData = payload.data as Record<string, unknown> | undefined;\n if (innerData && typeof innerData === \"object\") {\n const innerType = (innerData.type as string) ?? \"\";\n if (innerType === \"status\") {\n return this.processChatEvent(innerData, accumulated);\n }\n const innerMode = (innerData.mode as string) ?? \"\";\n if (innerMode) {\n return this.classifyEventPayload(\n (innerData.namespace as unknown) ?? payload.namespace ?? null,\n innerMode,\n innerData.data,\n );\n }\n }\n // Fallback: payload itself carries mode/data directly.\n const mode = (payload.mode as string) ?? \"\";\n if (mode === \"status\" || mode === \"\") {\n if (typeof payload.state === \"string\" || (innerData && \"state\" in (innerData ?? {}))) {\n return this.processChatEvent({ type: \"status\", ...(innerData ?? payload) }, accumulated);\n }\n }\n if (mode) {\n return this.classifyEventPayload((payload.namespace as unknown) ?? null, mode, payload.data);\n }\n return { terminal: ChatEventTerminal.Continue };\n }\n\n /**\n * Classifies an event payload by (namespace, mode, phase). `data` may be a\n * map or an array of messages (mode=\"messages\").\n */\n private classifyEventPayload(namespace: unknown, mode: string, data: unknown): ChatEventResult {\n // Normalize namespace to a string for matching.\n const ns = namespaceToString(namespace);\n\n // Normalize data to a map for thinking-step / output extraction.\n const dataMap = normalizeEventData(data);\n\n if (dataMap) {\n let dataType = ns;\n const dt = dataMap[\"type\"];\n if (typeof dt === \"string\" && dt) dataType = dt;\n if (dataType === EVENT_LOOP_HISTORY_REPLAYED) {\n return { terminal: ChatEventTerminal.Continue };\n }\n const [step, ok] = extractThinkingStep(dataType, dataMap, this.thinkingStepEvents);\n if (ok) {\n return { thinkingStep: step, terminal: ChatEventTerminal.Continue };\n }\n }\n\n // mode=\"messages\": assistant content (streaming chunks or deliverable).\n if (mode === \"messages\") {\n const result = this.classifyMessagesMode(data, ns);\n if (result) return result;\n }\n\n if (!dataMap) {\n return { terminal: ChatEventTerminal.Continue };\n }\n\n let dataType = ns;\n const dt = dataMap[\"type\"];\n if (typeof dt === \"string\" && dt) dataType = dt;\n let completionEvent = dataType;\n if (!completionEvent) completionEvent = ns;\n\n // soothe.output / responded namespaces.\n if (\n isNamespaceMatch(ns, dataType, \"soothe.output\") ||\n isNamespaceMatch(ns, dataType, \"responded\")\n ) {\n const [content, ok] = extractContentFromData(dataMap);\n if (ok) {\n if (this.isFinalOutputEvent(dataType, ns)) {\n return this.deliverableResult(content, completionEvent);\n }\n return this.continueResult(content);\n }\n }\n\n if (\n isNamespaceMatch(ns, dataType, \"agent_loop.completed\") ||\n isNamespaceMatch(ns, dataType, \"agent_loop.reasoned\") ||\n isNamespaceMatch(ns, dataType, \"loop.completed\")\n ) {\n const [content, ok] = extractContentFromData(dataMap);\n if (ok) return this.continueResult(content);\n }\n\n if (isNamespaceMatch(ns, dataType, \"final_report\")) {\n const [content, ok] = extractContentFromData(dataMap);\n if (ok) return this.deliverableResult(content, completionEvent);\n }\n\n if (dataType.includes(\"soothe.error.\") || ns.includes(\"soothe.error.\")) {\n const errType = dataType || ns;\n const msg = dataMap[\"message\"];\n if (typeof msg === \"string\" && msg) {\n return this.failedResult(new Error(`${errType}: ${msg}`));\n }\n const [content, ok] = extractContentFromData(dataMap);\n if (ok) return this.failedResult(new Error(`${errType}: ${content}`));\n return this.failedResult(new Error(errType));\n }\n\n if (\n isNamespaceMatch(ns, dataType, \"stream\") ||\n isNamespaceMatch(ns, dataType, \"progress\") ||\n isNamespaceMatch(ns, dataType, \"tool_call_updates_batch\") ||\n isNamespaceMatch(ns, dataType, \"soothe.stream.tool_call.update\")\n ) {\n const delta = dataMap[\"delta\"];\n if (typeof delta === \"string\") return this.continueResult(delta);\n }\n\n if (\n isNamespaceMatch(ns, dataType, \"heartbeat\") ||\n isNamespaceMatch(ns, dataType, \"system.daemon\") ||\n isNamespaceMatch(ns, dataType, \"agent_loop.started\") ||\n isNamespaceMatch(ns, dataType, \"intent.classified\")\n ) {\n return { terminal: ChatEventTerminal.Continue };\n }\n\n return { terminal: ChatEventTerminal.Continue };\n }\n\n /** Classifies a mode=\"messages\" payload (array of message objects). */\n private classifyMessagesMode(data: unknown, _ns: string): ChatEventResult | null {\n const items = Array.isArray(data) ? data : null;\n if (!items || items.length === 0) return null;\n const first = items[0];\n if (!first || typeof first !== \"object\") return null;\n\n const [msgType, rawContent, phase, hasPayload] = firstMessagePayload(data);\n if (hasPayload && rawContent && isStreamingMessageType(msgType)) {\n return this.continueResult(rawContent);\n }\n\n // Loop-tagged assistant message.\n const loopMsg = loopAIMessage(data);\n if (loopMsg) {\n const content = loopMsg.content;\n if (content) {\n if (isStreamingMessageType(loopMsg.type)) {\n return this.continueResult(content);\n }\n if (\n this.isDeliverableLoopPhase(loopMsg.phase) &&\n this.isSubstantiveAssistantReply(content)\n ) {\n return this.deliverableResult(content, \"soothe.protocol.message.\" + loopMsg.phase);\n }\n return this.continueResult(content);\n }\n }\n\n // Direct-LLM assistant content (mode=messages, terminal AIMessage, no phase).\n const [directContent, directOk] = this.messagesModeAssistantContent(data);\n if (directOk && this.isSubstantiveAssistantReply(directContent)) {\n return this.deliverableResult(directContent, \"soothe.protocol.message.direct_model\");\n }\n\n if (hasPayload && rawContent) {\n if (isTerminalMessageType(msgType) || msgType === \"\") {\n if (this.isDeliverableLoopPhase(phase) && this.isSubstantiveAssistantReply(rawContent)) {\n return this.deliverableResult(rawContent, \"soothe.protocol.message.\" + phase);\n }\n return this.continueResult(rawContent);\n }\n return this.continueResult(rawContent);\n }\n return null;\n }\n\n /**\n * Extracts plain assistant text from mode=\"messages\" events that carry a\n * terminal AIMessage without loop-tagged phase metadata (legacy direct_llm turns\n * before phase tagging; prefer deliverablePhases including text_completion).\n */\n private messagesModeAssistantContent(data: unknown): [string, boolean] {\n if (!Array.isArray(data) || data.length === 0) return [\"\", false];\n const msgMap = data[0] as Record<string, unknown>;\n if (!msgMap || typeof msgMap !== \"object\") return [\"\", false];\n const phase = typeof msgMap.phase === \"string\" ? msgMap.phase.trim() : \"\";\n if (phase) return [\"\", false];\n const msgType = typeof msgMap.type === \"string\" ? msgMap.type : \"\";\n if (msgType && !isTerminalMessageType(msgType)) return [\"\", false];\n const content = extractContentFromMessage(msgMap).trim();\n if (!content) return [\"\", false];\n return [content, true];\n }\n\n /** soothe output/responded events that carry user-facing final text. */\n private isFinalOutputEvent(dataType: string, ns: string): boolean {\n const combined = dataType + \" \" + ns;\n if (combined.includes(\"final_report\")) return true;\n for (const phase of this.deliverablePhases) {\n if (combined.includes(phase)) return true;\n }\n return false;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Helpers (module-private)\n// ---------------------------------------------------------------------------\n\nfunction isStreamingMessageType(msgType: string): boolean {\n return msgType === \"AIMessageChunk\" || msgType === \"ai_chunk\" || msgType === \"message_chunk\";\n}\n\nfunction isTerminalMessageType(msgType: string): boolean {\n return msgType === \"AIMessage\" || msgType === \"ai\" || msgType === \"assistant\";\n}\n\n/** Extracts the first message's (type, content, phase, hasPayload). */\nfunction firstMessagePayload(data: unknown): [string, string, string, boolean] {\n if (!Array.isArray(data) || data.length === 0) return [\"\", \"\", \"\", false];\n const msgMap = data[0] as Record<string, unknown>;\n if (!msgMap || typeof msgMap !== \"object\") return [\"\", \"\", \"\", false];\n const msgType = typeof msgMap.type === \"string\" ? msgMap.type : \"\";\n const phase = typeof msgMap.phase === \"string\" ? msgMap.phase : \"\";\n const content = extractContentFromMessage(msgMap);\n return [msgType, content, phase, true];\n}\n\n/** Extracts a loop-tagged assistant message (type, content, phase). */\nfunction loopAIMessage(data: unknown): { type: string; content: string; phase: string } | null {\n if (!Array.isArray(data) || data.length === 0) return null;\n const msgMap = data[0] as Record<string, unknown>;\n if (!msgMap || typeof msgMap !== \"object\") return null;\n const phase = typeof msgMap.phase === \"string\" ? msgMap.phase.trim() : \"\";\n if (!phase) return null;\n const type = typeof msgMap.type === \"string\" ? msgMap.type : \"\";\n const content = extractContentFromMessage(msgMap);\n return { type, content, phase };\n}\n\nfunction extractContentFromMessage(msgMap: Record<string, unknown>): string {\n const c = msgMap.content;\n if (typeof c === \"string\" && c) return c;\n if (Array.isArray(c) && c.length > 0) {\n let b = \"\";\n for (const item of c) {\n if (typeof item === \"string\") {\n b += item;\n continue;\n }\n if (item && typeof item === \"object\") {\n const blk = item as Record<string, unknown>;\n const t = blk.text;\n if (typeof t === \"string\") b += t;\n }\n }\n return b;\n }\n const blocks = msgMap.content_blocks;\n if (Array.isArray(blocks) && blocks.length > 0) {\n let b = \"\";\n for (const blk of blocks) {\n if (blk && typeof blk === \"object\") {\n const m = blk as Record<string, unknown>;\n const t = m.text;\n if (typeof t === \"string\") b += t;\n }\n }\n return b;\n }\n return \"\";\n}\n\nfunction extractContentFromData(data: Record<string, unknown>): [string, boolean] {\n for (const key of [\n \"final_stdout_message\",\n \"completion_summary\",\n \"content\",\n \"text\",\n \"response\",\n \"output\",\n \"message\",\n \"report\",\n ]) {\n const val = data[key];\n if (typeof val === \"string\" && val) return [val, true];\n }\n const nested = data.data;\n if (nested && typeof nested === \"object\") {\n const nm = nested as Record<string, unknown>;\n for (const key of [\n \"final_stdout_message\",\n \"completion_summary\",\n \"content\",\n \"text\",\n \"response\",\n \"output\",\n \"message\",\n \"report\",\n ]) {\n const val = nm[key];\n if (typeof val === \"string\" && val) return [val, true];\n }\n }\n return [\"\", false];\n}\n\nfunction isNamespaceMatch(ns: string, dataType: string, pattern: string): boolean {\n return dataType.includes(pattern) || ns.includes(pattern);\n}\n\n/** Normalizes a namespace value (string or string[]) to a dotted string. */\nfunction namespaceToString(namespace: unknown): string {\n if (typeof namespace === \"string\") return namespace;\n if (Array.isArray(namespace)) return namespace.filter(s => typeof s === \"string\").join(\".\");\n return \"\";\n}\n\n/** Normalizes event data to a map. Strings are parsed as JSON. */\nfunction normalizeEventData(data: unknown): Record<string, unknown> | null {\n if (data == null) return null;\n if (typeof data === \"object\" && !Array.isArray(data)) {\n return data as Record<string, unknown>;\n }\n if (typeof data === \"string\") {\n try {\n const m = JSON.parse(data);\n if (m && typeof m === \"object\" && !Array.isArray(m)) return m;\n } catch {\n return null;\n }\n }\n return null;\n}\n\n// Re-export for callers that want the default allowlist.\nexport { DEFAULT_THINKING_STEP_EVENTS };\n","/**\n * Thinking-step extraction for appkit.\n *\n * Maps an allowlisted progress event to one structured UI line. Free-form\n * streams (tokens, reports, reasoning) are excluded. Ported from the Go\n * appkit's thinking_step with the allowlist made configurable.\n */\n\nconst MAX_THINKING_STEP_RUNES = 280;\n\n/** Default thinking-step event allowlist (triarch's set). */\nexport const DEFAULT_THINKING_STEP_EVENTS: ReadonlySet<string> = new Set([\n \"soothe.cognition.plan.step.started\",\n \"soothe.cognition.plan.step.completed\",\n \"soothe.cognition.plan.step.failed\",\n \"soothe.lifecycle.iteration.started\",\n \"soothe.agent.loop.step.started\",\n \"soothe.agent.loop.started\",\n \"soothe.cognition.plan.batch.started\",\n \"soothe.cognition.plan.created\",\n \"soothe.cognition.goal.created\",\n \"soothe.tool.execution.started\",\n]);\n\n/**\n * Maps an allowlisted progress event to one structured UI line. Returns\n * [line, true] for a recognized event; [\"\", false] otherwise. `allow` may be\n * omitted to use the default allowlist.\n */\nexport function extractThinkingStep(\n eventType: string,\n data: Record<string, unknown> | null,\n allow?: ReadonlySet<string>,\n): [string, boolean] {\n if (!eventType || !data) return [\"\", false];\n const et = eventType.trim();\n if (!et) return [\"\", false];\n\n const allowlist = allow ?? DEFAULT_THINKING_STEP_EVENTS;\n if (!allowlist.has(et)) return [\"\", false];\n\n let line = \"\";\n switch (et) {\n case \"soothe.cognition.plan.step.started\":\n line = formatPlanStepLine(data, \"\");\n break;\n case \"soothe.cognition.plan.step.completed\":\n line = formatPlanStepLine(data, \"done\");\n break;\n case \"soothe.cognition.plan.step.failed\": {\n const stepID = strField(data, \"step_id\");\n const errMsg = strField(data, \"error\");\n if (stepID && errMsg) line = `Step ${stepID} failed: ${errMsg}`;\n else if (stepID) line = `Step ${stepID} failed`;\n else if (errMsg) line = `Step failed: ${errMsg}`;\n break;\n }\n case \"soothe.agent.loop.step.started\":\n line = formatAgentStepLine(data, \"\");\n break;\n case \"soothe.cognition.plan.batch.started\": {\n const n = data[\"parallel_count\"];\n if (typeof n === \"number\" && n > 0) line = `Running ${Math.floor(n)} steps in parallel`;\n break;\n }\n case \"soothe.cognition.plan.created\":\n case \"soothe.agent.loop.started\": {\n const g = strField(data, \"goal\");\n if (g) line = \"Goal: \" + g;\n break;\n }\n case \"soothe.cognition.goal.created\": {\n const g = strField(data, \"friendly_message\", \"description\");\n if (g) line = \"Goal: \" + g;\n break;\n }\n case \"soothe.lifecycle.iteration.started\": {\n const g = strField(data, \"goal_description\");\n if (g) line = \"Iteration: \" + g;\n break;\n }\n case \"soothe.tool.execution.started\": {\n const name = strField(data, \"tool_name\", \"name\");\n if (name) line = \"Tool: \" + name;\n break;\n }\n default:\n return [\"\", false];\n }\n\n line = line.trim();\n if (!line) return [\"\", false];\n const runes = [...line];\n if (runes.length > MAX_THINKING_STEP_RUNES) {\n line = runes.slice(0, MAX_THINKING_STEP_RUNES).join(\"\") + \"…\";\n }\n return [line, true];\n}\n\nfunction formatPlanStepLine(data: Record<string, unknown>, suffix: string): string {\n const stepID = strField(data, \"step_id\");\n const desc = strField(data, \"description\");\n if (stepID && suffix) return `Step ${stepID}: ${suffix}`;\n if (stepID && desc) return `Step ${stepID}: ${desc}`;\n if (stepID) return `Step ${stepID}`;\n if (desc && suffix) return `Step: ${suffix}`;\n if (desc) return `Step: ${desc}`;\n if (suffix) return \"Step: \" + suffix;\n return \"\";\n}\n\nfunction formatAgentStepLine(data: Record<string, unknown>, suffix: string): string {\n const stepID = strField(data, \"step_id\");\n const desc = strField(data, \"description\");\n if (stepID && desc) return `Step ${stepID}: ${desc}`;\n if (desc) return suffix ? `Step: ${suffix}` : `Step: ${desc}`;\n if (stepID) return `Step ${stepID}`;\n return \"\";\n}\n\n/** Returns the first non-empty trimmed string field among `keys`. */\nfunction strField(data: Record<string, unknown>, ...keys: string[]): string {\n for (const key of keys) {\n const v = data[key];\n if (typeof v === \"string\") {\n const s = v.trim();\n if (s) return s;\n }\n }\n return \"\";\n}\n","/**\n * Single-flight query gate for appkit.\n *\n * Enforces single-flight query execution per session id and the\n * cancel-before-context ordering: when a query is cancelled, the daemon is\n * told to stop (command_request{command:\"cancel\"}) BEFORE the local abort\n * signal is cancelled, on a detached timeout so the caller's cancellation\n * cannot block the wire send.\n *\n * The app-agnostic successor to triarch's AcquireQuery/CancelQuery/\n * sendLoopCancelCommand.\n */\n\n/** Returned when a session already has an in-flight query. */\nexport class ErrQueryBusy extends Error {\n constructor() {\n super(\"appkit: query already in progress for session\");\n this.name = \"ErrQueryBusy\";\n }\n}\n\ninterface QueryState {\n /** Local abort for the query's timeout context. */\n abort: AbortController;\n /** Daemon-cancel sender (sends command_request{cancel} for the loop). */\n sendCancel: ((signal: AbortSignal) => Promise<void>) | null;\n}\n\n/**\n * QueryGate enforces single-flight query execution per session id.\n */\nexport class QueryGate {\n private active = new Map<string, QueryState>();\n\n /** Constructs an empty gate. */\n constructor() {}\n\n /**\n * Reserves sessionID for one agent turn. Returns ErrQueryBusy if a query is\n * already in flight. `abort` is the AbortController for the query's timeout\n * context. `sendCancel` is the daemon-cancel sender; it is invoked from\n * `cancel()` on a detached 10s timeout.\n */\n acquire(\n sessionID: string,\n abort: AbortController,\n sendCancel: ((signal: AbortSignal) => Promise<void>) | null,\n ): void {\n if (this.active.has(sessionID)) {\n throw new ErrQueryBusy();\n }\n this.active.set(sessionID, { abort, sendCancel });\n }\n\n /**\n * Cooperatively stops a running query for sessionID. Sends the daemon cancel\n * (on a detached 10s-timeout abort so caller cancellation cannot block the\n * wire send) BEFORE aborting the local context. Returns silently if no query\n * is in flight (intent already satisfied).\n */\n async cancel(sessionID: string): Promise<void> {\n const state = this.active.get(sessionID);\n if (!state) return;\n this.active.delete(sessionID);\n\n if (state.sendCancel) {\n const detached = new AbortController();\n const timer = setTimeout(() => detached.abort(), 10_000);\n try {\n await state.sendCancel(detached.signal);\n } catch {\n // Log but proceed to local cancel; the query is still stopping locally.\n } finally {\n clearTimeout(timer);\n }\n }\n state.abort.abort();\n }\n\n /**\n * Clears the gate for sessionID without sending a daemon cancel. Call when a\n * query completes normally (success or local failure) so the next turn can\n * acquire.\n */\n release(sessionID: string): void {\n this.active.delete(sessionID);\n }\n\n /** Reports whether a query is in flight for sessionID. */\n isActive(sessionID: string): boolean {\n return this.active.has(sessionID);\n }\n}\n","/**\n * Per-session connection pool for appkit.\n *\n * Manages a pool of daemon connections, one active per session. Reuses an\n * active connection when still live, otherwise bootstraps a fresh loop\n * (loop_new + subscribe) or reattaches an existing one (loop_reattach +\n * subscribe + reattachAndProbe). Persistence of session↔loop mappings is\n * abstracted behind SessionStore.\n *\n * The app-agnostic successor to triarch's SoothePoolManager connection\n * mechanics.\n */\n\nimport { StaleLoopError } from \"../errors.js\";\nimport type { Config } from \"../config.js\";\nimport { defaultConfig } from \"../config.js\";\nimport type { DecodedMessage } from \"../protocol.js\";\nimport type { SessionStore } from \"./session_store.js\";\nimport {\n type BootstrapFunc,\n type ClientFactory,\n type ManagedClient,\n defaultBootstrapFunc,\n defaultClientFactory,\n} from \"./client.js\";\n\n/** Returned when no free connection slot is available. */\nexport class ErrPoolExhausted extends Error {\n constructor() {\n super(\"appkit: connection pool exhausted\");\n this.name = \"ErrPoolExhausted\";\n }\n}\n\n/** Configures a ConnectionPool. Zero values use defaults. */\nexport interface PoolConfig {\n poolSize: number;\n queryTimeout: number; // ms\n connectionTimeout: number; // ms\n maxIdleTime: number; // ms\n healthCheckInterval: number; // ms\n}\n\n/** Returns env-overridable defaults (mirrors triarch).\n * `maxIdleTime` is enforced on acquire; `healthCheckInterval` is reserved. */\nexport function defaultPoolConfig(): PoolConfig {\n return {\n poolSize: 1000,\n queryTimeout: 30 * 60 * 1000,\n connectionTimeout: 30_000,\n maxIdleTime: 10 * 60 * 1000,\n healthCheckInterval: 30_000,\n };\n}\n\n/** One connection slot in the pool. */\nexport class PooledConn {\n slotID: number;\n client: ManagedClient;\n eventStream: AsyncGenerator<DecodedMessage> | null = null;\n streamController: AbortController | null = null;\n sessionID = \"\";\n loopID = \"\";\n workspaceID = \"\";\n lastUsed = 0;\n\n constructor(slotID: number, client: ManagedClient) {\n this.slotID = slotID;\n this.client = client;\n }\n\n /** Reports whether the underlying client signalled a drop. */\n isDisconnected(): boolean {\n return this.client.isDisconnected();\n }\n\n isConnected(): boolean {\n return this.client.isConnected() && !this.isDisconnected();\n }\n\n getLoopID(): string {\n return this.loopID;\n }\n}\n\n/**\n * ConnectionPool manages a pool of daemon connections, one active per session.\n */\nexport class ConnectionPool {\n private cfg: PoolConfig;\n private scfg: Config;\n private factory: ClientFactory;\n private bootstrap: BootstrapFunc;\n private store: SessionStore;\n private pool: PooledConn[] = [];\n private activeSlots = new Map<string, PooledConn>();\n private nextSlotID = 1;\n private url: string;\n\n /**\n * Constructs a pool. `url` is the daemon WebSocket URL. If cfg is null,\n * defaultPoolConfig is used; if scfg is null, defaultConfig is used; nil\n * factory/bootstrap fall back to the defaults.\n */\n constructor(\n url: string,\n store: SessionStore,\n cfg?: PoolConfig | null,\n scfg?: Config | null,\n factory?: ClientFactory | null,\n ) {\n this.cfg = cfg ?? defaultPoolConfig();\n this.scfg = scfg ?? defaultConfig();\n this.factory = factory ?? defaultClientFactory();\n this.bootstrap = defaultBootstrapFunc();\n this.store = store;\n this.url = url;\n // Pre-seed the pool with up to poolSize slots.\n for (let i = 0; i < this.cfg.poolSize; i++) {\n this.pool.push(new PooledConn(this.nextSlotID++, this.factory(url, this.scfg)));\n }\n }\n\n /** Overrides the loop bootstrap function (useful for test fakes). */\n withBootstrap(f: BootstrapFunc): ConnectionPool {\n if (f) this.bootstrap = f;\n return this;\n }\n\n /**\n * Returns a live connection for sessionID, reusing an active slot or\n * bootstrapping/reattaching as needed. The caller must call `release()`\n * when done with the connection (a turn completes or the session is reset).\n */\n async acquire(\n sessionID: string,\n workspaceID: string,\n userID: string,\n _signal?: AbortSignal,\n ): Promise<PooledConn> {\n // 1. Reuse active connection when still live.\n const existing = this.activeSlots.get(sessionID);\n if (existing) {\n if (existing.isDisconnected() || !existing.isConnected()) {\n await this.release(sessionID);\n } else {\n const idleTooLong =\n this.cfg.maxIdleTime > 0 &&\n existing.lastUsed > 0 &&\n Date.now() - existing.lastUsed > this.cfg.maxIdleTime;\n if (idleTooLong) {\n await this.release(sessionID);\n } else {\n existing.lastUsed = Date.now();\n await this.store.updateLastUsed(sessionID).catch(() => {});\n return existing;\n }\n }\n }\n\n // 2. Pull a slot from the pool.\n const conn = this.pool.pop();\n if (!conn) throw new ErrPoolExhausted();\n this.activeSlots.set(sessionID, conn);\n\n const { loopID, ok } = await this.store\n .getLoopIDForSession(sessionID)\n .catch(() => ({ loopID: \"\", ok: false }));\n let finalLoopID = \"\";\n try {\n if (!ok || !loopID) {\n // Fresh bootstrap.\n await conn.client.connect();\n finalLoopID = await this.bootstrapNew(conn, workspaceID, userID);\n await this.store.createSession(workspaceID, sessionID, finalLoopID, \"\").catch(() => {});\n } else {\n // Reattach.\n try {\n await this.resumeAndReattach(conn, loopID);\n finalLoopID = loopID;\n } catch {\n // Reattach failed (incl. StaleLoopError) → fresh bootstrap.\n await conn.client.connect();\n finalLoopID = await this.bootstrapNew(conn, workspaceID, userID);\n await this.store.createSession(workspaceID, sessionID, finalLoopID, \"\").catch(() => {});\n }\n }\n } catch (err) {\n await this.release(sessionID);\n throw err;\n }\n\n conn.sessionID = sessionID;\n conn.loopID = finalLoopID;\n conn.workspaceID = workspaceID;\n conn.lastUsed = Date.now();\n await this.store.updateLastUsed(sessionID).catch(() => {});\n return conn;\n }\n\n /** Tears down the connection for sessionID and returns the slot. */\n async release(sessionID: string): Promise<void> {\n const conn = this.activeSlots.get(sessionID);\n if (!conn) return;\n this.activeSlots.delete(sessionID);\n if (conn.streamController) {\n conn.streamController.abort();\n conn.streamController = null;\n }\n try {\n conn.client.close();\n } catch {\n // ignore\n }\n conn.sessionID = \"\";\n conn.loopID = \"\";\n conn.eventStream = null;\n // Return a fresh slot to the pool (the closed client is spent).\n this.pool.push(new PooledConn(this.nextSlotID++, this.factory(this.url, this.scfg)));\n }\n\n /**\n * Tears down the connection for sessionID so the next acquire bootstraps\n * fresh. The store should archive the loop id so getLoopIDForSession returns\n * false next time.\n */\n async resetSession(sessionID: string): Promise<void> {\n await this.release(sessionID);\n }\n\n /** Gracefully shuts down all active connections. */\n stop(): void {\n for (const [sid, conn] of this.activeSlots) {\n if (conn.streamController) conn.streamController.abort();\n try {\n conn.client.close();\n } catch {\n // ignore\n }\n this.activeSlots.delete(sid);\n }\n }\n\n /** Stats snapshot for observability. */\n stats(): { active: number; idle: number } {\n return { active: this.activeSlots.size, idle: this.pool.length };\n }\n\n /** Bootstrap a fresh loop and start the reader. */\n private async bootstrapNew(\n conn: PooledConn,\n workspaceID: string,\n userID: string,\n ): Promise<string> {\n const loopID = await this.bootstrap(conn.client, workspaceID, userID, this.scfg);\n this.startReader(conn);\n return loopID;\n }\n\n /** Reconnect + reattach an existing loop, then start the reader. */\n private async resumeAndReattach(conn: PooledConn, loopID: string): Promise<void> {\n await conn.client.connect();\n try {\n await conn.client.reattachAndProbe(loopID);\n } catch (err) {\n if (err instanceof StaleLoopError) throw err;\n throw err;\n }\n this.startReader(conn);\n }\n\n /** Starts a receiveMessages generator and stores the stream + controller. */\n private startReader(conn: PooledConn): void {\n const controller = new AbortController();\n conn.streamController = controller;\n conn.eventStream = conn.client.receiveMessages(controller.signal);\n }\n}\n","/**\n * ManagedClient — the subset of the core Client that appkit's ConnectionPool\n * and TurnRunner depend on.\n *\n * The concrete `Client` satisfies it; tests supply a fake. Defining it as an\n * interface lets appkit be unit-tested without a live WebSocket daemon.\n */\n\nimport type { Client, InputOptions } from \"../client.js\";\nimport type { Config } from \"../config.js\";\nimport type { DecodedMessage } from \"../protocol.js\";\nimport type { DisconnectCause } from \"../errors.js\";\n\n/**\n * ManagedClient is the subset of the core Client that appkit depends on.\n * Methods are async (TS) rather than channel-based (Go).\n */\nexport interface ManagedClient {\n /** Dials and handshakes. */\n connect(): Promise<void>;\n /** Re-dials after a drop. */\n reconnect(): Promise<void>;\n /** Resumes a loop by id and probes liveness. */\n reattachAndProbe(loopID: string): Promise<void>;\n /** Sends a fire-and-forget notification (e.g. loop_input). */\n sendMessage(msg: unknown): Promise<void>;\n /** Sends user input to the daemon (loop_input notification). */\n sendInput(text: string, options?: InputOptions): Promise<void>;\n /** Starts the read loop, returning the event stream. */\n receiveMessages(signal?: AbortSignal): AsyncGenerator<DecodedMessage>;\n /** Returns whether the connection has dropped. */\n isDisconnected(): boolean;\n /** Returns the drop cause, or null if not dropped. */\n disconnectCause(): DisconnectCause | null;\n /** Reports connection liveness. */\n isConnected(): boolean;\n /** Tears down the connection. */\n close(): void;\n}\n\n/**\n * Builds a fresh ManagedClient for a daemon URL and config. ConnectionPool\n * calls it per pooled connection. Applications may supply a custom factory\n * (e.g. wrapping Client with logging/metrics).\n */\nexport type ClientFactory = (url: string, config?: Config) => ManagedClient;\n\nimport { defaultConfig } from \"../config.js\";\nimport { Client as CoreClient } from \"../client.js\";\n\n/** Returns a ClientFactory that builds a core Client. */\nexport function defaultClientFactory(): ClientFactory {\n return (url: string, config?: Config) => {\n return new CoreClient(url, config ?? defaultConfig()) as unknown as ManagedClient;\n };\n}\n\n/**\n * Creates a new loop (loop_new + subscribe) on a connected client and returns\n * the new loop id. The default implementation calls bootstrapLoopSession;\n * apps may override it.\n */\nexport type BootstrapFunc = (\n client: ManagedClient,\n workspaceID: string,\n userID: string,\n config?: Config,\n) => Promise<string>;\n\nimport { bootstrapLoopSession } from \"../session.js\";\nimport type { LoopNewOptions } from \"../protocol.js\";\n\n/** Default bootstrap: loop_new + subscribe(loop_events). */\nexport function defaultBootstrapFunc(): BootstrapFunc {\n return async (client: ManagedClient, workspaceID: string, userID: string, config?: Config) => {\n // bootstrapLoopSession expects a Client; cast through unknown.\n const c = client as unknown as Client;\n const opts: LoopNewOptions = {\n client_workspace: workspaceID,\n user_id: userID,\n client_workspace_id: workspaceID,\n };\n return bootstrapLoopSession(c, \"\", config, opts);\n };\n}\n","/**\n * Attachment image compaction for appkit.\n *\n * When `sharp` is installed (optionalDependency), oversized image/* payloads\n * are downscaled. Without sharp, attachments pass through unchanged.\n */\n\nexport interface CompactImageOptions {\n /** Max width or height in pixels. Default 768. */\n maxDim?: number;\n /** JPEG encode quality 1–100. Default 85. */\n jpegQuality?: number;\n}\n\nfunction compactDefaults(opts?: CompactImageOptions | null): { maxDim: number; quality: number } {\n return {\n maxDim: opts?.maxDim && opts.maxDim > 0 ? opts.maxDim : 768,\n quality: opts?.jpegQuality && opts.jpegQuality > 0 ? opts.jpegQuality : 85,\n };\n}\n\ntype SharpModule = {\n default: (\n input: Buffer,\n options?: { failOn?: string },\n ) => {\n metadata: () => Promise<{ width?: number; height?: number }>;\n resize: (\n w: number,\n h: number,\n opts?: { fit?: string },\n ) => {\n png: () => { toBuffer: () => Promise<Buffer> };\n jpeg: (opts?: { quality?: number }) => { toBuffer: () => Promise<Buffer> };\n };\n };\n};\n\nlet sharpLoader: Promise<SharpModule | null> | null = null;\n\nasync function loadSharp(): Promise<SharpModule | null> {\n if (!sharpLoader) {\n sharpLoader = (async () => {\n try {\n const m = await (Function('return import(\"sharp\")')() as Promise<{ default: unknown }>);\n return m as unknown as SharpModule;\n } catch {\n return null;\n }\n })();\n }\n return sharpLoader;\n}\n\n/**\n * Downscales image/* payloads when either dimension exceeds MaxDim.\n * Non-images and decode failures pass through unchanged.\n * PNG stays PNG; other image types re-encode as JPEG when sharp is available.\n */\nexport async function compactImageAttachment(\n mimeType: string,\n dataB64: string,\n opts?: CompactImageOptions | null,\n): Promise<[string, string]> {\n if (!dataB64 || !mimeType.startsWith(\"image/\")) {\n return [mimeType, dataB64];\n }\n let raw: Buffer;\n try {\n raw = Buffer.from(dataB64, \"base64\");\n } catch {\n return [mimeType, dataB64];\n }\n if (raw.length === 0) return [mimeType, dataB64];\n\n const sharpMod = await loadSharp();\n if (!sharpMod) return [mimeType, dataB64];\n\n const { maxDim, quality } = compactDefaults(opts);\n try {\n const img = sharpMod.default(raw, { failOn: \"none\" });\n const meta = await img.metadata();\n const w = meta.width ?? 0;\n const h = meta.height ?? 0;\n if (w <= 0 || h <= 0 || (w <= maxDim && h <= maxDim)) {\n return [mimeType, dataB64];\n }\n let nw = w;\n let nh = h;\n if (w >= h) {\n if (w > maxDim) {\n nw = maxDim;\n nh = Math.max(1, Math.round((h * maxDim) / w));\n }\n } else if (h > maxDim) {\n nh = maxDim;\n nw = Math.max(1, Math.round((w * maxDim) / h));\n }\n const resized = img.resize(nw, nh, { fit: \"fill\" });\n if (mimeType === \"image/png\") {\n const buf = await resized.png().toBuffer();\n return [mimeType, buf.toString(\"base64\")];\n }\n const buf = await resized.jpeg({ quality }).toBuffer();\n return [\"image/jpeg\", buf.toString(\"base64\")];\n } catch {\n return [mimeType, dataB64];\n }\n}\n\n/**\n * Applies compactImageAttachment to each attachment map with mime_type + data.\n */\nexport async function compactAttachments(\n atts: Record<string, unknown>[],\n opts?: CompactImageOptions | null,\n): Promise<Record<string, unknown>[]> {\n if (!atts.length) return atts;\n const out: Record<string, unknown>[] = [];\n for (const att of atts) {\n const cp: Record<string, unknown> = { ...att };\n const mime = typeof cp.mime_type === \"string\" ? cp.mime_type : \"\";\n const data = typeof cp.data === \"string\" ? cp.data : \"\";\n if (mime && data) {\n const [outMime, outData] = await compactImageAttachment(mime, data, opts);\n cp.mime_type = outMime;\n cp.data = outData;\n }\n out.push(cp);\n }\n return out;\n}\n","/**\n * Turn runner for appkit.\n *\n * Executes one query turn end-to-end: acquire a pooled connection, enforce\n * single-flight, send loop_input, consume the event stream, classify events,\n * resolve the deliverable, persist the reply, and broadcast completion.\n *\n * Supports lifecycle knobs: idle timeout, soft-complete\n * policies, attachment compaction, and stream-close soft-complete.\n */\n\nimport type { PooledConn } from \"./pool.js\";\nimport { type ConnectionPool } from \"./pool.js\";\nimport { type EventClassifier, ChatEventTerminal } from \"./classifier.js\";\nimport { type QueryGate } from \"./query_gate.js\";\nimport { type SSEBroadcaster, SSEEvent } from \"./broadcaster.js\";\nimport type { SessionStore, SessionMessage } from \"./session_store.js\";\nimport type { LoopInputIntentHint } from \"../intent_hints.js\";\nimport { validateLoopInputIntentHint } from \"../intent_hints.js\";\nimport type { DecodedMessage } from \"../protocol.js\";\nimport { compactAttachments, type CompactImageOptions } from \"./attachments.js\";\n\n/** Returned when a turn exceeds the configured timeout and policy is Fail. */\nexport class ErrQueryTimeout extends Error {\n constructor() {\n super(\"appkit: query timeout\");\n this.name = \"ErrQueryTimeout\";\n }\n}\n\n/** Returned when no events arrive within IdleTimeout and policy is Fail. */\nexport class ErrIdleTimeout extends Error {\n constructor() {\n super(\"appkit: idle timeout\");\n this.name = \"ErrIdleTimeout\";\n }\n}\n\n/** Selects fail vs soft-complete behaviour for idle, query, and stream-close. */\nexport enum TimeoutPolicy {\n Fail = 0,\n SoftComplete = 1,\n}\n\nexport type StreamClosePolicy = TimeoutPolicy;\nexport const StreamCloseFail = TimeoutPolicy.Fail;\nexport const StreamCloseSoftComplete = TimeoutPolicy.SoftComplete;\n\n/** Configures a TurnRunner. */\nexport interface TurnConfig {\n /** Per-turn deadline in ms. Defaults to 30m. */\n queryTimeout: number;\n /** Max silence between classified events in ms. Zero disables (default). */\n idleTimeout?: number;\n /**\n * When > 0, raises idleTimeout for turns with attachments if idleTimeout\n * is positive but below this floor.\n */\n minIdleTimeoutWithAttachments?: number;\n /** Fail vs soft-complete when the idle watchdog fires. Default Fail. */\n onIdleTimeout?: TimeoutPolicy;\n /** Fail vs soft-complete when queryTimeout fires. Default Fail. */\n onQueryTimeout?: TimeoutPolicy;\n /** Fail vs soft-complete when the event stream closes. Default Fail. */\n onStreamClose?: StreamClosePolicy;\n /** Run compactAttachments before buildInput. Default false. */\n compactAttachmentsBeforeSend?: boolean;\n /** Overrides for compactAttachmentsBeforeSend. */\n compactImageOpts?: CompactImageOptions | null;\n}\n\n/** Carries optional daemon hints on a loop_input payload. */\nexport interface InputOpts {\n intentHint?: LoopInputIntentHint;\n preferredSubagent?: string;\n responseSchema?: Record<string, unknown>;\n responseSchemaName?: string;\n responseSchemaStrict?: boolean;\n}\n\n/** Optional attachment shape ({mime_type, data(base64)}). */\nexport type Attachment = Record<string, unknown>;\n\n/**\n * Builds a loop_input payload with optional attachments. Apps build this from\n * their product modes (e.g. triarch's ask/agent/deep-research).\n */\nexport function inputMessageForLoop(\n text: string,\n loopID: string,\n attachments?: Attachment[],\n opts?: InputOpts,\n): Record<string, unknown> {\n const msg: Record<string, unknown> = { type: \"loop_input\", content: text };\n if (loopID) msg.loop_id = loopID;\n if (attachments && attachments.length > 0) msg.attachments = attachments;\n if (opts) {\n if (opts.intentHint?.trim()) {\n const hintError = validateLoopInputIntentHint(opts.intentHint);\n if (hintError) {\n throw new Error(hintError);\n }\n msg.intent_hint = opts.intentHint.trim();\n }\n if (opts.preferredSubagent?.trim()) msg.preferred_subagent = opts.preferredSubagent.trim();\n if (opts.responseSchema && Object.keys(opts.responseSchema).length > 0) {\n msg.response_schema = opts.responseSchema;\n }\n if (opts.responseSchemaName?.trim()) msg.response_schema_name = opts.responseSchemaName.trim();\n if (opts.responseSchemaStrict !== undefined)\n msg.response_schema_strict = opts.responseSchemaStrict;\n }\n return msg;\n}\n\n/** Effective idle timeout for a turn (attachment floor applied). */\nexport function idleTimeoutForTurn(cfg: TurnConfig, hasAttachments: boolean): number {\n const idle = cfg.idleTimeout ?? 0;\n if (idle <= 0) return 0;\n const floor = cfg.minIdleTimeoutWithAttachments ?? 0;\n if (hasAttachments && floor > 0 && idle < floor) return floor;\n return idle;\n}\n\n/** Completion hook signature. */\nexport type OnComplete = (\n sessionID: string,\n loopID: string,\n content: string,\n completionEvent: string,\n elapsedMs: number,\n) => void;\n/** Error hook signature. */\nexport type OnError = (sessionID: string, loopID: string, err: Error) => void;\n\n/**\n * TurnRunner executes one query turn end-to-end.\n */\nexport class TurnRunner {\n private pool: ConnectionPool;\n private gate: QueryGate;\n private classifier: EventClassifier;\n private store: SessionStore;\n private broadcaster: SSEBroadcaster | null;\n private cfg: TurnConfig;\n private buildInput: typeof inputMessageForLoop = inputMessageForLoop;\n private onComplete: OnComplete | null = null;\n private onError: OnError | null = null;\n\n constructor(\n pool: ConnectionPool,\n gate: QueryGate,\n classifier: EventClassifier,\n store: SessionStore,\n broadcaster: SSEBroadcaster | null,\n cfg: TurnConfig,\n ) {\n this.pool = pool;\n this.gate = gate;\n this.classifier = classifier;\n this.store = store;\n this.broadcaster = broadcaster;\n this.cfg = {\n ...cfg,\n queryTimeout: cfg.queryTimeout > 0 ? cfg.queryTimeout : 30 * 60 * 1000,\n };\n }\n\n withInputBuilder(f: typeof inputMessageForLoop): TurnRunner {\n if (f) this.buildInput = f;\n return this;\n }\n\n withOnComplete(f: OnComplete): TurnRunner {\n this.onComplete = f;\n return this;\n }\n\n withOnError(f: OnError): TurnRunner {\n this.onError = f;\n return this;\n }\n\n async execute(\n sessionID: string,\n message: string,\n userID: string,\n workspaceID: string,\n attachments: Attachment[] | null,\n opts: InputOpts | null,\n signal?: AbortSignal,\n ): Promise<void> {\n let conn: PooledConn;\n try {\n conn = await this.pool.acquire(sessionID, workspaceID, userID, signal);\n } catch (err) {\n await this.persistFailed(sessionID, \"\", err as Error);\n this.broadcastError(sessionID, err as Error);\n this.onError?.(sessionID, \"\", err as Error);\n throw err;\n }\n const loopID = conn.getLoopID();\n\n const timeoutController = new AbortController();\n const timeoutMs = this.cfg.queryTimeout;\n const timer = setTimeout(() => timeoutController.abort(), timeoutMs);\n\n const sendCancel = async (detachedSignal: AbortSignal) => {\n await this.sendLoopCancel(detachedSignal, conn, loopID);\n };\n try {\n this.gate.acquire(sessionID, timeoutController, sendCancel);\n } catch (err) {\n clearTimeout(timer);\n await this.pool.release(sessionID);\n await this.persistFailed(sessionID, loopID, err as Error);\n this.broadcastError(sessionID, err as Error);\n this.onError?.(sessionID, loopID, err as Error);\n throw err;\n }\n\n let idleTimer: ReturnType<typeof setTimeout> | null = null;\n const clearIdle = () => {\n if (idleTimer) {\n clearTimeout(idleTimer);\n idleTimer = null;\n }\n };\n\n try {\n let atts = attachments ?? undefined;\n if (this.cfg.compactAttachmentsBeforeSend && atts && atts.length > 0) {\n atts = await compactAttachments(atts, this.cfg.compactImageOpts);\n }\n\n const inputMsg = this.buildInput(message, loopID, atts, opts ?? undefined);\n try {\n await conn.client.sendMessage(inputMsg);\n } catch (err) {\n await this.persistFailed(sessionID, loopID, err as Error);\n this.broadcastError(sessionID, err as Error);\n this.onError?.(sessionID, loopID, err as Error);\n throw err;\n }\n\n const eventStream = conn.eventStream;\n if (!eventStream) {\n const err = new Error(`missing event stream for session ${sessionID} (loop ${loopID})`);\n await this.persistFailed(sessionID, loopID, err);\n this.broadcastError(sessionID, err);\n this.onError?.(sessionID, loopID, err);\n throw err;\n }\n\n let assistantContent = \"\";\n const startedAt = Date.now();\n const idleForTurn = idleTimeoutForTurn(this.cfg, (attachments?.length ?? 0) > 0);\n\n type RaceTag = \"timeout\" | \"caller\" | \"idle\";\n let idleReject: (() => void) | null = null;\n\n const armIdle = (): Promise<\"idle\"> => {\n clearIdle();\n idleReject = null;\n if (idleForTurn <= 0) {\n return new Promise<\"idle\">(() => {});\n }\n return new Promise<\"idle\">(resolve => {\n idleReject = () => resolve(\"idle\");\n idleTimer = setTimeout(() => {\n idleReject?.();\n }, idleForTurn);\n });\n };\n\n let idleRace = armIdle();\n\n const abortRace = new Promise<RaceTag>(resolve => {\n const onTimeout = () => resolve(\"timeout\");\n timeoutController.signal.addEventListener(\"abort\", onTimeout, { once: true });\n if (signal) {\n const onCaller = () => resolve(\"caller\");\n signal.addEventListener(\"abort\", onCaller, { once: true });\n }\n });\n\n const iterator = eventStream[Symbol.asyncIterator]();\n\n while (true) {\n const next = iterator.next();\n const raced = await Promise.race([\n next.then(res => ({ tag: \"msg\" as const, res })),\n abortRace.then(tag => ({ tag })),\n idleRace.then(tag => ({ tag })),\n ]);\n\n if (\"tag\" in raced && raced.tag !== \"msg\") {\n if (raced.tag === \"caller\" || signal?.aborted) {\n clearIdle();\n const err = new Error(\"aborted\");\n await this.persistFailed(sessionID, loopID, err);\n this.broadcastError(sessionID, err);\n this.onError?.(sessionID, loopID, err);\n throw err;\n }\n if (raced.tag === \"idle\") {\n clearIdle();\n await this.sendLoopCancel(new AbortController().signal, conn, loopID).catch(() => {});\n await this.finishTimeout(\n sessionID,\n loopID,\n assistantContent,\n startedAt,\n new ErrIdleTimeout(),\n \"idle_timeout\",\n this.cfg.onIdleTimeout ?? TimeoutPolicy.Fail,\n );\n return;\n }\n clearIdle();\n await this.sendLoopCancel(new AbortController().signal, conn, loopID).catch(() => {});\n await this.finishTimeout(\n sessionID,\n loopID,\n assistantContent,\n startedAt,\n new ErrQueryTimeout(),\n \"query_timeout\",\n this.cfg.onQueryTimeout ?? TimeoutPolicy.Fail,\n );\n return;\n }\n\n const res = (raced as { tag: \"msg\"; res: IteratorResult<DecodedMessage> }).res;\n if (res.done) {\n clearIdle();\n if (\n (this.cfg.onStreamClose ?? TimeoutPolicy.Fail) === TimeoutPolicy.SoftComplete &&\n assistantContent.trim() !== \"\"\n ) {\n await this.completeTurn(\n sessionID,\n loopID,\n assistantContent,\n startedAt,\n \"stream_closed\",\n );\n return;\n }\n const err = new Error(\"event stream closed\");\n await this.persistFailed(sessionID, loopID, err);\n this.broadcastError(sessionID, err);\n this.onError?.(sessionID, loopID, err);\n throw err;\n }\n\n idleRace = armIdle();\n const msg = res.value;\n\n const eventResult = this.classifier.classify(msg, assistantContent);\n if (eventResult.err && eventResult.terminal === ChatEventTerminal.FailedComplete) {\n clearIdle();\n await this.persistFailed(sessionID, loopID, eventResult.err);\n this.broadcastError(sessionID, eventResult.err);\n this.onError?.(sessionID, loopID, eventResult.err);\n throw eventResult.err;\n }\n\n const step = (eventResult.thinkingStep ?? \"\").trim();\n if (step) this.broadcastThinkingStep(sessionID, step);\n\n if (eventResult.content) {\n if (eventResult.content.startsWith(assistantContent)) {\n assistantContent = eventResult.content;\n } else {\n assistantContent += eventResult.content;\n }\n }\n\n const [final, deliverable] = this.classifier.resolveDeliverableFinalContent(\n eventResult,\n assistantContent,\n );\n if (deliverable) {\n clearIdle();\n await this.completeTurn(\n sessionID,\n loopID,\n final,\n startedAt,\n eventResult.completionEvent ?? \"\",\n );\n return;\n }\n }\n } finally {\n clearIdle();\n clearTimeout(timer);\n this.gate.release(sessionID);\n }\n }\n\n private async finishTimeout(\n sessionID: string,\n loopID: string,\n content: string,\n startedAt: number,\n failErr: Error,\n completionEvent: string,\n policy: TimeoutPolicy,\n ): Promise<void> {\n if (policy === TimeoutPolicy.SoftComplete && content.trim() !== \"\") {\n await this.completeTurn(sessionID, loopID, content, startedAt, completionEvent);\n return;\n }\n await this.persistFailed(sessionID, loopID, failErr);\n this.broadcastError(sessionID, failErr);\n this.onError?.(sessionID, loopID, failErr);\n throw failErr;\n }\n\n private async completeTurn(\n sessionID: string,\n loopID: string,\n final: string,\n startedAt: number,\n completionEvent: string,\n ): Promise<void> {\n const elapsedMs = Date.now() - startedAt;\n await this.persistResponse(sessionID, loopID, final, startedAt, completionEvent);\n this.broadcastComplete(sessionID, final);\n this.onComplete?.(sessionID, loopID, final, completionEvent, elapsedMs);\n }\n\n private async sendLoopCancel(\n _signal: AbortSignal,\n conn: PooledConn,\n loopID: string,\n ): Promise<void> {\n const lid = (loopID ?? \"\").trim();\n if (!conn || !lid) return;\n const cancelMsg = { type: \"command_request\", command: \"cancel\", loop_id: lid };\n await conn.client.sendMessage(cancelMsg);\n }\n\n private async persistResponse(\n sessionID: string,\n loopID: string,\n content: string,\n startedAt: number,\n completionEvent: string,\n ): Promise<void> {\n const msg: SessionMessage = {\n role: \"assistant\",\n content,\n metadata: {\n started_at: startedAt,\n completed_at: Date.now(),\n duration_ms: Date.now() - startedAt,\n status: \"completed\",\n completion_event: completionEvent,\n deliverable: true,\n },\n };\n await this.store.appendMessage(sessionID, msg).catch(() => {});\n }\n\n private async persistFailed(sessionID: string, _loopID: string, err: Error): Promise<void> {\n const msg: SessionMessage = {\n role: \"error\",\n content: err.message,\n metadata: { status: \"failed\", error_message: err.message },\n };\n await this.store.appendMessage(sessionID, msg).catch(() => {});\n }\n\n private broadcastThinkingStep(sessionID: string, step: string): void {\n if (!this.broadcaster) return;\n this.broadcaster.broadcast(sessionID, { type: \"delta\", data: step + \"\\n\" } as SSEEvent);\n }\n\n private broadcastComplete(sessionID: string, content: string): void {\n this.broadcaster?.broadcast(sessionID, { type: \"complete\", data: content } as SSEEvent);\n }\n\n private broadcastError(sessionID: string, err: Error): void {\n this.broadcaster?.broadcast(sessionID, { type: \"query_error\", data: err.message } as SSEEvent);\n }\n}\n","/**\n * Dual-socket daemon loop session with turn streaming (Python DaemonSession parity).\n *\n * Owns a subscribed stream WebSocket plus an RPC sidecar so metadata calls do not\n * starve loop events. `iterTurnChunks` handles idle timeout, post-idle drain,\n * loop scoping, and connection-loss detection.\n */\n\nimport { Client } from \"../client.js\";\nimport { defaultConfig, type Config } from \"../config.js\";\nimport { StaleLoopError } from \"../errors.js\";\nimport { bootstrapLoopSession, connectWithRetries } from \"../session.js\";\nimport { STREAM_END, isTurnEndCustomData, isTurnProgressChunk } from \"../stream_terminal.js\";\nimport { shouldDropStreamChunkEarly } from \"./chunk_filter.js\";\nimport { unwrapNext } from \"./events.js\";\nimport { TurnEventStats } from \"./observability.js\";\n\nexport const DEFAULT_POST_IDLE_DRAIN_MS = 500;\n\nexport type EarlyDropFn = (namespace: unknown[], mode: string, data: unknown) => boolean;\nexport type StatsFactory = () => TurnEventStats;\nexport type StreamDeliveryResolver = () => string;\n\nexport interface DaemonSessionOptions {\n workspace?: string | null;\n streamDelivery?: string | StreamDeliveryResolver;\n postIdleDrainDeadlineMs?: number;\n earlyDropFn?: EarlyDropFn | null;\n statsFactory?: StatsFactory | null;\n config?: Config;\n}\n\nexport type TurnChunk = [namespace: unknown[], mode: string, data: unknown];\n\n/** Daemon-backed loop session with stream + RPC sockets. */\nexport class DaemonSession {\n private wsUrl: string;\n private workspace: string | null | undefined;\n private streamDelivery: string | StreamDeliveryResolver;\n private client: Client;\n private rpcClient: Client;\n private loopId: string | null = null;\n private readBusy = false;\n private rpcBusy = false;\n private rpcConnected = false;\n private streaming = false;\n private postIdleDrainDeadlineMs: number;\n private closed = false;\n private earlyDropFn: EarlyDropFn;\n private statsFactory: StatsFactory;\n private config: Config;\n\n turnEventStats: TurnEventStats;\n lastTurnEndState: string | null = null;\n lastTurnCancellationSeen = false;\n lastTurnErrorMessage: string | null = null;\n\n constructor(wsUrl: string, opts: DaemonSessionOptions = {}) {\n this.wsUrl = wsUrl;\n this.workspace = opts.workspace;\n this.streamDelivery = opts.streamDelivery ?? \"adaptive\";\n this.config = opts.config ?? defaultConfig();\n this.client = new Client(wsUrl, this.config);\n this.rpcClient = new Client(wsUrl, this.config);\n this.postIdleDrainDeadlineMs =\n opts.postIdleDrainDeadlineMs && opts.postIdleDrainDeadlineMs > 0\n ? opts.postIdleDrainDeadlineMs\n : DEFAULT_POST_IDLE_DRAIN_MS;\n this.earlyDropFn = opts.earlyDropFn ?? shouldDropStreamChunkEarly;\n this.statsFactory = opts.statsFactory ?? (() => new TurnEventStats());\n this.turnEventStats = this.statsFactory();\n }\n\n get streamClient(): Client {\n return this.client;\n }\n\n get rpcSideClient(): Client {\n return this.rpcClient;\n }\n\n get activeLoopId(): string | null {\n return this.loopId;\n }\n\n private resolveStreamDeliveryMode(): string {\n const delivery = this.streamDelivery;\n if (typeof delivery === \"function\") return String(delivery() || \"adaptive\");\n return String(delivery || \"adaptive\");\n }\n\n get streamDeliveryMode(): string {\n return this.resolveStreamDeliveryMode();\n }\n\n private shouldDrop(namespace: unknown[], mode: string, data: unknown): boolean {\n return Boolean(this.earlyDropFn(namespace, mode, data));\n }\n\n async connect(resumeLoopId?: string | null): Promise<Record<string, unknown>> {\n await connectWithRetries(this.client);\n return this.bootstrapLoop(resumeLoopId ?? null);\n }\n\n private async bootstrapLoop(resumeLoopId: string | null): Promise<Record<string, unknown>> {\n const loopNew = this.workspace\n ? { client_workspace: this.workspace, workspace: this.workspace }\n : undefined;\n const loopId = await bootstrapLoopSession(this.client, resumeLoopId, this.config, loopNew);\n this.loopId = loopId;\n return { type: \"status\", loop_id: loopId, state: \"ready\" };\n }\n\n async newLoop(): Promise<Record<string, unknown>> {\n return this.bootstrapLoop(null);\n }\n\n async switchLoop(loopId: string): Promise<Record<string, unknown>> {\n return this.bootstrapLoop(loopId);\n }\n\n async ensureConnected(): Promise<void> {\n if (this.client.isConnected() && !this.client.isDisconnected()) return;\n\n let resumeLoopId = this.loopId;\n if (this.rpcConnected) {\n this.rpcClient.close();\n this.rpcConnected = false;\n }\n\n try {\n await this.client.reconnect();\n } catch {\n this.client.close();\n await connectWithRetries(this.client);\n }\n\n if (resumeLoopId) {\n try {\n await this.client.reattachAndProbe(resumeLoopId);\n this.loopId = resumeLoopId;\n return;\n } catch (err) {\n if (!(err instanceof StaleLoopError)) throw err;\n resumeLoopId = null;\n }\n }\n\n await this.bootstrapLoop(resumeLoopId);\n }\n\n async close(): Promise<void> {\n if (this.closed) return;\n this.closed = true;\n this.client.close();\n this.rpcClient.close();\n this.rpcConnected = false;\n }\n\n async detach(): Promise<void> {\n if (!this.client.isConnected()) return;\n try {\n await this.client.notify(\"disconnect\", {});\n } catch {\n // ignore\n }\n }\n\n async sendTurn(\n text: string,\n options?: {\n autonomous?: boolean;\n maxIterations?: number;\n preferredSubagent?: string;\n model?: string;\n modelParams?: Record<string, unknown>;\n attachments?: Array<{ mime_type: string; data: string }>;\n clarificationMode?: string;\n clarificationAnswer?: boolean;\n intentHint?: string;\n },\n ): Promise<void> {\n if (!this.loopId) throw new Error(\"No active loop session\");\n await this.client.sendInput(text, {\n loopID: this.loopId,\n autonomous: options?.autonomous,\n maxIterations: options?.maxIterations,\n subagent: options?.preferredSubagent,\n model: options?.model,\n modelParams: options?.modelParams,\n attachments: options?.attachments,\n clarificationMode: options?.clarificationMode,\n clarificationAnswer: options?.clarificationAnswer,\n intentHint: options?.intentHint as\n import(\"../intent_hints.js\").LoopInputIntentHint | undefined,\n });\n }\n\n async cancelActiveTurn(): Promise<void> {\n await this.client.notify(\"slash_command\", { cmd: \"/cancel\" });\n }\n\n private async *drainStreamEventsAfterIdle(\n expectedLoopId: string | null,\n ): AsyncGenerator<TurnChunk> {\n const deadline = Date.now() + this.postIdleDrainDeadlineMs;\n let exp = expectedLoopId;\n while (Date.now() < deadline) {\n const event = await this.client.readEventWithTimeout(250);\n if (!event) break;\n let frame = event;\n let eventType = String(frame.type ?? \"\");\n if (eventType === \"next\") {\n frame = unwrapNext(frame) ?? frame;\n eventType = String(frame.type ?? \"\");\n }\n const eventLoopId = frame.loop_id;\n if (exp && typeof eventLoopId === \"string\" && eventLoopId && eventLoopId !== exp) {\n continue;\n }\n if (eventType === \"error\") {\n const errObj = (frame.error as { message?: string }) ?? {};\n throw new Error(String(errObj.message || frame.message || \"daemon error\"));\n }\n if (eventType === \"status\") {\n const loopEv = frame.loop_id;\n if (typeof loopEv === \"string\" && loopEv) {\n this.loopId = loopEv;\n exp = loopEv;\n }\n continue;\n }\n if (eventType !== \"event\") continue;\n const data = frame.data;\n const namespace = Array.isArray(frame.namespace) ? (frame.namespace as unknown[]) : [];\n const mode = String(frame.mode ?? \"\");\n if (this.shouldDrop(namespace, mode, data)) {\n this.turnEventStats.filteredEarly += 1;\n continue;\n }\n this.turnEventStats.postIdleDrained += 1;\n yield [namespace, mode, data];\n }\n }\n\n private async withRpcLock<T>(fn: () => Promise<T>): Promise<T> {\n while (this.rpcBusy) {\n await new Promise(r => setTimeout(r, 5));\n }\n this.rpcBusy = true;\n try {\n return await fn();\n } finally {\n this.rpcBusy = false;\n }\n }\n\n private async ensureRpcConnected(): Promise<void> {\n if (this.rpcConnected && this.rpcClient.isConnected()) return;\n await connectWithRetries(this.rpcClient);\n this.rpcConnected = true;\n }\n\n async listLoops(_limit = 20): Promise<Record<string, unknown>> {\n return this.withRpcLock(async () => {\n await this.ensureRpcConnected();\n return this.rpcClient.listLoops(15_000);\n });\n }\n\n async fetchLoopCards(loopId: string): Promise<{\n cards: unknown[];\n seq: number;\n contextTokens: number;\n success: boolean;\n }> {\n const lid = String(loopId || \"\").trim();\n if (!lid) return { cards: [], seq: 0, contextTokens: 0, success: false };\n return this.withRpcLock(async () => {\n await this.ensureRpcConnected();\n try {\n const resp = await this.rpcClient.fetchLoopCards(lid, 30_000);\n const rawCards = resp.cards;\n return {\n cards: Array.isArray(rawCards) ? rawCards : [],\n seq: Number(resp.seq ?? 0),\n contextTokens:\n typeof resp.context_tokens === \"number\" && resp.context_tokens >= 0\n ? resp.context_tokens\n : 0,\n success: true,\n };\n } catch {\n return { cards: [], seq: 0, contextTokens: 0, success: false };\n }\n });\n }\n\n async fetchLoopHistory(loopId: string): Promise<{\n goals: unknown[];\n liveCards: unknown[];\n liveGoalIndex: number | null;\n contextTokens: number;\n success: boolean;\n }> {\n const lid = String(loopId || \"\").trim();\n if (!lid) {\n return { goals: [], liveCards: [], liveGoalIndex: null, contextTokens: 0, success: false };\n }\n return this.withRpcLock(async () => {\n await this.ensureRpcConnected();\n try {\n const resp = await this.rpcClient.fetchLoopHistory(lid, 30_000);\n const liveGoalIndex = resp.live_goal_index;\n return {\n goals: Array.isArray(resp.goals) ? resp.goals : [],\n liveCards: Array.isArray(resp.live_cards) ? resp.live_cards : [],\n liveGoalIndex: typeof liveGoalIndex === \"number\" ? liveGoalIndex : null,\n contextTokens:\n typeof resp.context_tokens === \"number\" && resp.context_tokens >= 0\n ? resp.context_tokens\n : 0,\n success: Boolean(resp.success ?? true),\n };\n } catch {\n return {\n goals: [],\n liveCards: [],\n liveGoalIndex: null,\n contextTokens: 0,\n success: false,\n };\n }\n });\n }\n\n async fetchConversationLog(\n loopId: string,\n opts: { limit?: number; offset?: number; includeEvents?: boolean } = {},\n ): Promise<Record<string, unknown>[]> {\n const lid = String(loopId || \"\").trim();\n if (!lid) return [];\n return this.withRpcLock(async () => {\n await this.ensureRpcConnected();\n const resp = await this.rpcClient.getLoopMessages(\n lid,\n opts.limit ?? 100,\n opts.offset ?? 0,\n opts.includeEvents ?? false,\n );\n const raw = resp.messages;\n if (!Array.isArray(raw)) return [];\n return raw.filter((m): m is Record<string, unknown> => !!m && typeof m === \"object\");\n });\n }\n\n async *iterTurnChunks(opts: { maxWaitMs?: number } = {}): AsyncGenerator<TurnChunk> {\n this.turnEventStats = this.statsFactory();\n this.lastTurnEndState = null;\n this.lastTurnCancellationSeen = false;\n this.lastTurnErrorMessage = null;\n\n let queryStarted = false;\n let expectedLoopId = this.loopId;\n let streamPayloadSeen = false;\n let turnProgressSeen = false;\n this.streaming = true;\n const absoluteDeadline =\n opts.maxWaitMs !== undefined && opts.maxWaitMs > 0 ? Date.now() + opts.maxWaitMs : null;\n\n this.client.peelStalePendingControlEvents();\n\n while (this.readBusy) {\n await new Promise(r => setTimeout(r, 5));\n }\n this.readBusy = true;\n try {\n while (true) {\n if (absoluteDeadline !== null && Date.now() >= absoluteDeadline) {\n throw new Error(\n `Turn timed out after ${opts.maxWaitMs}ms (loop=${expectedLoopId ?? \"?\"})`,\n );\n }\n const event = await this.client.readEvent();\n if (!event) {\n if (queryStarted && !this.client.isConnectionAlive()) {\n this.lastTurnEndState = \"connection_lost\";\n throw new Error(\"Daemon connection lost\");\n }\n break;\n }\n\n let frame: Record<string, unknown> = event;\n let eventType = String(frame.type ?? \"\");\n if (eventType === \"next\") {\n frame = unwrapNext(frame) ?? frame;\n eventType = String(frame.type ?? \"\");\n }\n\n const eventLoopId = frame.loop_id;\n if (\n expectedLoopId &&\n typeof eventLoopId === \"string\" &&\n eventLoopId &&\n eventLoopId !== expectedLoopId\n ) {\n continue;\n }\n\n if (eventType === \"error\") {\n const errObj = (frame.error as { message?: string }) ?? {};\n throw new Error(String(errObj.message || frame.message || \"daemon error\"));\n }\n\n if (eventType === \"status\") {\n const loopEv = frame.loop_id;\n if (typeof loopEv === \"string\" && loopEv) {\n this.loopId = loopEv;\n expectedLoopId = loopEv;\n }\n const state = String(frame.state ?? \"\");\n if (state === \"running\") {\n queryStarted = true;\n } else if (queryStarted && state === \"stopped\") {\n this.lastTurnEndState = state;\n yield* this.drainStreamEventsAfterIdle(expectedLoopId);\n break;\n } else if (queryStarted && state === \"idle\") {\n if (!streamPayloadSeen && !this.lastTurnCancellationSeen) continue;\n this.lastTurnEndState = state;\n yield* this.drainStreamEventsAfterIdle(expectedLoopId);\n break;\n }\n continue;\n }\n\n if (eventType === \"command_response\") {\n const content = String(frame.content ?? \"\");\n if (content.includes(\"Cancellation requested\")) {\n this.lastTurnCancellationSeen = true;\n }\n continue;\n }\n\n if (eventType !== \"event\") continue;\n\n const data = frame.data;\n const namespace = Array.isArray(frame.namespace) ? (frame.namespace as unknown[]) : [];\n const mode = String(frame.mode ?? \"\");\n if (this.shouldDrop(namespace, mode, data)) {\n this.turnEventStats.filteredEarly += 1;\n continue;\n }\n\n if (mode === \"custom\" && isTurnEndCustomData(data)) {\n if (!queryStarted || !turnProgressSeen) continue;\n }\n\n streamPayloadSeen = true;\n if (isTurnProgressChunk(mode, data)) turnProgressSeen = true;\n yield [namespace, mode, data];\n\n if (mode === \"custom\" && isTurnEndCustomData(data)) {\n const customType = String((data as Record<string, unknown>).type ?? \"\").trim();\n this.lastTurnEndState = customType === STREAM_END ? \"stream_end\" : \"completed\";\n yield* this.drainStreamEventsAfterIdle(expectedLoopId);\n break;\n }\n }\n } catch (exc) {\n this.lastTurnErrorMessage = String(exc);\n throw exc;\n } finally {\n this.streaming = false;\n this.readBusy = false;\n }\n }\n}\n","/**\n * Early filters for daemon stream chunks (wire / dict-shaped payloads).\n */\n\nconst MSG_PAIR_LEN = 2;\n\n/** True when an updates chunk carries no LangGraph interrupt. */\nexport function updatesChunkIsNoop(data: unknown): boolean {\n if (!data || typeof data !== \"object\") return true;\n return !(\"__interrupt__\" in (data as Record<string, unknown>));\n}\n\nfunction wireBody(msg: Record<string, unknown>): Record<string, unknown> {\n for (const key of [\"kwargs\", \"data\"] as const) {\n const nested = msg[key];\n if (nested && typeof nested === \"object\") return nested as Record<string, unknown>;\n }\n return msg;\n}\n\nfunction dictHasToolInvocation(msg: Record<string, unknown>): boolean {\n const body = wireBody(msg);\n if (body.tool_calls || body.tool_call_chunks) return true;\n for (const key of [\"content\", \"content_blocks\"] as const) {\n const raw = body[key];\n if (Array.isArray(raw)) {\n for (const item of raw) {\n if (\n item &&\n typeof item === \"object\" &&\n [\"tool_call\", \"tool_call_chunk\", \"tool_use\"].includes(\n String((item as Record<string, unknown>).type ?? \"\"),\n )\n ) {\n return true;\n }\n }\n }\n }\n return false;\n}\n\nfunction plainText(msg: Record<string, unknown>): string {\n const body = wireBody(msg);\n const content = body.content ?? msg.content;\n if (typeof content === \"string\") return content;\n if (Array.isArray(content)) {\n const parts: string[] = [];\n for (const block of content) {\n if (typeof block === \"string\") parts.push(block);\n else if (block && typeof block === \"object\") {\n const text = (block as Record<string, unknown>).text;\n if (typeof text === \"string\") parts.push(text);\n }\n }\n return parts.join(\"\");\n }\n return \"\";\n}\n\n/** True when a wire messages pair has no tool, text, or loop phase payload. */\nexport function messageChunkIsNonActionable(data: unknown): boolean {\n if (!Array.isArray(data) || data.length !== MSG_PAIR_LEN) return false;\n const msg = data[0];\n if (msg === null || msg === undefined) return true;\n if (!msg || typeof msg !== \"object\") return false;\n const m = msg as Record<string, unknown>;\n const body = wireBody(m);\n const raw = String(body.type ?? m.type ?? \"\");\n if (raw === \"tool\" || raw === \"ToolMessage\" || raw.endsWith(\"ToolMessage\")) return false;\n if (dictHasToolInvocation(m)) return false;\n if (body.phase || m.phase) return false;\n return !plainText(m).trim();\n}\n\n/** Return true when the chunk can be skipped before the turn pipeline. */\nexport function shouldDropStreamChunkEarly(\n _namespace: unknown[],\n mode: string,\n data: unknown,\n): boolean {\n if (mode === \"updates\") return updatesChunkIsNoop(data);\n if (mode === \"messages\") return messageChunkIsNonActionable(data);\n return false;\n}\n","/**\n * Protocol-1 streaming frame helpers for application loops.\n */\n\n/** Unwrap a protocol-1 next envelope to its inner streaming frame. */\nexport function unwrapNext(\n event: Record<string, unknown> | null | undefined,\n): Record<string, unknown> | null | undefined {\n if (!event || typeof event !== \"object\") return event;\n if (event.type !== \"next\") return event;\n const payload = event.payload;\n if (!payload || typeof payload !== \"object\") return event;\n const data = (payload as Record<string, unknown>).data;\n return data && typeof data === \"object\" ? (data as Record<string, unknown>) : event;\n}\n\n/**\n * Return whether a daemon frame belongs to the active StrangeLoop session.\n */\nexport function isLoopScopedEvent(event: Record<string, unknown>, activeLoopId: string): boolean {\n let eventType = String(event.type ?? \"\");\n let frame = event;\n if (eventType === \"next\") {\n const inner = unwrapNext(event);\n if (inner && typeof inner === \"object\") {\n frame = inner;\n eventType = String(inner.type ?? \"\");\n return eventType !== \"status\" && eventType !== \"event\"\n ? true\n : String(inner.loop_id ?? \"\") === activeLoopId;\n }\n }\n if (eventType !== \"status\" && eventType !== \"event\") return true;\n return String(frame.loop_id ?? \"\") === activeLoopId;\n}\n","/**\n * Per-turn observability counters for daemon stream consumption.\n */\n\nexport class TurnEventStats {\n total = 0;\n messages = 0;\n updates = 0;\n custom = 0;\n skipped = 0;\n filteredEarly = 0;\n toolCalls = 0;\n toolResults = 0;\n textChunks = 0;\n heartbeatsDropped = 0;\n postIdleDrained = 0;\n inboundDropped = 0;\n}\n"],"mappings":"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","names":["DisconnectCause","VerbosityTier","WebSocket","msg","Client","ChatEventTerminal","dataType","dt","buf","TimeoutPolicy","res"]}
|