@mirasoth/soothe-client 0.5.4 → 0.5.7

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.
@@ -1599,10 +1599,6 @@ var Client = class extends EventEmitter {
1599
1599
  if (asNode) params.as_node = asNode;
1600
1600
  return this.sendMessage(requestEnvelope("loop_state_update", params));
1601
1601
  }
1602
- /** Requests display card ledger snapshot. */
1603
- sendLoopCardsFetch(loopID) {
1604
- return this.sendMessage(requestEnvelope("loop_cards_fetch", { loop_id: loopID }));
1605
- }
1606
1602
  /** Requests the full loop history. */
1607
1603
  sendLoopHistoryFetch(loopID) {
1608
1604
  return this.sendMessage(requestEnvelope("loop_history_fetch", { loop_id: loopID }));
@@ -1653,15 +1649,6 @@ var Client = class extends EventEmitter {
1653
1649
  timeout ?? 15e3
1654
1650
  );
1655
1651
  }
1656
- /** Requests display cards and waits for response. */
1657
- fetchLoopCards(loopID, timeout) {
1658
- return this.requestResponse(
1659
- "loop_cards_fetch",
1660
- { loop_id: loopID },
1661
- "loop_cards_fetch",
1662
- timeout ?? 15e3
1663
- );
1664
- }
1665
1652
  /** Requests MCP status and waits for response. */
1666
1653
  getMCPStatus(timeout) {
1667
1654
  return this.requestResponse("mcp_status", {}, "mcp_status", timeout ?? 15e3);
@@ -1825,6 +1812,16 @@ var Client = class extends EventEmitter {
1825
1812
  timeout ?? 15e3
1826
1813
  );
1827
1814
  }
1815
+ /** Jobs → goals → loops snapshot for CLI top. */
1816
+ autopilotTop(timeoutOrOptions) {
1817
+ const options = typeof timeoutOrOptions === "number" ? { timeout: timeoutOrOptions } : timeoutOrOptions;
1818
+ return this.requestResponse(
1819
+ "autopilot_top",
1820
+ { include_terminal: options?.includeTerminal ?? false },
1821
+ "autopilot_top",
1822
+ options?.timeout ?? 15e3
1823
+ );
1824
+ }
1828
1825
  /** Subscribes to autopilot worker events. */
1829
1826
  autopilotSubscribe(timeout) {
1830
1827
  return this.subscribe("autopilot_events", {}, timeout ?? 15e3);
@@ -1978,4 +1975,4 @@ export {
1978
1975
  inboundNeedsDeliveryAck,
1979
1976
  Client
1980
1977
  };
1981
- //# sourceMappingURL=chunk-B5FIL7O4.js.map
1978
+ //# sourceMappingURL=chunk-56Z7SUGW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client.ts","../src/config.ts","../src/errors.ts","../src/multiplexer.ts","../src/intent_hints.ts","../src/verbosity.ts","../src/events.ts","../src/stream_terminal.ts","../src/inbound_priority.ts","../src/protocol.ts"],"sourcesContent":["/**\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 intent_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 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 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 /** Jobs → goals → loops snapshot for CLI top. */\n autopilotTop(\n timeoutOrOptions?: number | { includeTerminal?: boolean; timeout?: number },\n ): Promise<Record<string, unknown>> {\n const options =\n typeof timeoutOrOptions === \"number\"\n ? { timeout: timeoutOrOptions }\n : timeoutOrOptions;\n return this.requestResponse(\n \"autopilot_top\",\n { include_terminal: options?.includeTerminal ?? false },\n \"autopilot_top\",\n options?.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 * 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 * 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 * 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 * Daemon ``loop_input`` intent_hint values (non-agent turns).\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 intent_hint values for non-agent turns. */\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\", \"direct_model\"] 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 direct_model:\n \"intent_hint direct_model is removed; use text_completion, image_to_text, ocr, or embed\",\n};\n\n/**\n * Wire ``loop_input.intent_hint``: intent-hint values or agent-path pass-through\n * (e.g. ``resume_clarification``, ``skill:foo``). Legacy ``direct_llm``, ``quiz``,\n * and ``direct_model`` 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() as RemovedIntentHint;\n if (key in REMOVED_INTENT_HINT_MESSAGES) {\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 \"chitchat\",\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 (intent hints + agent outputs). */\nexport const DEFAULT_DELIVERABLE_PHASES: ReadonlySet<string> = new Set([\n \"quiz\",\n \"goal_completion\",\n \"chitchat\",\n \"text_completion\",\n \"image_to_text\",\n \"ocr\",\n \"embed\",\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-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// Deep research subagent events\nexport const EventDeepResearchStarted = \"soothe.subagent.deep_research.started\";\nexport const EventDeepResearchProgress = \"soothe.subagent.deep_research.progress\";\nexport const EventDeepResearchStepCompleted = \"soothe.subagent.deep_research.step.completed\";\nexport const EventDeepResearchGatherSummary = \"soothe.subagent.deep_research.gather.summary\";\nexport const EventDeepResearchCrawlSummary = \"soothe.subagent.deep_research.crawl.summary\";\nexport const EventDeepResearchCompleted = \"soothe.subagent.deep_research.completed\";\n\n// Control-plane wire envelopes (not soothe.* catalog events)\nexport const EventReplayComplete = \"replay_complete\";\nexport const EventLoopReattachedWire = \"loop_reattached\";\n\n// Display card ledger frames (UI source of truth)\nexport const EventCardCreated = \"soothe.card.created\";\nexport const EventCardUpdated = \"soothe.card.updated\";\nexport const EventCardFinalized = \"soothe.card.finalized\";\nexport const EventCardReplayBegin = \"soothe.card.replay.begin\";\nexport const EventCardReplayEnd = \"soothe.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 * 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 EventCardFinalized,\n EventCardReplayBegin,\n EventCardReplayEnd,\n EventCardUpdated,\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 EventCardCreated,\n EventCardUpdated,\n EventCardFinalized,\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 * 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.5.3\";\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_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 | \"autopilot_top\"\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"],"mappings":";AAQA,SAAS,oBAAoB;AAC7B,OAAO,eAAe;;;AC2Bf,SAAS,gBAAwB;AACtC,SAAO;AAAA,IACL,WAAW;AAAA,IACX,gBAAgB;AAAA,IAChB,YAAY;AAAA,IACZ,gBAAgB;AAAA,IAChB,mBAAmB;AAAA,IACnB,oBAAoB;AAAA,IACpB,mBAAmB;AAAA,IACnB,qBAAqB;AAAA,IAErB,sBAAsB;AAAA,IACtB,uBAAuB;AAAA,IACvB,mBAAmB;AAAA,IACnB,sBAAsB;AAAA,EACxB;AACF;AAGO,SAAS,oBAA4B;AAC1C,QAAM,SAAS,cAAc;AAE7B,MAAI,OAAO,YAAY,YAAa,QAAO;AAE3C,QAAM,MAAM,QAAQ,IAAI;AACxB,MAAI,IAAK,QAAO,YAAY;AAE5B,QAAM,YAAY,QAAQ,IAAI;AAC9B,MAAI,UAAW,QAAO,iBAAiB;AAEvC,QAAM,UAAU,QAAQ,IAAI;AAC5B,MAAI,SAAS;AACX,UAAM,MAAM,SAAS,SAAS,EAAE;AAChC,QAAI,CAAC,MAAM,GAAG,EAAG,QAAO,aAAa;AAAA,EACvC;AAEA,QAAM,eAAe,QAAQ,IAAI;AACjC,MAAI,cAAc;AAChB,UAAM,MAAM,SAAS,cAAc,EAAE;AACrC,QAAI,MAAM,EAAG,QAAO,qBAAqB,MAAM;AAAA,EACjD;AAEA,QAAM,gBAAgB,QAAQ,IAAI;AAClC,MAAI,eAAe;AACjB,UAAM,MAAM,SAAS,eAAe,EAAE;AACtC,QAAI,MAAM,EAAG,QAAO,oBAAoB,MAAM;AAAA,EAChD;AAEA,QAAM,aAAa,QAAQ,IAAI;AAC/B,MAAI,YAAY;AACd,UAAM,MAAM,SAAS,YAAY,EAAE;AACnC,QAAI,MAAM,EAAG,QAAO,sBAAsB,MAAM;AAAA,EAClD;AAEA,SAAO;AACT;;;ACtFO,IAAM,kBAAN,cAA8B,MAAM;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,KAAa,SAAiB,OAAc;AACtD,UAAM,uBAAuB,GAAG,aAAa,OAAO,MAAM,MAAM,OAAO,EAAE;AACzE,SAAK,OAAO;AACZ,SAAK,MAAM;AACX,SAAK,UAAU;AACf,SAAK,QAAQ;AAAA,EACf;AACF;AAQO,IAAM,cAAN,cAA0B,MAAM;AAAA;AAAA,EAE5B;AAAA;AAAA,EAEA;AAAA;AAAA,EAEA;AAAA,EAET,YAAY,MAAc,SAAiB,MAAgB;AACzD,UAAM,iBAAiB,IAAI,MAAM,OAAO,EAAE;AAC1C,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,SAAK,gBAAgB;AACrB,SAAK,OAAO;AAAA,EACd;AACF;AAGO,IAAM,eAAN,cAA2B,MAAM;AAAA,EAC7B;AAAA,EACA;AAAA,EAET,YAAY,WAAmB,UAAkB;AAC/C,UAAM,iBAAiB,QAAQ,gBAAgB,SAAS,EAAE;AAC1D,SAAK,OAAO;AACZ,SAAK,YAAY;AACjB,SAAK,WAAW;AAAA,EAClB;AACF;AAUO,IAAK,kBAAL,kBAAKA,qBAAL;AAEL,EAAAA,kCAAA,aAAU,KAAV;AAEA,EAAAA,kCAAA,WAAQ,KAAR;AAJU,SAAAA;AAAA,GAAA;AAQL,SAAS,oBAAoB,OAAgC;AAClE,SAAO,UAAU,gBAAwB,UAAU;AACrD;AAGO,IAAM,iBAAN,cAA6B,MAAM;AAAA,EAC/B;AAAA,EACA;AAAA,EACA;AAAA,EAET,YAAY,KAAa,UAAkB,OAAc;AACvD,UAAM,gBAAgB,GAAG,iBAAiB,QAAQ,cAAc,MAAM,OAAO,EAAE;AAC/E,SAAK,OAAO;AACZ,SAAK,MAAM;AACX,SAAK,WAAW;AAChB,SAAK,QAAQ;AAAA,EACf;AACF;AAOO,IAAM,iBAAN,cAA6B,MAAM;AAAA,EAC/B;AAAA,EACA;AAAA,EAET,YAAY,QAAgB,OAAe;AACzC,UAAM,SAAS,QAAQ,KAAK,MAAM,OAAO,KAAK;AAC9C,UAAM,cAAc,MAAM,gDAAgD,MAAM,EAAE;AAClF,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,QAAQ;AAAA,EACf;AACF;;;ACxDO,IAAM,cAAN,MAAkB;AAAA,EACf,OAAO,oBAAI,IAAyB;AAAA,EACpC,OAAO,oBAAI,IAAiC;AAAA,EAC5C,WAAW,oBAAI,IAAsD;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQ7E,YAAY,IAGV;AACA,QAAI;AACJ,QAAI;AACJ,UAAM,OAAO,IAAI,QAAiC,CAAC,SAAS,WAAW;AACrE,oBAAc;AACd,mBAAa;AAAA,IACf,CAAC;AACD,UAAM,UAAuB,EAAE,SAAS,aAAa,QAAQ,WAAW;AACxE,SAAK,KAAK,IAAI,IAAI,OAAO;AACzB,UAAM,aAAa,MAAM;AAGvB,UAAI,KAAK,KAAK,IAAI,EAAE,MAAM,SAAS;AACjC,aAAK,KAAK,OAAO,EAAE;AAAA,MACrB;AAAA,IACF;AACA,WAAO,EAAE,MAAM,WAAW;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,qBAAqB,IAInB;AACA,QAAI;AACJ,UAAM,OAAO,IAAI,QAAc,aAAW;AACxC,oBAAc;AAAA,IAChB,CAAC;AACD,UAAM,UAA+B;AAAA,MACnC,MAAM,MAAM;AAAA,MAEZ;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS;AAAA,IACX;AAGA,UAAM,OAAO,CAAC,UAAmC;AAC/C,UAAI,QAAQ,QAAS;AACrB,cAAQ,KAAK,KAAK;AAAA,IACpB;AAIA,YAAQ,OAAO,MAAM;AAAA,IAAC;AACtB,SAAK,KAAK,IAAI,IAAI,OAAO;AACzB,UAAM,aAAa,MAAM;AACvB,UAAI,KAAK,KAAK,IAAI,EAAE,MAAM,SAAS;AACjC,gBAAQ,UAAU;AAClB,aAAK,KAAK,OAAO,EAAE;AACnB,oBAAY;AAAA,MACd;AAAA,IACF;AACA,WAAO,EAAE,MAAM,MAAM,WAAW;AAAA,EAClC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gBAAgB,SAGd;AACA,QAAI;AACJ,UAAM,OAAO,IAAI,QAAiC,aAAW;AAC3D,oBAAc;AAAA,IAChB,CAAC;AACD,SAAK,SAAS,IAAI,SAAS,WAAW;AACtC,UAAM,aAAa,MAAM;AACvB,WAAK,SAAS,OAAO,OAAO;AAAA,IAC9B;AACA,WAAO,EAAE,MAAM,WAAW;AAAA,EAC5B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,oBAAoB,IAAY,MAAsD;AACpF,UAAM,MAAM,KAAK,KAAK,IAAI,EAAE;AAC5B,QAAI,IAAK,KAAI,OAAO;AAAA,EACtB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,OAAyC;AAC7C,QAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,UAAM,MAAM,MAAM;AAClB,UAAM,KAAK,MAAM;AAEjB,QAAI,QAAQ,cAAc,QAAQ,SAAS;AACzC,UAAI,CAAC,GAAI,QAAO;AAChB,YAAM,KAAK,KAAK,KAAK,IAAI,EAAE;AAC3B,UAAI,CAAC,GAAI,QAAO;AAChB,UAAI,QAAQ,SAAS;AACnB,cAAM,SACH,MAAM,SAID,CAAC;AACT,cAAM,OAAO,OAAO,OAAO,SAAS,WAAW,OAAO,OAAO;AAC7D,cAAM,UAAU,OAAO,WAAW;AAClC,WAAG,OAAO,IAAI,YAAY,MAAM,SAAS,OAAO,IAAI,CAAC;AAAA,MACvD,OAAO;AACL,cAAM,SAAU,MAAM,UAAkD;AACxE,WAAG,QAAQ,MAAM;AAAA,MACnB;AAEA,WAAK,KAAK,OAAO,EAAE;AACnB,aAAO;AAAA,IACT;AAEA,QAAI,QAAQ,UAAU,QAAQ,YAAY;AACxC,UAAI,CAAC,GAAI,QAAO;AAChB,YAAM,KAAK,KAAK,KAAK,IAAI,EAAE;AAC3B,UAAI,CAAC,GAAI,QAAO;AAChB,UAAI,GAAG,QAAS,QAAO;AACvB,SAAG,KAAK,KAAK;AACb,aAAO;AAAA,IACT;AAEA,QAAI,QAAQ,oBAAoB;AAC9B,YAAM,MAAM,MAAM;AAClB,UAAI,CAAC,IAAK,QAAO;AACjB,YAAM,KAAK,KAAK,SAAS,IAAI,GAAG;AAChC,UAAI,CAAC,GAAI,QAAO;AAChB,SAAG,KAAK;AACR,WAAK,SAAS,OAAO,GAAG;AACxB,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,aAAa,IAAqB;AAChC,WAAO,KAAK,KAAK,IAAI,EAAE;AAAA,EACzB;AACF;;;ACnNO,IAAM,8BAA8B;AAGpC,IAAM,4BAA4B;AAGlC,IAAM,kBAAkB;AAGxB,IAAM,oBAAoB;AAU1B,IAAM,uBAAuB,CAAC,cAAc,QAAQ,cAAc;AAIzE,IAAM,+BAAkE;AAAA,EACtE,YACE;AAAA,EACF,MAAM;AAAA,EACN,cACE;AACJ;AAUO,SAAS,4BAA4B,MAA6B;AACvE,QAAM,MAAM,KAAK,KAAK,EAAE,YAAY;AACpC,MAAI,OAAO,8BAA8B;AACvC,WAAO,6BAA6B,GAAG;AAAA,EACzC;AACA,SAAO;AACT;AAGO,IAAM,+BAA+B;AAAA,EAC1C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAKO,IAAM,6BAAkD,oBAAI,IAAI;AAAA,EACrE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;;;ACpEM,IAAK,gBAAL,kBAAKC,mBAAL;AAEL,EAAAA,8BAAA,WAAQ,KAAR;AAEA,EAAAA,8BAAA,YAAS,KAAT;AAEA,EAAAA,8BAAA,cAAW,KAAX;AAEA,EAAAA,8BAAA,WAAQ,KAAR;AAEA,EAAAA,8BAAA,cAAW,MAAX;AAVU,SAAAA;AAAA,GAAA;AAaZ,IAAM,uBAAuD;AAAA,EAC3D,OAAO;AAAA,EACP,QAAQ;AAAA,EACR,OAAO;AACT;AAGO,SAAS,WAAW,MAAqB,WAAoC;AAClF,MAAI,SAAS,mBAAwB;AACnC,WAAO;AAAA,EACT;AACA,QAAM,QAAQ,qBAAqB,SAAS,KAAK;AACjD,SAAO,QAAQ;AACjB;AAGO,SAAS,sBAAsB,GAAgC;AACpE,SAAO,KAAK;AACd;;;AC3BO,IAAM,mBAAmB;AAGzB,IAAM,2BAA2B;AACjC,IAAM,4BAA4B;AAClC,IAAM,iCAAiC;AACvC,IAAM,iCAAiC;AACvC,IAAM,gCAAgC;AACtC,IAAM,6BAA6B;AAGnC,IAAM,sBAAsB;AAC5B,IAAM,0BAA0B;AAGhC,IAAM,mBAAmB;AACzB,IAAM,mBAAmB;AACzB,IAAM,qBAAqB;AAC3B,IAAM,uBAAuB;AAC7B,IAAM,qBAAqB;AAG3B,IAAM,mBAAmB;AACzB,IAAM,qBAAqB;AAC3B,IAAM,iBAAiB;AAGvB,IAAM,4BAA4B;AAClC,IAAM,4BAA4B;AAGlC,IAAM,0BAA0B;AAChC,IAAM,4BAA4B;AAClC,IAAM,+BAA+B;AACrC,IAAM,2BAA2B;AACjC,IAAM,8BAA8B;AACpC,IAAM,6BAA6B;AACnC,IAAM,gCAAgC;AACtC,IAAM,mCAAmC;AAGzC,IAAM,uBAAuB;AAC7B,IAAM,mBAAmB;AAGzB,IAAM,mBAAmB;AAGzB,IAAM,2BAA2B;AACjC,IAAM,6BAA6B;AACnC,IAAM,4BAA4B;AAClC,IAAM,8BAA8B;AACpC,IAAM,+BAA+B;AACrC,IAAM,iCAAiC;AAGvC,IAAM,qBAAqB;AAO3B,SAAS,eACd,IAC8D;AAC9D,QAAM,QAAQ,eAAe,EAAE;AAC/B,MAAI,MAAM,SAAS,KAAK,MAAM,CAAC,MAAM,UAAU;AAC7C,WAAO;AAAA,EACT;AACA,MAAI,MAAM,CAAC,MAAM,YAAY;AAC3B,WAAO;AAAA,EACT;AACA,SAAO,EAAE,QAAQ,MAAM,CAAC,GAAG,WAAW,MAAM,CAAC,GAAG,QAAQ,MAAM,CAAC,EAAE;AACnE;AAEA,SAAS,eAAe,IAAsB;AAC5C,QAAM,QAAkB,CAAC;AACzB,MAAI,QAAQ;AACZ,WAAS,IAAI,GAAG,IAAI,GAAG,QAAQ,KAAK;AAClC,QAAI,GAAG,CAAC,MAAM,KAAK;AACjB,YAAM,KAAK,GAAG,MAAM,OAAO,CAAC,CAAC;AAC7B,cAAQ,IAAI;AAAA,IACd;AAAA,EACF;AACA,QAAM,KAAK,GAAG,MAAM,KAAK,CAAC;AAC1B,SAAO;AACT;AAOO,SAAS,uBAAuB,sBAA6C;AAClF,QAAM,SAAS,eAAe,oBAAoB;AAClD,MAAI,CAAC,QAAQ;AACX,WAAO,0BAA0B,oBAAoB;AAAA,EACvD;AACA,SAAO,6BAA6B,OAAO,QAAQ,OAAO,WAAW,oBAAoB;AAC3F;AAEA,SAAS,6BACP,QACA,YACA,MACe;AACf,UAAQ,QAAQ;AAAA,IACd,KAAK;AACH;AAAA,IACF,KAAK;AACH;AAAA,IACF,KAAK;AACH;AAAA,IACF,KAAK;AACH,aAAO,sBAAsB,IAAI;AAAA,IACnC,KAAK;AACH;AAAA,IACF,KAAK;AAAA,IACL,KAAK;AACH;AAAA,IACF;AACE;AAAA,EACJ;AACF;AAEA,SAAS,sBAAsB,MAA6B;AAC1D,QAAM,SAAS,eAAe,IAAI;AAClC,MAAI,CAAC,OAAQ;AACb,UAAQ,OAAO,QAAQ;AAAA,IACrB,KAAK;AAAA,IACL,KAAK;AACH;AAAA,IACF;AACE;AAAA,EACJ;AACF;AAEA,SAAS,0BAA0B,WAAkC;AACnE,MAAI,cAAc,oBAAoB,cAAc,oBAAoB;AACtE;AAAA,EACF;AACA,MAAI,cAAc,kBAAkB;AAClC;AAAA,EACF;AACA;AACF;AAOO,SAAS,kBAAkB,WAA4B;AAC5D,SACE,UAAU,SAAS,YAAY,KAC/B,UAAU,SAAS,SAAS,KAC5B,cAAc;AAElB;AAGO,SAAS,wBAAwB,WAA4B;AAClE,QAAM,SAAS,eAAe,SAAS;AACvC,MAAI,CAAC,UAAU,OAAO,WAAW,YAAY;AAC3C,WAAO;AAAA,EACT;AACA,SAAO,OAAO,WAAW,aAAa,OAAO,WAAW;AAC1D;;;AC/JO,IAAM,aAAa;AAEnB,IAAM,wBAA6C,oBAAI,IAAI;AAAA,EAChE;AAAA,EACA;AACF,CAAC;AAED,IAAM,6BAAkD,oBAAI,IAAI;AAAA,EAC9D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAGM,IAAM,2BAAgD,oBAAI,IAAI;AAAA,EACnE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAGM,SAAS,oBAAoB,MAAgD;AAClF,MAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;AAC9C,QAAM,aAAa,OAAQ,KAAiC,QAAQ,EAAE,EAAE,KAAK;AAC7E,MAAI,CAAC,sBAAsB,IAAI,UAAU,EAAG,QAAO;AACnD,MAAI,eAAe,YAAY;AAC7B,UAAM,QAAQ,OAAQ,KAAiC,SAAS,MAAM,EACnE,KAAK,EACL,YAAY;AACf,WAAO,UAAU,MAAM,UAAU;AAAA,EACnC;AACA,SAAO;AACT;AAOO,SAAS,oBAAoB,MAAc,MAAwB;AACxE,MAAI,SAAS,cAAc,SAAS,UAAW,QAAO;AACtD,MAAI,SAAS,YAAY,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;AACnE,MAAI,oBAAoB,IAAI,EAAG,QAAO;AACtC,QAAM,aAAa,OAAQ,KAAiC,QAAQ,EAAE,EAAE,KAAK;AAC7E,MAAI,2BAA2B,IAAI,UAAU,EAAG,QAAO;AACvD,MAAI,WAAW,WAAW,oCAAoC,EAAG,QAAO;AACxE,SAAO;AACT;AAGO,SAAS,uBAAuB,OAA+C;AACpF,QAAM,YAAY,OAAO,MAAM,QAAQ,EAAE;AACzC,MAAI,yBAAyB,IAAI,SAAS,EAAG,QAAO;AAEpD,MAAI,cAAc,QAAQ;AACxB,UAAM,UAAU,MAAM;AACtB,QAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AACpD,UAAM,IAAI;AACV,UAAM,YAAY,OAAO,EAAE,QAAQ,EAAE;AACrC,QAAI,yBAAyB,IAAI,SAAS,EAAG,QAAO;AACpD,UAAM,QAAQ,EAAE;AAChB,QAAI,SAAS,OAAO,UAAU,UAAU;AACtC,aAAO,uBAAuB,KAAgC;AAAA,IAChE;AACA,WAAO;AAAA,EACT;AAEA,MAAI,cAAc,SAAS;AACzB,UAAM,OAAO,OAAO,MAAM,QAAQ,EAAE;AACpC,UAAM,OAAO,MAAM;AACnB,QAAI,SAAS,YAAY,oBAAoB,IAAI,GAAG;AAClD,aAAO,OAAQ,KAAiC,QAAQ,EAAE,EAAE,KAAK;AAAA,IACnE;AAAA,EACF;AACA,SAAO;AACT;AAGO,SAAS,wBAAwB,OAAyC;AAC/E,QAAM,YAAY,OAAO,MAAM,QAAQ,EAAE;AACzC,MAAI,cAAc,WAAY,QAAO;AACrC,MAAI,cAAc,QAAQ;AACxB,UAAM,UAAU,MAAM;AACtB,QAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AACpD,UAAM,IAAI;AACV,UAAM,QAAQ,EAAE;AAChB,QAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAChD,QAAI,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS;AACpC,aAAO,8BAA8B,KAAgC;AAAA,IACvE;AACA,WAAO;AAAA,EACT;AACA,MAAI,cAAc,QAAS,QAAO,8BAA8B,KAAK;AACrE,SAAO;AACT;AAEA,SAAS,8BAA8B,OAAyC;AAC9E,QAAM,OAAO,OAAO,MAAM,QAAQ,EAAE;AACpC,QAAM,OAAO,MAAM;AACnB,MAAI,SAAS,YAAY,oBAAoB,IAAI,EAAG,QAAO;AAC3D,MAAI,SAAS,cAAc,MAAM,QAAQ,IAAI,KAAK,KAAK,SAAS,GAAG;AACjE,UAAM,OAAO,KAAK,CAAC;AACnB,QAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;AAC9C,UAAM,IAAI,OAAQ,KAAiC,QAAQ,EAAE;AAC7D,WAAO,MAAM,cAAc,EAAE,SAAS,YAAY;AAAA,EACpD;AACA,SAAO;AACT;AAGO,SAAS,yBAAyB,OAAwC;AAC/E,QAAM,SAAS,OAAO,MAAM,WAAW,EAAE,EAAE,KAAK;AAChD,MAAI,OAAQ,QAAO;AACnB,MAAI,OAAO,MAAM,QAAQ,EAAE,MAAM,OAAQ,QAAO;AAChD,QAAM,UAAU,MAAM;AACtB,MAAI,CAAC,WAAW,OAAO,YAAY,SAAU,QAAO;AACpD,QAAM,IAAI;AACV,QAAM,cAAc,OAAO,EAAE,WAAW,EAAE,EAAE,KAAK;AACjD,MAAI,YAAa,QAAO;AACxB,QAAM,QAAQ,EAAE;AAChB,MAAI,SAAS,OAAO,UAAU,UAAU;AACtC,WAAO,OAAQ,MAAkC,WAAW,EAAE,EAAE,KAAK;AAAA,EACvE;AACA,SAAO;AACT;;;ACjJO,IAAM,yBAAyB;AAC/B,IAAM,qBAAqB;AAC3B,IAAM,uBAAuB;AAG7B,IAAM,2BAA2B;AAGjC,SAAS,yBAAyB,OAA2D;AAClG,MAAI,CAAC,MAAO,QAAO;AACnB,MAAI,YAAY,OAAO,MAAM,QAAQ,EAAE;AACvC,MAAI,cAAc,iBAAiB,cAAc,2BAA2B;AAC1E,WAAO;AAAA,EACT;AACA,MAAI,cAAc,QAAQ;AACxB,UAAM,UAAU,MAAM;AACtB,QAAI,WAAW,OAAO,YAAY,UAAU;AAC1C,YAAM,IAAI;AACV,YAAM,YAAY,OAAO,EAAE,QAAQ,EAAE;AACrC,YAAM,YAAY,EAAE;AACpB,UAAI,cAAc,YAAY;AAC5B,YAAI,qBAAqB,SAAS,EAAG,QAAO;AAC5C,YAAI,MAAM,QAAQ,SAAS,KAAK,UAAU,CAAC,KAAK,OAAO,UAAU,CAAC,MAAM,UAAU;AAChF,cAAI,OAAQ,UAAU,CAAC,EAA8B,SAAS,EAAE,MAAM,mBAAmB;AACvF,mBAAO;AAAA,UACT;AAAA,QACF;AAAA,MACF;AACA,UAAI,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAY,QAAO;AAChD,UAAI,aAAa,OAAO,cAAc,UAAU;AAC9C,eAAO,yBAAyB,SAAoC;AAAA,MACtE;AACA,kBAAY,OAAO,EAAE,QAAQ,EAAE;AAAA,IACjC;AAAA,EACF;AACA,MAAI,cAAc,cAAc,cAAc,WAAW,cAAc,kBAAkB;AACvF,WAAO;AAAA,EACT;AACA,MAAI,cAAc,UAAU;AAC1B,UAAM,QAAQ,OAAO,MAAM,SAAS,EAAE;AACtC,QAAI,CAAC,QAAQ,WAAW,WAAW,UAAU,EAAE,SAAS,KAAK,GAAG;AAC9D,aAAO;AAAA,IACT;AAAA,EACF;AACA,MAAI,cAAc,SAAS;AACzB,UAAM,OAAO,OAAO,MAAM,QAAQ,EAAE;AACpC,UAAM,OAAO,MAAM;AACnB,QAAI,SAAS,UAAU;AACrB,UAAI,oBAAoB,IAAI,EAAG,QAAO;AACtC,UAAI,QAAQ,OAAO,SAAS,UAAU;AACpC,cAAM,aAAa,OAAQ,KAAiC,QAAQ,EAAE;AACtE,YAAI,WAAW,WAAW,mBAAmB,EAAG,QAAO;AACvD,YAAI,WAAW,WAAW,eAAe,KAAK,eAAe,mBAAmB;AAC9E,iBAAO;AAAA,QACT;AACA,YAAI,eAAe,sDAAsD;AACvE,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AACA,QAAI,SAAS,YAAY;AACvB,UAAI,qBAAqB,IAAI,EAAG,QAAO;AACvC,UAAI,MAAM,QAAQ,IAAI,KAAK,KAAK,CAAC,KAAK,OAAO,KAAK,CAAC,MAAM,UAAU;AACjE,YAAI,OAAQ,KAAK,CAAC,EAA8B,SAAS,EAAE,MAAM,mBAAmB;AAClF,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,qBAAqB,MAAwB;AACpD,MAAI,CAAC,MAAM,QAAQ,IAAI,KAAK,KAAK,WAAW,EAAG,QAAO;AACtD,QAAM,OAAO,KAAK,CAAC;AACnB,MAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;AAC9C,QAAM,IAAI,OAAQ,KAAiC,QAAQ,EAAE;AAC7D,SAAO,MAAM,cAAc,EAAE,SAAS,YAAY;AACpD;;;AC3EA,SAAS,kBAAkB;AAIpB,IAAM,gBAAgB;AAGtB,IAAM,8BAA8B,CAAC,aAAa,SAAS,aAAa,UAAU;AAGlF,IAAM,iBAAiB;AA6RvB,SAAS,cAAc,KAAsB;AAClD,SAAO,KAAK,UAAU,GAAG,IAAI;AAC/B;AAQO,SAAS,cAAc,MAAqC;AACjE,MAAI,CAAC,QAAQ,KAAK,WAAW,EAAG,QAAO;AAEvC,MAAI;AACJ,MAAI;AACF,aAAS,KAAK,MAAM,IAAI;AAAA,EAC1B,QAAQ;AACN,UAAM,IAAI,MAAM,iBAAiB,IAAI,EAAE;AAAA,EACzC;AAEA,MAAI,CAAC,UAAU,OAAO,WAAW,SAAU,QAAO;AAElD,QAAM,OAAO,OAAO;AACpB,MAAI,CAAC,KAAM,QAAO;AAElB,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO,EAAE,GAAG,OAAO;AAAA,IACrB,KAAK;AACH,aAAO,EAAE,GAAG,OAAO;AAAA,IACrB,KAAK;AACH,aAAO,EAAE,GAAG,OAAO;AAAA,IACrB,KAAK;AACH,aAAO,EAAE,GAAG,OAAO;AAAA,IACrB,KAAK;AACH,aAAO,EAAE,GAAG,OAAO;AAAA,IACrB,KAAK;AACH,aAAO,EAAE,GAAG,OAAO;AAAA,IACrB,KAAK;AACH,aAAO,EAAE,GAAG,OAAO;AAAA,IACrB,KAAK;AACH,aAAO,EAAE,GAAG,OAAO;AAAA,IACrB,KAAK;AACH,aAAO,EAAE,GAAG,OAAO;AAAA,IACrB,KAAK;AACH,aAAO,EAAE,GAAG,OAAO;AAAA,IACrB,KAAK;AACH,aAAO,EAAE,GAAG,OAAO;AAAA,IACrB,KAAK;AACH,aAAO,EAAE,GAAG,OAAO;AAAA,IACrB,KAAK;AACH,aAAO,EAAE,GAAG,OAAO;AAAA,IACrB,KAAK;AACH,aAAO,EAAE,GAAG,OAAO;AAAA,IACrB,KAAK;AACH,aAAO,EAAE,GAAG,OAAO;AAAA,IACrB;AACE,aAAO;AAAA,EACX;AACF;AAOO,SAAS,gBACd,QACA,QACA,IACiB;AACjB,SAAO;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA,IAAI,MAAM,aAAa;AAAA,EACzB;AACF;AAGO,SAAS,qBACd,QACA,QACsB;AACtB,SAAO,EAAE,OAAO,eAAe,MAAM,gBAAgB,QAAQ,OAAO;AACtE;AAGO,SAAS,kBACd,QACA,QACA,IACmB;AACnB,SAAO;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN;AAAA,IACA;AAAA,IACA,IAAI,MAAM,aAAa;AAAA,EACzB;AACF;AAGO,SAAS,oBAAoB,IAAiC;AACnE,SAAO,EAAE,OAAO,eAAe,MAAM,eAAe,GAAG;AACzD;AAGO,SAAS,uBAAuB,MAKZ;AACzB,SAAO;AAAA,IACL,OAAO;AAAA,IACP,MAAM;AAAA,IACN,QAAQ;AAAA,MACN,gBAAgB,MAAM,kBAAkB;AAAA,MACxC,aAAa,MAAM,eAAe;AAAA,MAClC,cAAc,MAAM,gBAAgB,CAAC,aAAa;AAAA,MAClD,cAAc,MAAM,gBAAgB;AAAA,IACtC;AAAA,EACF;AACF;AAGO,SAAS,eAA6B;AAC3C,SAAO,EAAE,OAAO,eAAe,MAAM,OAAO;AAC9C;AAGO,SAAS,eAA6B;AAC3C,SAAO,EAAE,OAAO,eAAe,MAAM,OAAO;AAC9C;AAGO,SAAS,qBAAyC;AACvD,SAAO,EAAE,OAAO,eAAe,MAAM,aAAa;AACpD;AAOO,SAAS,iBAAiB,MAAwB;AACvD,QAAM,UAAU,KAAK,KAAK;AAC1B,MAAI,YAAY,GAAI,QAAO,CAAC;AAE5B,QAAM,QAAQ,QACX,MAAM,IAAI,EACV,IAAI,OAAK,EAAE,KAAK,CAAC,EACjB,OAAO,OAAK,MAAM,EAAE;AACvB,SAAO,MAAM,SAAS,IAAI,QAAQ,CAAC,IAAI;AACzC;AAcO,SAAS,oBAAoB,KAAiC;AACnE,MAAI,CAAC,OAAO,OAAO,QAAQ,SAAU,QAAO,CAAC,IAAI,KAAK;AACtD,QAAM,IAAI;AAGV,MAAI,EAAE,SAAS,QAAQ;AACrB,UAAM,UAAU,EAAE;AAClB,QAAI,WAAW,OAAO,YAAY,UAAU;AAC1C,YAAM,OAAO,QAAQ;AACrB,UAAI,QAAQ,OAAO,SAAS,UAAU;AACpC,cAAM,KAAK,KAAK;AAChB,YAAI,MAAM,OAAO,GAAI,QAAO,CAAC,IAAI,IAAI;AAAA,MACvC;AAEA,YAAM,MAAM,QAAQ;AACpB,UAAI,OAAO,QAAQ,GAAI,QAAO,CAAC,KAAK,IAAI;AAAA,IAC1C;AACA,WAAO,CAAC,IAAI,KAAK;AAAA,EACnB;AAEA,MAAI,EAAE,SAAS,UAAU;AACvB,UAAM,KAAK,EAAE;AACb,QAAI,MAAM,OAAO,GAAI,QAAO,CAAC,IAAI,IAAI;AACrC,WAAO,CAAC,IAAI,KAAK;AAAA,EACnB;AAGA,QAAM,UAAU,EAAE;AAClB,MAAI,WAAW,YAAY,GAAI,QAAO,CAAC,SAAS,IAAI;AAEpD,SAAO,CAAC,IAAI,KAAK;AACnB;AAMO,SAAS,eAAuB;AACrC,SAAO,WAAW;AACpB;AAGO,SAAS,oBAAoB,QAAgB,SAAuC;AACzF,SAAO,qBAAqB,cAAc;AAAA,IACxC,SAAS;AAAA,IACT;AAAA,IACA,YAAY;AAAA,EACd,CAAC;AACH;AAGO,SAAS,kBAAkB,MAAiD;AACjF,QAAM,UACJ,OAAO,SAAS,WAAW,EAAE,kBAAkB,KAAK,IAAK,QAAQ,CAAC;AACpE,QAAM,kBAAkB,QAAQ,oBAAoB,QAAQ;AAC5D,QAAM,SAAkC,CAAC;AACzC,MAAI,iBAAiB,KAAK,GAAG;AAC3B,WAAO,mBAAmB,gBAAgB,KAAK;AAAA,EACjD;AACA,MAAI,QAAQ,SAAS,KAAK,GAAG;AAC3B,WAAO,UAAU,QAAQ,QAAQ,KAAK;AAAA,EACxC;AACA,MAAI,QAAQ,qBAAqB,KAAK,GAAG;AACvC,WAAO,sBAAsB,QAAQ,oBAAoB,KAAK;AAAA,EAChE;AACA,MAAI,QAAQ,cAAc;AACxB,WAAO,eAAe;AAAA,EACxB;AACA,SAAO,gBAAgB,YAAY,MAAM;AAC3C;AAGO,SAAS,wBACd,QACA,WACA,gBACmB;AACnB,QAAM,SAAkC,EAAE,SAAS,QAAQ,UAAU;AACrE,MAAI,gBAAgB;AAClB,WAAO,kBAAkB;AAAA,EAC3B;AACA,SAAO,kBAAkB,eAAe,MAAM;AAChD;;;ATjeO,IAAM,SAAN,cAAqB,aAAa;AAAA,EAC/B;AAAA,EACA;AAAA,EACA,KAAuB;AAAA,EACvB,gBAAkC,CAAC;AAAA,EACnC,iBAAiB;AAAA,EACjB,sBAAsB;AAAA,EACtB,mBAAuE;AAAA,EACvE,YAA2D,CAAC;AAAA;AAAA,EAE5D,oBAAoB;AAAA,EACpB,yBAAiD,oBAAI,IAAI;AAAA,EACzD,kBAAiC;AAAA,EACjC,iBAAgC;AAAA,EAChC,sBAAsB;AAAA,EACtB,iBAAwC;AAAA,EACxC,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA,EAKpB,eAAe;AAAA;AAAA;AAAA,EAGf,MAAM,IAAI,YAAY;AAAA,EACtB,kBAAkB,oBAAI,IAAoB;AAAA,EAC1C,mBAAmB,oBAAI,IAAoB;AAAA,EAEnD,YAAY,KAAa,QAAiB;AACxC,UAAM;AACN,SAAK,MAAM;AACX,SAAK,SAAS,UAAU,cAAc;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,UAAyB;AACvB,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,YAAM,KAAK,IAAI,UAAU,KAAK,KAAK;AAAA,QACjC,kBAAkB;AAAA,MACpB,CAAC;AAED,SAAG,GAAG,QAAQ,MAAM;AAClB,aAAK,KAAK;AAGV,aAAK,eAAe;AACpB,aAAK,aAAa;AAClB,aAAK,MAAM,IAAI,YAAY;AAE3B,aAAK,kBAAkB,EACpB,KAAK,SAAO;AACX,eAAK,oBAAoB;AACzB,eAAK,iBAAiB,IAAI,QAAQ,mBAAmB;AACrD,eAAK,gBAAgB;AACrB,kBAAQ;AAAA,QACV,CAAC,EACA,MAAM,SAAO;AAGZ,eAAK,eAAe;AACpB,eAAK,KAAK;AACV,eAAK,oBAAoB;AACzB,cAAI;AACF,eAAG,MAAM,MAAM,kBAAkB;AAAA,UACnC,QAAQ;AAAA,UAER;AACA,iBAAO,GAAG;AAAA,QACZ,CAAC;AAAA,MACL,CAAC;AAED,SAAG,GAAG,SAAS,SAAO;AAIpB,aAAK,iCAAyC;AAC9C,YAAI,CAAC,KAAK,IAAI;AACZ,iBAAO,IAAI,MAAM,gBAAgB,IAAI,OAAO,EAAE,CAAC;AAAA,QACjD;AAAA,MACF,CAAC;AAED,SAAG,GAAG,WAAW,CAAC,SAA4B;AAC5C,cAAM,OAAO,KAAK,SAAS;AAC3B,mBAAW,SAAS,iBAAiB,IAAI,GAAG;AAC1C,cAAI;AACJ,cAAI;AACF,kBAAM,cAAc,KAAK;AAAA,UAC3B,QAAQ;AACN;AAAA,UACF;AACA,cAAI,QAAQ,KAAM;AAGlB,gBAAM,IAAI;AACV,cAAI,EAAE,SAAS,QAAQ;AACrB,iBAAK,SAAS,aAAa,CAAC;AAC5B;AAAA,UACF;AACA,cAAI,EAAE,SAAS,QAAQ;AACrB,iBAAK,oBAAoB,KAAK,IAAI;AAClC;AAAA,UACF;AAGA,cAAI,EAAE,SAAS,cAAc;AAC3B,iBAAK,+BAAuC;AAAA,UAE9C;AAKA,cAAI,KAAK,IAAI,MAAM,CAAC,GAAG;AACrB,iBAAK,yBAAyB,CAAC;AAC/B;AAAA,UACF;AAEA,eAAK,yBAAyB,CAAC;AAK/B,gBAAM,WAAW,KAAK,UAAU,MAAM;AACtC,cAAI,UAAU;AACZ,qBAAS,GAAG;AAAA,UACd,OAAO;AACL,iBAAK,qBAAqB,GAAG;AAAA,UAC/B;AACA,eAAK,KAAK,WAAW,GAAG;AAAA,QAC1B;AAAA,MACF,CAAC;AAED,SAAG,GAAG,SAAS,MAAM;AACnB,aAAK,KAAK;AACV,aAAK,eAAe;AACpB,aAAK,oBAAoB;AAGzB,aAAK,iCAAyC;AAC9C,aAAK,KAAK,OAAO;AAEjB,mBAAW,YAAY,KAAK,WAAW;AACrC,mBAAS,IAAI;AAAA,QACf;AACA,aAAK,YAAY,CAAC;AAAA,MACpB,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,QAAc;AACZ,SAAK,eAAe;AACpB,QAAI,CAAC,KAAK,GAAI;AACd,QAAI;AAEF,UAAI,KAAK,GAAG,eAAe,UAAU,MAAM;AACzC,aAAK,GAAG,KAAK,KAAK,UAAU,mBAAmB,CAAC,CAAC;AAAA,MACnD;AACA,WAAK,GAAG,MAAM,KAAM,EAAE;AAAA,IACxB,QAAQ;AAAA,IAER;AACA,SAAK,KAAK;AACV,SAAK,oBAAoB;AAAA,EAC3B;AAAA;AAAA,EAGA,cAAuB;AACrB,WAAO,KAAK,OAAO,QAAQ,KAAK,GAAG,eAAe,UAAU,QAAQ,KAAK;AAAA,EAC3E;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,iBAA0B;AACxB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,kBAA0C;AACxC,QAAI,CAAC,KAAK,aAAc,QAAO;AAC/B,WAAO,KAAK;AAAA,EACd;AAAA,EAEQ,aAAqC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOrC,kBAAkB,OAA8B;AACtD,QAAI,KAAK,aAAc;AACvB,SAAK,eAAe;AACpB,SAAK,aAAa;AAKlB,QAAI;AACF,WAAK,KAAK,gBAAgB,KAAK;AAAA,IACjC,QAAQ;AAAA,IAER;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,MAAM,YAA2B;AAC/B,UAAM,cAAc,KAAK,OAAO,wBAAwB;AACxD,UAAM,eAAe,KAAK,OAAO,yBAAyB;AAC1D,UAAM,WAAW,KAAK,OAAO,qBAAqB;AAElD,QAAI,UAAwB;AAC5B,QAAI,QAAQ;AACZ,aAAS,UAAU,GAAG,WAAW,aAAa,WAAW;AACvD,UAAI;AAGF,cAAM,KAAK,QAAQ;AACnB;AAAA,MACF,SAAS,KAAK;AACZ,kBAAU;AAAA,MACZ;AACA,UAAI,UAAU,aAAa;AACzB,cAAM,IAAI,QAAQ,aAAW,WAAW,SAAS,KAAK,CAAC;AACvD,gBAAQ,KAAK,IAAI,QAAQ,GAAG,QAAQ;AAAA,MACtC;AAAA,IACF;AACA,UAAM,IAAI,eAAe,KAAK,KAAK,aAAa,WAAW,IAAI,MAAM,eAAe,CAAC;AAAA,EACvF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,iBAAiB,QAA+B;AACpD,QAAI,CAAC,UAAU,CAAC,OAAO,KAAK,GAAG;AAC7B,YAAM,IAAI,MAAM,6CAA6C;AAAA,IAC/D;AACA,UAAM,MAAM,OAAO,KAAK;AAGxB,UAAM,kBAAkB,KAAK,OAAO,qBAAqB;AACzD,QAAI;AACF,YAAM,KAAK;AAAA,QACT;AAAA,QACA,EAAE,SAAS,IAAI;AAAA,QACf;AAAA,QACA;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,IAAI,MAAM,kBAAmB,IAAc,OAAO,EAAE;AAAA,IAC5D;AAIA,UAAM,aAAa,KAAK,OAAO,uBAAuB;AACtD,QAAI;AACF,YAAM,KAAK;AAAA,QACT;AAAA,QACA,EAAE,SAAS,KAAK,WAAW,KAAK,OAAO,eAAe;AAAA,QACtD;AAAA,MACF;AAAA,IACF,SAAS,KAAK;AACZ,YAAM,IAAI,MAAM,oCAAqC,IAAc,OAAO,EAAE;AAAA,IAC9E;AAKA,UAAM,eAAe,KAAK,OAAO,wBAAwB;AACzD,QAAI;AACF,YAAM,KAAK,QAAQ,KAAK,YAAY;AAAA,IACtC,SAAS,KAAK;AACZ,UAAI,eAAe,eAAe,IAAI,SAAS,QAAQ;AACrD,cAAM,IAAI,eAAe,KAAK,GAAG;AAAA,MACnC;AAEA,YAAM,IAAI,eAAe,KAAK,GAAY;AAAA,IAC5C;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAc,oBAAoD;AAChE,UAAM,OAAO,uBAAuB;AAAA,MAClC,gBAAgB;AAAA,MAChB,aAAa;AAAA,MACb,cAAc,CAAC,aAAa;AAAA,MAC5B,cAAc;AAAA,IAChB,CAAC;AACD,UAAM,KAAK,YAAY,IAAI;AAE3B,UAAM,WAAW,KAAK,IAAI,IAAI,KAAK,OAAO;AAC1C,WAAO,KAAK,IAAI,IAAI,UAAU;AAC5B,YAAM,YAAY,WAAW,KAAK,IAAI;AACtC,UAAI,aAAa,EAAG;AACpB,YAAM,KAAM,MAAM,KAAK,qBAAqB,SAAS;AACrD,UAAI,OAAO,MAAM;AACf,cAAM,IAAI,MAAM,oCAAoC;AAAA,MACtD;AAEA,UAAI,GAAG,SAAS,UAAU;AACxB;AAAA,MACF;AACA,UAAI,GAAG,SAAS,kBAAkB;AAChC;AAAA,MACF;AACA,YAAM,MAAM;AACZ,YAAM,SAAS,IAAI,UAAU,CAAC;AAC9B,YAAM,QAAQ,OAAO,mBAAmB;AACxC,WAAK,kBAAkB,OAAO,oBAAoB;AAClD,WAAK,yBAAyB,IAAI,IAAI,OAAO,gBAAgB,CAAC,CAAC;AAC/D,WAAK,sBAAsB,OAAO,yBAAyB;AAE3D,UAAI,UAAU,gBAAgB;AAC5B,cAAM,IAAI,MAAM,kDAAkD,KAAK,eAAe,EAAE;AAAA,MAC1F;AACA,UAAI,UAAU,SAAS;AACrB,eAAO;AAAA,MACT;AACA,UAAI,UAAU,SAAS;AACrB,cAAM,IAAI,MAAM,uBAAuB;AAAA,MACzC;AACA,UAAI,UAAU,YAAY;AACxB,cAAM,IAAI,MAAM,oBAAoB;AAAA,MACtC;AAEA,YAAM,KAAK,OAAO,EAAE;AACpB,YAAM,KAAK,YAAY,IAAI;AAAA,IAC7B;AACA,UAAM,IAAI,MAAM,iBAAiB,KAAK,OAAO,kBAAkB,+BAA+B;AAAA,EAChG;AAAA;AAAA;AAAA;AAAA,EAMQ,kBAAwB;AAC9B,QAAI,CAAC,KAAK,uBAAuB,IAAI,WAAW,EAAG;AACnD,UAAM,WAAW,KAAK;AACtB,QAAI,YAAY,EAAG;AACnB,SAAK,oBAAoB,KAAK,IAAI;AAClC,SAAK,iBAAiB,YAAY,MAAM,KAAK,eAAe,QAAQ,GAAG,QAAQ;AAAA,EACjF;AAAA,EAEQ,iBAAuB;AAC7B,QAAI,KAAK,gBAAgB;AACvB,oBAAc,KAAK,cAAc;AACjC,WAAK,iBAAiB;AAAA,IACxB;AAAA,EACF;AAAA,EAEQ,eAAe,YAA0B;AAC/C,QAAI,CAAC,KAAK,MAAM,KAAK,GAAG,eAAe,UAAU,KAAM;AACvD,UAAM,YAAY,KAAK,IAAI,KAAQ,aAAa,CAAC;AACjD,UAAM,MAAM,KAAK,IAAI;AACrB,QAAI,OAAO,KAAK,qBAAqB,OAAO,aAAa,WAAW;AAGlE,WAAK,iCAAyC;AAC9C,UAAI;AACF,aAAK,GAAG,MAAM,MAAM,mBAAmB;AAAA,MACzC,QAAQ;AAAA,MAER;AACA;AAAA,IACF;AACA,QAAI;AACF,WAAK,GAAG,KAAK,KAAK,UAAU,aAAa,CAAC,CAAC;AAAA,IAC7C,QAAQ;AAAA,IAER;AAAA,EACF;AAAA,EAEQ,OAAO,IAA2B;AACxC,WAAO,IAAI,QAAQ,aAAW,WAAW,SAAS,EAAE,CAAC;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YAAY,KAA6B;AACvC,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAI,CAAC,KAAK,MAAM,KAAK,GAAG,eAAe,UAAU,MAAM;AACrD,eAAO,IAAI,MAAM,uBAAuB,CAAC;AACzC;AAAA,MACF;AACA,YAAM,UAAU,KAAK,UAAU,GAAG;AAClC,WAAK,GAAG,KAAK,SAAS,SAAO;AAC3B,YAAI,KAAK;AAIP,eAAK,iCAAyC;AAC9C,iBAAO,GAAG;AAAA,QACZ,OAAO;AACL,kBAAQ;AAAA,QACV;AAAA,MACF,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AAAA;AAAA,EAGQ,SAAS,KAAoB;AACnC,QAAI,CAAC,KAAK,MAAM,KAAK,GAAG,eAAe,UAAU,KAAM;AACvD,QAAI;AACF,WAAK,GAAG,KAAK,KAAK,UAAU,GAAG,CAAC;AAAA,IAClC,QAAQ;AAAA,IAER;AAAA,EACF;AAAA;AAAA,EAGA,OAAO,gBAAgB,QAAsD;AAC3E,WAAO,MAAM;AACX,UAAI,QAAQ,QAAS;AAGrB,aAAO,KAAK,cAAc,SAAS,GAAG;AACpC,cAAMC,OAAM,KAAK,cAAc,MAAM;AACrC,cAAMA;AAAA,MACR;AAGA,YAAM,MAAM,MAAM,IAAI,QAA+B,aAAW;AAC9D,YAAI,CAAC,KAAK,IAAI;AACZ,kBAAQ,IAAI;AACZ;AAAA,QACF;AACA,aAAK,UAAU,KAAK,OAAO;AAAA,MAC7B,CAAC;AAED,UAAI,QAAQ,KAAM;AAClB,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA,EAGA,MAAM,YAAqD;AACzD,QAAI,KAAK,cAAc,SAAS,GAAG;AACjC,YAAMA,OAAM,KAAK,cAAc,MAAM;AACrC,aAAOA;AAAA,IACT;AACA,QAAI,CAAC,KAAK,GAAI,QAAO;AACrB,UAAM,MAAM,MAAM,IAAI,QAA+B,aAAW;AAC9D,WAAK,UAAU,KAAK,OAAO;AAAA,IAC7B,CAAC;AACD,QAAI,QAAQ,KAAM,QAAO;AACzB,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,qBAAqB,SAA0D;AAC7E,QAAI,KAAK,cAAc,SAAS,GAAG;AACjC,YAAM,MAAM,KAAK,cAAc,MAAM;AACrC,aAAO,QAAQ,QAAQ,GAA8B;AAAA,IACvD;AACA,QAAI,CAAC,KAAK,GAAI,QAAO,QAAQ,QAAQ,IAAI;AAEzC,WAAO,IAAI,QAAwC,aAAW;AAC5D,YAAM,QAAQ,WAAW,MAAM;AAC7B,cAAM,MAAM,KAAK,UAAU,QAAQ,QAAQ;AAC3C,YAAI,OAAO,EAAG,MAAK,UAAU,OAAO,KAAK,CAAC;AAC1C,gBAAQ,IAAI;AAAA,MACd,GAAG,OAAO;AAEV,YAAM,WAAW,CAAC,QAA+B;AAC/C,qBAAa,KAAK;AAClB,gBAAQ,GAAqC;AAAA,MAC/C;AAEA,WAAK,UAAU,KAAK,QAAQ;AAAA,IAC9B,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,gCAA0C;AACxC,QAAI,KAAK,cAAc,WAAW,EAAG,QAAO,CAAC;AAC7C,UAAM,OAAyB,CAAC;AAChC,UAAM,UAAoB,CAAC;AAC3B,WAAO,KAAK,cAAc,SAAS,GAAG;AACpC,YAAM,QAAQ,KAAK,cAAc,MAAM;AACvC,YAAM,QAAQ,uBAAuB,KAAK;AAC1C,UAAI,UAAU,MAAM;AAClB,gBAAQ,KAAK,KAAK;AAClB;AAAA,MACF;AACA,WAAK,KAAK,KAAuB;AAAA,IACnC;AACA,SAAK,gBAAgB;AACrB,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,oBAA6B;AAC3B,WAAO,KAAK,OAAO,QAAQ,KAAK,GAAG,eAAe,UAAU;AAAA,EAC9D;AAAA;AAAA,EAGA,kBAAkB,GAAiB;AACjC,QAAI,IAAI,EAAG,MAAK,iBAAiB;AAAA,EACnC;AAAA;AAAA,EAGA,iBAAyB;AACvB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,0BAA0B,IAA8D;AACtF,SAAK,mBAAmB;AAAA,EAC1B;AAAA,EAEQ,qBAAqB,KAA2B;AACtD,UAAM,MAAM,KAAK,iBAAiB,IAAI,KAAK,iBAAiB;AAC5D,QAAI,KAAK,cAAc,SAAS,KAAK;AACnC,WAAK,cAAc,KAAK,GAAG;AAC3B;AAAA,IACF;AACA,UAAM,KAAK;AACX,QAAI,UAAU;AACd,QAAI,UAAU;AACd,aAAS,IAAI,GAAG,IAAI,KAAK,cAAc,QAAQ,KAAK;AAClD,YAAM,IAAI,yBAAyB,KAAK,cAAc,CAAC,CAA4B;AACnF,UAAI,IAAI,SAAS;AACf,kBAAU;AACV,kBAAU;AAAA,MACZ;AAAA,IACF;AACA,UAAM,cAAc,yBAAyB,EAAE;AAC/C,QAAI,WAAW,KAAK,WAAW,sBAAsB;AACnD,WAAK,cAAc,OAAO,SAAS,CAAC;AACpC,WAAK,cAAc,KAAK,GAAG;AAC3B,WAAK,gBAAgB;AACrB;AAAA,IACF;AACA,QAAI,eAAe,sBAAsB;AACvC,WAAK,gBAAgB;AACrB;AAAA,IACF;AACA,QAAI,KAAK,cAAc,SAAS,GAAG;AACjC,WAAK,cAAc,MAAM;AACzB,WAAK,gBAAgB;AAAA,IACvB;AACA,SAAK,cAAc,KAAK,GAAG;AAAA,EAC7B;AAAA,EAEQ,kBAAwB;AAC9B,SAAK,uBAAuB;AAC5B,QAAI,KAAK,oBAAoB,KAAK,wBAAwB,GAAG;AAC3D,UAAI;AACF,aAAK,iBAAiB,GAAG,wBAAwB;AAAA,MACnD,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcQ,yBAAyB,SAA0D;AACzF,QAAI,CAAC,KAAK,GAAI,QAAO,QAAQ,QAAQ,IAAI;AACzC,WAAO,IAAI,QAAwC,aAAW;AAC5D,YAAM,QAAQ,WAAW,MAAM;AAC7B,cAAM,MAAM,KAAK,UAAU,QAAQ,QAAQ;AAC3C,YAAI,OAAO,EAAG,MAAK,UAAU,OAAO,KAAK,CAAC;AAC1C,gBAAQ,IAAI;AAAA,MACd,GAAG,OAAO;AAEV,YAAM,WAAW,CAAC,QAA+B;AAC/C,qBAAa,KAAK;AAClB,gBAAQ,GAAqC;AAAA,MAC/C;AAEA,WAAK,UAAU,KAAK,QAAQ;AAAA,IAC9B,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,gBACJ,QACA,QACA,cACA,UAAkB,MACgB;AAClC,UAAM,MAAM,gBAAgB,QAAQ,MAAM;AAC1C,UAAM,MAAM,IAAI;AAGhB,UAAM,EAAE,MAAM,WAAW,IAAI,KAAK,IAAI,YAAY,GAAG;AACrD,UAAM,QAAQ,gBAAgB;AAC9B,QAAI;AACF,YAAM,KAAK,YAAY,GAAG;AAC1B,YAAM,SAAS,MAAM,KAAK,SAAS,MAAM,SAAS,KAAK;AACvD,aAAO;AAAA,IACT,UAAE;AACA,iBAAW;AAAA,IACb;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,SACZ,MACA,SACA,OACkC;AAClC,QAAI;AACJ,QAAI,oBAAgC,MAAM;AAAA,IAAC;AAC3C,UAAM,WAAW,IAAI,QAAe,CAAC,GAAG,WAAW;AACjD,cAAQ;AAAA,QACN,MAAM,OAAO,IAAI,MAAM,iBAAiB,OAAO,kBAAkB,KAAK,EAAE,CAAC;AAAA,QACzE;AAAA,MACF;AAAA,IACF,CAAC;AACD,UAAM,UAAU,IAAI,QAAe,CAAC,GAAG,WAAW;AAChD,UAAI,KAAK,cAAc;AACrB,eAAO,IAAI,MAAM,iCAAiC,KAAK,EAAE,CAAC;AAC1D;AAAA,MACF;AACA,YAAM,eAAe,MAAM;AACzB,eAAO,IAAI,MAAM,iCAAiC,KAAK,EAAE,CAAC;AAAA,MAC5D;AACA,WAAK,KAAK,gBAAgB,YAAY;AACtC,0BAAoB,MAAM,KAAK,eAAe,gBAAgB,YAAY;AAAA,IAC5E,CAAC;AACD,QAAI;AACF,aAAO,MAAM,QAAQ,KAAK,CAAC,MAAM,UAAU,OAAO,CAAC;AAAA,IACrD,UAAE;AACA,UAAI,MAAO,cAAa,KAAK;AAC7B,wBAAkB;AAAA,IACpB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAc,4BACZ,KACA,OACA,SACkC;AAClC,UAAM,MAAM,IAAI;AAChB,UAAM,EAAE,MAAM,WAAW,IAAI,KAAK,IAAI,YAAY,GAAG;AACrD,QAAI;AACF,YAAM,KAAK,YAAY,GAAG;AAC1B,aAAO,MAAM,KAAK,SAAS,MAAM,SAAS,KAAK;AAAA,IACjD,UAAE;AACA,iBAAW;AAAA,IACb;AAAA,EACF;AAAA;AAAA,EAGA,OAAO,QAAoB,QAAgD;AACzE,WAAO,KAAK,YAAY,qBAAqB,QAAQ,MAAM,CAAC;AAAA,EAC9D;AAAA,EAEQ,yBAAyB,OAAsC;AACrE,QAAI,OAAO,MAAM,QAAQ,EAAE,MAAM,eAAe;AAC9C,YAAM,SAAS,MAAM;AACrB,UAAI,MAAM,QAAQ,MAAM,GAAG;AACzB,mBAAW,OAAO,QAAQ;AACxB,cAAI,OAAO,OAAO,QAAQ,UAAU;AAClC,iBAAK,yBAAyB,GAA8B;AAAA,UAC9D;AAAA,QACF;AAAA,MACF;AACA;AAAA,IACF;AACA,QAAI,CAAC,wBAAwB,KAAK,EAAG;AACrC,UAAM,SAAS,yBAAyB,KAAK;AAC7C,QAAI,CAAC,OAAQ;AACb,UAAM,QAAQ,KAAK,gBAAgB,IAAI,MAAM,KAAK,KAAK;AACvD,SAAK,gBAAgB,IAAI,QAAQ,IAAI;AACrC,SAAK,KAAK,iBAAiB,QAAQ,IAAI;AAAA,EACzC;AAAA,EAEA,MAAc,iBAAiB,QAAgB,KAA4B;AACzE,UAAM,QAAQ,KAAK,iBAAiB,IAAI,MAAM,KAAK;AACnD,QAAI,OAAO,MAAO;AAClB,SAAK,iBAAiB,IAAI,QAAQ,GAAG;AACrC,QAAI,CAAC,KAAK,YAAY,EAAG;AACzB,QAAI;AACF,YAAM,KAAK,OAAO,gBAAgB,EAAE,SAAS,QAAQ,IAAI,CAAC;AAAA,IAC5D,QAAQ;AAAA,IAER;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,UACJ,QACA,QACA,UAAkB,KACD;AACjB,UAAM,MAAM,kBAAkB,QAAQ,MAAM;AAC5C,UAAM,QAAQ,IAAI;AAClB,UAAM,KAAK,YAAY,GAAG;AAK1B,UAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,WAAO,KAAK,IAAI,IAAI,UAAU;AAC5B,YAAM,YAAY,WAAW,KAAK,IAAI;AACtC,UAAI,aAAa,EAAG;AACpB,YAAM,KAAK,MAAM,KAAK,yBAAyB,SAAS;AACxD,UAAI,OAAO,KAAM;AACjB,YAAM,OAAO,GAAG;AAChB,UAAI,SAAS,OAAO;AAClB,aAAK,qBAAqB,EAAoB;AAC9C;AAAA,MACF;AACA,YAAM,MAAM,GAAG;AACf,UAAI,QAAQ,SAAS;AACnB,cAAM,SAAU,GAAG,SAAiE,CAAC;AACrF,cAAM,IAAI;AAAA,UACR,OAAO,QAAQ;AAAA,UACf,OAAO,WAAW;AAAA,UAClB,OAAO;AAAA,QACT;AAAA,MACF;AACA,UAAI,QAAQ,UAAU,QAAQ,YAAY;AAGxC,aAAK,cAAc,QAAQ,EAAoB;AAC/C;AAAA,MACF;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,YAAY,gBAAuC;AACjD,WAAO,KAAK,YAAY,oBAAoB,cAAc,CAAC;AAAA,EAC7D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,OAAgD;AACpD,UAAM,KAAK,MAAM,KAAK,UAAU;AAChC,QAAI,OAAO,KAAM,QAAO;AACxB,QAAI,GAAG,SAAS,QAAQ;AACtB,aAAQ,GAAG,WAAuC,CAAC;AAAA,IACrD;AACA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,UAAU,MAAc,SAAuC;AAC7D,UAAM,UAAU,SAAS,UAAU,IAAI,KAAK;AAC5C,QAAI,CAAC,QAAQ;AACX,aAAO,QAAQ,OAAO,IAAI,MAAM,mCAAmC,CAAC;AAAA,IACtE;AACA,UAAM,SAAkC;AAAA,MACtC,SAAS;AAAA,MACT,SAAS;AAAA,MACT,YAAY,SAAS,cAAc;AAAA,IACrC;AACA,QAAI,SAAS,kBAAkB,OAAW,QAAO,iBAAiB,QAAQ;AAC1E,QAAI,SAAS,SAAU,QAAO,qBAAqB,QAAQ;AAC3D,QAAI,SAAS,MAAO,QAAO,QAAQ,QAAQ;AAC3C,QAAI,SAAS,YAAa,QAAO,eAAe,QAAQ;AACxD,QAAI,SAAS,YAAa,QAAO,cAAc,QAAQ;AACvD,QAAI,SAAS,YAAY;AACvB,YAAM,YAAY,4BAA4B,QAAQ,UAAU;AAChE,UAAI,WAAW;AACb,eAAO,QAAQ,OAAO,IAAI,MAAM,SAAS,CAAC;AAAA,MAC5C;AACA,aAAO,cAAc,QAAQ;AAAA,IAC/B;AACA,QAAI,SAAS,eAAgB,QAAO,kBAAkB,QAAQ;AAC9D,QAAI,SAAS,mBAAoB,QAAO,uBAAuB,QAAQ;AACvE,QAAI,SAAS,yBAAyB;AACpC,aAAO,yBAAyB,QAAQ;AAC1C,QAAI,SAAS,kBAAmB,QAAO,qBAAqB,QAAQ;AACpE,QAAI,SAAS,oBAAqB,QAAO,uBAAuB;AAChE,QAAI,SAAS,qBAAsB,QAAO,wBAAwB,QAAQ;AAC1E,WAAO,KAAK,OAAO,cAAc,MAAM;AAAA,EACzC;AAAA;AAAA,EAGA,YAAY,KAA4B;AACtC,WAAO,KAAK,OAAO,iBAAiB,EAAE,IAAI,CAAC;AAAA,EAC7C;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,YAAY,MAA+C;AACzD,WAAO,KAAK,YAAY,kBAAkB,IAAI,CAAC;AAAA,EACjD;AAAA;AAAA,EAGA,MAAM,kBACJ,QACA,WACA,gBACe;AACf,UAAM,KAAK,UAAU,eAAe;AAAA,MAClC,SAAS;AAAA,MACT;AAAA,MACA,iBAAiB;AAAA,IACnB,CAAC;AAAA,EACH;AAAA;AAAA,EAGA,eAAe,QAA+B;AAG5C,WAAO,KAAK,YAAY,oBAAoB,MAAM,CAAC;AAAA,EACrD;AAAA;AAAA,EAGA,aAA4B;AAC1B,WAAO,KAAK,YAAY,mBAAmB,CAAC;AAAA,EAC9C;AAAA;AAAA,EAGA,mBAAkC;AAChC,WAAO,KAAK,YAAY,gBAAgB,iBAAiB,CAAC,CAAC,CAAC;AAAA,EAC9D;AAAA;AAAA,EAGA,qBAAoC;AAClC,WAAO,KAAK,YAAY,gBAAgB,mBAAmB,CAAC,CAAC,CAAC;AAAA,EAChE;AAAA;AAAA,EAGA,cAAc,SAAgC;AAC5C,WAAO,KAAK,YAAY,gBAAgB,cAAc,EAAE,QAAQ,CAAC,CAAC;AAAA,EACpE;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,WAAW,SAAoD;AAC7D,WAAO,KAAK,gBAAgB,eAAe,CAAC,GAAG,eAAe,WAAW,IAAM;AAAA,EACjF;AAAA;AAAA,EAGA,WAAW,SAAoD;AAC7D,WAAO,KAAK,gBAAgB,eAAe,CAAC,GAAG,eAAe,WAAW,IAAM;AAAA,EACjF;AAAA;AAAA,EAGA,YAAY,OAAe,MAAe,SAAoD;AAC5F,UAAM,SAAkC,EAAE,OAAO,MAAM,QAAQ,GAAG;AAClE,WAAO,KAAK,gBAAgB,gBAAgB,QAAQ,gBAAgB,WAAW,IAAO;AAAA,EACxF;AAAA;AAAA,EAGA,UAAU,SAAkB,WAAsD;AAChF,UAAM,SAAkC,CAAC;AACzC,QAAI,UAAW,QAAO,SAAS,EAAE,UAAU;AAC3C,WAAO,KAAK,gBAAgB,aAAa,QAAQ,aAAa,WAAW,IAAM;AAAA,EACjF;AAAA;AAAA,EAGA,QAAQ,QAAgB,SAAoD;AAC1E,WAAO,KAAK,gBAAgB,YAAY,EAAE,SAAS,OAAO,GAAG,YAAY,WAAW,IAAM;AAAA,EAC5F;AAAA;AAAA,EAGA,YAAY,QAAgB,SAAoD;AAC9E,WAAO,KAAK,gBAAgB,aAAa,EAAE,SAAS,OAAO,GAAG,aAAa,WAAW,IAAM;AAAA,EAC9F;AAAA;AAAA,EAGA,WAAW,QAAgB,SAAoD;AAC7E,WAAO,KAAK;AAAA,MACV;AAAA,MACA,EAAE,SAAS,OAAO;AAAA,MAClB;AAAA,MACA,WAAW;AAAA,IACb;AAAA,EACF;AAAA;AAAA,EAGA,iBACE,QACA,OACA,QACA,eACe;AACf,UAAM,SAAkC,EAAE,SAAS,OAAO;AAC1D,QAAI,UAAU,OAAW,QAAO,QAAQ;AACxC,QAAI,WAAW,OAAW,QAAO,SAAS;AAC1C,QAAI,cAAe,QAAO,iBAAiB;AAC3C,WAAO,KAAK,YAAY,gBAAgB,iBAAiB,MAAM,CAAC;AAAA,EAClE;AAAA;AAAA,EAGA,iBAAiB,QAA+B;AAC9C,WAAO,KAAK,YAAY,gBAAgB,kBAAkB,EAAE,SAAS,OAAO,CAAC,CAAC;AAAA,EAChF;AAAA;AAAA,EAGA,oBACE,QACA,QACA,QACe;AACf,UAAM,SAAkC,EAAE,SAAS,QAAQ,OAAO;AAClE,QAAI,OAAQ,QAAO,UAAU;AAC7B,WAAO,KAAK,YAAY,gBAAgB,qBAAqB,MAAM,CAAC;AAAA,EACtE;AAAA;AAAA,EAGA,qBAAqB,QAA+B;AAClD,WAAO,KAAK,YAAY,gBAAgB,sBAAsB,EAAE,SAAS,OAAO,CAAC,CAAC;AAAA,EACpF;AAAA;AAAA,EAGA,gBAA+B;AAC7B,WAAO,KAAK,YAAY,gBAAgB,cAAc,CAAC,CAAC,CAAC;AAAA,EAC3D;AAAA;AAAA,EAGA,mBAAkC;AAChC,WAAO,KAAK,YAAY,gBAAgB,iBAAiB,CAAC,CAAC,CAAC;AAAA,EAC9D;AAAA;AAAA,EAGA,SAAS,WAAmB,WAAkC;AAC5D,WAAO,KAAK;AAAA,MACV,gBAAgB,QAAQ,EAAE,YAAY,WAAW,YAAY,UAAU,CAAC;AAAA,IAC1E;AAAA,EACF;AAAA;AAAA,EAGA,gBAAgB,cAAqC;AACnD,WAAO,KAAK,YAAY,gBAAgB,gBAAgB,EAAE,eAAe,aAAa,CAAC,CAAC;AAAA,EAC1F;AAAA;AAAA,EAGA,gBACE,QACA,OACA,QACA,eACA,SACkC;AAClC,UAAM,SAAkC,EAAE,SAAS,OAAO;AAC1D,QAAI,UAAU,OAAW,QAAO,QAAQ;AACxC,QAAI,WAAW,OAAW,QAAO,SAAS;AAC1C,QAAI,cAAe,QAAO,iBAAiB;AAC3C,WAAO,KAAK,gBAAgB,iBAAiB,QAAQ,iBAAiB,WAAW,IAAM;AAAA,EACzF;AAAA;AAAA,EAGA,aAAa,QAAgB,SAAoD;AAC/E,WAAO,KAAK;AAAA,MACV;AAAA,MACA,EAAE,SAAS,OAAO;AAAA,MAClB;AAAA,MACA,WAAW;AAAA,IACb;AAAA,EACF;AAAA;AAAA,EAGA,gBACE,QACA,QACA,QACA,SACkC;AAClC,UAAM,SAAkC,EAAE,SAAS,QAAQ,OAAO;AAClE,QAAI,OAAQ,QAAO,UAAU;AAC7B,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW;AAAA,IACb;AAAA,EACF;AAAA;AAAA,EAGA,aAAa,SAAoD;AAC/D,WAAO,KAAK,gBAAgB,cAAc,CAAC,GAAG,cAAc,WAAW,IAAM;AAAA,EAC/E;AAAA;AAAA,EAGA,iBAAiB,QAAgB,SAAoD;AACnF,WAAO,KAAK;AAAA,MACV;AAAA,MACA,EAAE,SAAS,OAAO;AAAA,MAClB;AAAA,MACA,WAAW;AAAA,IACb;AAAA,EACF;AAAA;AAAA,EAGA,aAAa,SAAoD;AAC/D,WAAO,KAAK,gBAAgB,iBAAiB,CAAC,GAAG,iBAAiB,WAAW,IAAM;AAAA,EACrF;AAAA;AAAA,EAGA,aACE,WACA,WACA,SACkC;AAClC,WAAO,KAAK;AAAA,MACV;AAAA,MACA,EAAE,YAAY,WAAW,YAAY,UAAU;AAAA,MAC/C;AAAA,MACA,WAAW;AAAA,IACb;AAAA,EACF;AAAA;AAAA,EAGA,iBAAiB,cAAsB,SAAoD;AACzF,WAAO,KAAK;AAAA,MACV;AAAA,MACA,EAAE,eAAe,aAAa;AAAA,MAC9B;AAAA,MACA,WAAW;AAAA,IACb;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,UACE,MACA,mBACA,WACA,SACkC;AAClC,UAAM,SAAkC,EAAE,KAAK;AAC/C,QAAI,kBAAmB,QAAO,qBAAqB;AACnD,QAAI,UAAW,QAAO,YAAY;AAClC,WAAO,KAAK,gBAAgB,cAAc,QAAQ,cAAc,WAAW,IAAM;AAAA,EACnF;AAAA;AAAA,EAGA,aAAa,OAAe,SAAoD;AAC9E,WAAO,KAAK,gBAAgB,cAAc,EAAE,QAAQ,MAAM,GAAG,cAAc,WAAW,IAAM;AAAA,EAC9F;AAAA;AAAA,EAGA,SAAS,OAAe,SAAoD;AAC1E,WAAO,KAAK,gBAAgB,aAAa,EAAE,QAAQ,MAAM,GAAG,aAAa,WAAW,IAAM;AAAA,EAC5F;AAAA;AAAA,EAGA,UAAU,OAAe,SAAoD;AAC3E,WAAO,KAAK,gBAAgB,cAAc,EAAE,QAAQ,MAAM,GAAG,cAAc,WAAW,IAAM;AAAA,EAC9F;AAAA;AAAA,EAGA,UAAU,OAAe,SAAoD;AAC3E,WAAO,KAAK,gBAAgB,cAAc,EAAE,QAAQ,MAAM,GAAG,cAAc,WAAW,IAAM;AAAA,EAC9F;AAAA;AAAA,EAGA,UAAU,OAAe,SAAoD;AAC3E,WAAO,KAAK,gBAAgB,WAAW,EAAE,QAAQ,MAAM,GAAG,WAAW,WAAW,IAAM;AAAA,EACxF;AAAA;AAAA,EAGA,gBACE,OACA,MACA,QACA,SACkC;AAClC,UAAM,SAAkC,EAAE,QAAQ,OAAO,SAAS,KAAK;AACvE,QAAI,OAAQ,QAAO,UAAU;AAC7B,WAAO,KAAK,gBAAgB,gBAAgB,QAAQ,gBAAgB,WAAW,GAAM;AAAA,EACvF;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,gBAAgB,SAAoD;AAClE,WAAO,KAAK,gBAAgB,oBAAoB,CAAC,GAAG,oBAAoB,WAAW,IAAM;AAAA,EAC3F;AAAA;AAAA,EAGA,gBACE,aACA,MACkC;AAClC,UAAM,SAAkC;AAAA,MACtC;AAAA,MACA,UAAU,MAAM,YAAY;AAAA,IAC9B;AACA,QAAI,MAAM,UAAW,QAAO,YAAY,KAAK;AAC7C,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA,MAAM,WAAW;AAAA,IACnB;AAAA,EACF;AAAA;AAAA,EAGA,mBAAmB,SAAoD;AACrE,WAAO,KAAK;AAAA,MACV;AAAA,MACA,CAAC;AAAA,MACD;AAAA,MACA,WAAW;AAAA,IACb;AAAA,EACF;AAAA;AAAA,EAGA,iBAAiB,QAAgB,SAAoD;AACnF,WAAO,KAAK;AAAA,MACV;AAAA,MACA,EAAE,SAAS,OAAO;AAAA,MAClB;AAAA,MACA,WAAW;AAAA,IACb;AAAA,EACF;AAAA;AAAA,EAGA,oBAAoB,QAAgB,SAAoD;AACtF,WAAO,KAAK;AAAA,MACV;AAAA,MACA,EAAE,SAAS,OAAO;AAAA,MAClB;AAAA,MACA,WAAW;AAAA,IACb;AAAA,EACF;AAAA;AAAA,EAGA,mBAAmB,SAAoD;AACrE,WAAO,KAAK;AAAA,MACV;AAAA,MACA,CAAC;AAAA,MACD;AAAA,MACA,WAAW;AAAA,IACb;AAAA,EACF;AAAA;AAAA,EAGA,cAAc,SAAoD;AAChE,WAAO,KAAK,gBAAgB,kBAAkB,CAAC,GAAG,kBAAkB,WAAW,IAAM;AAAA,EACvF;AAAA;AAAA,EAGA,eAAe,SAAoD;AACjE,WAAO,KAAK,gBAAgB,mBAAmB,CAAC,GAAG,mBAAmB,WAAW,IAAM;AAAA,EACzF;AAAA;AAAA,EAGA,gBAAgB,QAAgB,SAAoD;AAClF,WAAO,KAAK;AAAA,MACV;AAAA,MACA,EAAE,SAAS,OAAO;AAAA,MAClB;AAAA,MACA,WAAW;AAAA,IACb;AAAA,EACF;AAAA;AAAA,EAGA,kBAAkB,SAAoD;AACpE,WAAO,KAAK;AAAA,MACV;AAAA,MACA,CAAC;AAAA,MACD;AAAA,MACA,WAAW;AAAA,IACb;AAAA,EACF;AAAA;AAAA,EAGA,gBAAgB,OAAe,SAAoD;AACjF,WAAO,KAAK;AAAA,MACV;AAAA,MACA,EAAE,QAAQ,MAAM;AAAA,MAChB;AAAA,MACA,WAAW;AAAA,IACb;AAAA,EACF;AAAA;AAAA,EAGA,aACE,kBACkC;AAClC,UAAM,UACJ,OAAO,qBAAqB,WACxB,EAAE,SAAS,iBAAiB,IAC5B;AACN,WAAO,KAAK;AAAA,MACV;AAAA,MACA,EAAE,kBAAkB,SAAS,mBAAmB,MAAM;AAAA,MACtD;AAAA,MACA,SAAS,WAAW;AAAA,IACtB;AAAA,EACF;AAAA;AAAA,EAGA,mBAAmB,SAAmC;AACpD,WAAO,KAAK,UAAU,oBAAoB,CAAC,GAAG,WAAW,IAAM;AAAA,EACjE;AAAA;AAAA,EAGA,qBAAqB,SAAoD;AAIvE,UAAM,MAAM,oBAAoB,aAAa,CAAC;AAC9C,WAAO,KAAK,4BAA4B,KAAK,yBAAyB,WAAW,IAAM;AAAA,EACzF;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,QAAQ,MAAc,UAAmB,SAAoD;AAC3F,UAAM,SAAkC,EAAE,KAAK;AAC/C,QAAI,aAAa,OAAW,QAAO,WAAW;AAC9C,WAAO,KAAK;AAAA,MACV;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW;AAAA;AAAA,IACb;AAAA,EACF;AAAA;AAAA,EAGA,SAAS,QAAiB,SAAoD;AAC5E,UAAM,SAAkC,CAAC;AACzC,QAAI,WAAW,OAAW,QAAO,SAAS;AAC1C,WAAO,KAAK,gBAAgB,aAAa,QAAQ,aAAa,WAAW,IAAM;AAAA,EACjF;AAAA;AAAA,EAGA,SAAS,OAAe,SAAoD;AAC1E,WAAO,KAAK,gBAAgB,aAAa,EAAE,QAAQ,MAAM,GAAG,aAAa,WAAW,IAAM;AAAA,EAC5F;AAAA;AAAA,EAGA,WAAW,OAAe,SAAoD;AAC5E,WAAO,KAAK,gBAAgB,eAAe,EAAE,QAAQ,MAAM,GAAG,eAAe,WAAW,IAAM;AAAA,EAChG;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAM,mBAAmB,SAAoD;AAC3E,QAAI,KAAK,mBAAmB;AAC1B,aAAO,EAAE,iBAAiB,KAAK,kBAAkB,QAAQ;AAAA,IAC3D;AACA,UAAM,IAAI,WAAW;AACrB,UAAM,WAAW,KAAK,IAAI,IAAI;AAC9B,WAAO,KAAK,IAAI,IAAI,UAAU;AAC5B,YAAM,YAAY,WAAW,KAAK,IAAI;AACtC,UAAI,aAAa,EAAG;AACpB,YAAM,KAAK,MAAM,KAAK,qBAAqB,SAAS;AACpD,UAAI,OAAO,KAAM;AACjB,UAAI,GAAG,SAAS,iBAAkB;AAClC,YAAM,SAAU,GAAG,UAAkD,CAAC;AACtE,YAAM,QAAQ,OAAO;AACrB,UAAI,UAAU,QAAS,QAAO;AAC9B,YAAM,IAAI,MAAM,2BAA2B,SAAS,SAAS,EAAE;AAAA,IACjE;AACA,UAAM,IAAI,MAAM,iBAAiB,CAAC,+BAA+B;AAAA,EACnE;AACF;","names":["DisconnectCause","VerbosityTier","msg"]}
@@ -0,0 +1,7 @@
1
+ import {
2
+ Client
3
+ } from "./chunk-56Z7SUGW.js";
4
+ export {
5
+ Client
6
+ };
7
+ //# sourceMappingURL=client-CUYIRMFW.js.map