negotium 0.1.12 → 0.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/dist/canonical-mcp-bridge.js +2 -3
  2. package/dist/canonical-mcp-bridge.js.map +1 -1
  3. package/dist/chunk-a9y2rwxf.js.map +1 -1
  4. package/dist/{chunk-j0kjscb7.js → chunk-s2gez3wg.js} +20 -2
  5. package/dist/{chunk-j0kjscb7.js.map → chunk-s2gez3wg.js.map} +2 -2
  6. package/dist/cron.js +49 -25
  7. package/dist/cron.js.map +15 -14
  8. package/dist/hosted-agent.js +3012 -17
  9. package/dist/hosted-agent.js.map +30 -3
  10. package/dist/main.js +31323 -36
  11. package/dist/main.js.map +198 -3
  12. package/dist/prompts.js +11 -8
  13. package/dist/prompts.js.map +4 -4
  14. package/dist/runtime/src/application/submit-user-message.ts +3 -0
  15. package/dist/runtime/src/index.ts +7 -0
  16. package/dist/runtime/src/mcp/runtime-spec.ts +3 -0
  17. package/dist/runtime/src/mcp/session-comm/server.ts +1 -1
  18. package/dist/runtime/src/platform/mcp-config.ts +13 -0
  19. package/dist/runtime/src/prompts/builders.ts +20 -6
  20. package/dist/runtime/src/query/active-rooms.ts +2 -0
  21. package/dist/runtime/src/runtime/delivery-ack.ts +112 -0
  22. package/dist/runtime/src/runtime/errors.ts +12 -12
  23. package/dist/runtime/src/runtime/turn-runner.ts +12 -0
  24. package/dist/runtime/src/storage/runtime-turn-requests.ts +1 -0
  25. package/dist/runtime/src/types/api.ts +2 -0
  26. package/dist/runtime/src/types.ts +2 -0
  27. package/dist/runtime/src/version.ts +1 -1
  28. package/dist/runtime-helpers.js.map +1 -1
  29. package/dist/storage.js.map +1 -1
  30. package/dist/types/packages/core/src/mcp/runtime-spec.d.ts +2 -0
  31. package/dist/types/packages/core/src/platform/mcp-config.d.ts +4 -0
  32. package/dist/types/packages/core/src/prompts/builders.d.ts +2 -0
  33. package/dist/types/packages/core/src/types/api.d.ts +2 -0
  34. package/dist/types/packages/core/src/types.d.ts +2 -0
  35. package/dist/types/packages/core/src/version.d.ts +1 -1
  36. package/dist/vault.js.map +1 -1
  37. package/package.json +1 -1
  38. package/dist/chunk-00q25k7p.js +0 -2387
  39. package/dist/chunk-00q25k7p.js.map +0 -26
  40. package/dist/chunk-03kv7mvj.js +0 -2152
  41. package/dist/chunk-03kv7mvj.js.map +0 -15
  42. package/dist/chunk-05pm51dh.js +0 -589
  43. package/dist/chunk-05pm51dh.js.map +0 -11
  44. package/dist/chunk-0eh16bk1.js +0 -2936
  45. package/dist/chunk-0eh16bk1.js.map +0 -20
  46. package/dist/chunk-0yfqyv88.js +0 -108
  47. package/dist/chunk-0yfqyv88.js.map +0 -10
  48. package/dist/chunk-1k7t7bnx.js +0 -97
  49. package/dist/chunk-1k7t7bnx.js.map +0 -10
  50. package/dist/chunk-3gkfr9vb.js +0 -431
  51. package/dist/chunk-3gkfr9vb.js.map +0 -11
  52. package/dist/chunk-5akd1gbj.js +0 -281
  53. package/dist/chunk-5akd1gbj.js.map +0 -10
  54. package/dist/chunk-7k19pcg8.js +0 -577
  55. package/dist/chunk-7k19pcg8.js.map +0 -14
  56. package/dist/chunk-81tbfbmt.js +0 -10
  57. package/dist/chunk-81tbfbmt.js.map +0 -10
  58. package/dist/chunk-82qhv1mq.js +0 -512
  59. package/dist/chunk-82qhv1mq.js.map +0 -13
  60. package/dist/chunk-8dy7e2a9.js +0 -103
  61. package/dist/chunk-8dy7e2a9.js.map +0 -10
  62. package/dist/chunk-8f2sqmrj.js +0 -1712
  63. package/dist/chunk-8f2sqmrj.js.map +0 -18
  64. package/dist/chunk-9hjeemfz.js +0 -372
  65. package/dist/chunk-9hjeemfz.js.map +0 -10
  66. package/dist/chunk-a4aa2ccv.js +0 -141
  67. package/dist/chunk-a4aa2ccv.js.map +0 -10
  68. package/dist/chunk-bsg215q3.js +0 -3536
  69. package/dist/chunk-bsg215q3.js.map +0 -20
  70. package/dist/chunk-bxnfsc7w.js +0 -58
  71. package/dist/chunk-bxnfsc7w.js.map +0 -10
  72. package/dist/chunk-c500xe9z.js +0 -33
  73. package/dist/chunk-c500xe9z.js.map +0 -10
  74. package/dist/chunk-cngrf7ab.js +0 -149
  75. package/dist/chunk-cngrf7ab.js.map +0 -10
  76. package/dist/chunk-d7tprf06.js +0 -53
  77. package/dist/chunk-d7tprf06.js.map +0 -10
  78. package/dist/chunk-ddnrmkrv.js +0 -61
  79. package/dist/chunk-ddnrmkrv.js.map +0 -10
  80. package/dist/chunk-edb07sjp.js +0 -567
  81. package/dist/chunk-edb07sjp.js.map +0 -14
  82. package/dist/chunk-ejcm6zx8.js +0 -591
  83. package/dist/chunk-ejcm6zx8.js.map +0 -11
  84. package/dist/chunk-ezs352qs.js +0 -237
  85. package/dist/chunk-ezs352qs.js.map +0 -11
  86. package/dist/chunk-f5xgprg1.js +0 -59
  87. package/dist/chunk-f5xgprg1.js.map +0 -10
  88. package/dist/chunk-fbtb3v0s.js +0 -1339
  89. package/dist/chunk-fbtb3v0s.js.map +0 -16
  90. package/dist/chunk-ffefbd3r.js +0 -17
  91. package/dist/chunk-ffefbd3r.js.map +0 -10
  92. package/dist/chunk-gaknyw04.js +0 -708
  93. package/dist/chunk-gaknyw04.js.map +0 -14
  94. package/dist/chunk-gxmny6tq.js +0 -1637
  95. package/dist/chunk-gxmny6tq.js.map +0 -15
  96. package/dist/chunk-h7bj5zwb.js +0 -3069
  97. package/dist/chunk-h7bj5zwb.js.map +0 -32
  98. package/dist/chunk-hp4g7wx7.js +0 -46
  99. package/dist/chunk-hp4g7wx7.js.map +0 -10
  100. package/dist/chunk-hwy3n31w.js +0 -21
  101. package/dist/chunk-hwy3n31w.js.map +0 -9
  102. package/dist/chunk-jzz91jwh.js +0 -70
  103. package/dist/chunk-jzz91jwh.js.map +0 -10
  104. package/dist/chunk-k778y16p.js +0 -153
  105. package/dist/chunk-k778y16p.js.map +0 -11
  106. package/dist/chunk-mh5mexsf.js +0 -147
  107. package/dist/chunk-mh5mexsf.js.map +0 -11
  108. package/dist/chunk-mnwaext5.js +0 -318
  109. package/dist/chunk-mnwaext5.js.map +0 -10
  110. package/dist/chunk-nkgs40ch.js +0 -23
  111. package/dist/chunk-nkgs40ch.js.map +0 -10
  112. package/dist/chunk-pz57vwsm.js +0 -250
  113. package/dist/chunk-pz57vwsm.js.map +0 -11
  114. package/dist/chunk-r6kdp7gn.js +0 -252
  115. package/dist/chunk-r6kdp7gn.js.map +0 -10
  116. package/dist/chunk-rkvrkcgx.js +0 -117
  117. package/dist/chunk-rkvrkcgx.js.map +0 -10
  118. package/dist/chunk-s74rdyqe.js +0 -117
  119. package/dist/chunk-s74rdyqe.js.map +0 -12
  120. package/dist/chunk-sa874j5c.js +0 -9
  121. package/dist/chunk-sa874j5c.js.map +0 -10
  122. package/dist/chunk-sffqdkvq.js +0 -122
  123. package/dist/chunk-sffqdkvq.js.map +0 -10
  124. package/dist/chunk-tcs9qjps.js +0 -64
  125. package/dist/chunk-tcs9qjps.js.map +0 -10
  126. package/dist/chunk-wx83ep8e.js +0 -131
  127. package/dist/chunk-wx83ep8e.js.map +0 -10
  128. package/dist/chunk-xag86ng3.js +0 -122
  129. package/dist/chunk-xag86ng3.js.map +0 -10
  130. package/dist/chunk-xfdkep71.js +0 -371
  131. package/dist/chunk-xfdkep71.js.map +0 -11
  132. package/dist/chunk-xhm1rfpt.js +0 -2907
  133. package/dist/chunk-xhm1rfpt.js.map +0 -24
  134. package/dist/chunk-xpcps28p.js +0 -2138
  135. package/dist/chunk-xpcps28p.js.map +0 -29
  136. package/dist/chunk-yb4rbev9.js +0 -214
  137. package/dist/chunk-yb4rbev9.js.map +0 -10
@@ -1,20 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../adapters/otium/src/canonical-mcp-bridge.ts", "../../../adapters/otium/src/event-backflow.ts", "../../../adapters/otium/src/peer-files.ts", "../../../adapters/otium/src/runtime-bridge.ts", "../../../adapters/otium/src/session-bridge.ts", "../../../adapters/otium/src/session-bridge-ipc.ts", "../../../adapters/otium/src/relay-protocol.ts", "../../../adapters/otium/src/tunnel-client.ts", "../../../adapters/otium/src/peer-server.ts", "../../../adapters/otium/src/turn-bridge.ts", "../../../adapters/otium/src/index.ts"],
4
- "sourcesContent": [
5
- "import { randomUUID } from \"node:crypto\";\nimport type {\n CanonicalMcpBridgeScope,\n CanonicalMcpSurface,\n} from \"@negotium/core/canonical-mcp-bridge\";\nimport { registerCanonicalMcpBridgeEnvProvider } from \"@negotium/core/canonical-mcp-bridge\";\nimport { mintPeerToken, resolvePeerNodeByCellId } from \"@/central\";\nimport { PEER_PROTOCOL_VERSION } from \"@/protocol\";\n\nconst MAX_BODY_BYTES = 1024 * 1024;\nconst BODY_READ_TIMEOUT_MS = 10_000;\nconst MAX_INFLIGHT = 32;\nconst CAPABILITY_TTL_MS = 60 * 60 * 1000;\nconst MAX_CAPABILITIES = 2048;\nconst FORWARD_TIMEOUT_MS = 25_000;\n\nconst TOOL_ALLOWLIST: Record<CanonicalMcpSurface, ReadonlySet<string>> = {\n task: new Set([\"task_create\", \"task_update\", \"task_list\", \"task_get\", \"task_delete\"]),\n wiki: new Set([\n \"wiki_query\",\n \"wiki_topic_brief\",\n \"wiki_last_conversation\",\n \"save_wiki_entry\",\n \"index_upsert\",\n ]),\n};\n\ntype Capability = {\n surface: CanonicalMcpSurface;\n userId: string;\n hostTopicId: string;\n hostQueryId: string;\n hubCellId: string;\n expiresAt: number;\n};\n\ntype BridgeRequest = { tool: string; input: Record<string, unknown> };\ntype CanonicalToolResult = {\n content: Array<Record<string, unknown>>;\n isError?: boolean;\n [key: string]: unknown;\n};\n\nfunction readAuthorization(request: Request): string | null {\n const value = request.headers.get(\"authorization\");\n return value?.startsWith(\"Bearer \") ? value.slice(7) : null;\n}\n\nasync function readLimitedJson(request: Request): Promise<BridgeRequest | null> {\n const declared = Number(request.headers.get(\"content-length\") ?? \"0\");\n if (Number.isFinite(declared) && declared > MAX_BODY_BYTES) return null;\n const reader = request.body?.getReader();\n if (!reader) return null;\n const chunks: Uint8Array[] = [];\n let size = 0;\n const deadline = Date.now() + BODY_READ_TIMEOUT_MS;\n try {\n while (true) {\n const remaining = deadline - Date.now();\n if (remaining <= 0) throw new Error(\"body read timeout\");\n let timer: ReturnType<typeof setTimeout> | undefined;\n const { done, value } = await Promise.race([\n reader.read(),\n new Promise<never>((_, reject) => {\n timer = setTimeout(() => reject(new Error(\"body read timeout\")), remaining);\n }),\n ]).finally(() => {\n if (timer) clearTimeout(timer);\n });\n if (done) break;\n size += value.byteLength;\n if (size > MAX_BODY_BYTES) throw new Error(\"body too large\");\n chunks.push(value);\n }\n } catch {\n await reader.cancel().catch(() => undefined);\n return null;\n }\n try {\n const parsed = JSON.parse(Buffer.concat(chunks).toString(\"utf8\")) as unknown;\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) return null;\n const body = parsed as Record<string, unknown>;\n if (typeof body.tool !== \"string\" || body.tool.length > 128) return null;\n if (!body.input || typeof body.input !== \"object\" || Array.isArray(body.input)) return null;\n return { tool: body.tool, input: body.input as Record<string, unknown> };\n } catch {\n return null;\n }\n}\n\nasync function forwardCanonicalTool(\n capability: Capability,\n request: BridgeRequest,\n): Promise<{ result?: CanonicalToolResult; error?: string; status?: number }> {\n if (!TOOL_ALLOWLIST[capability.surface].has(request.tool)) {\n return { error: `tool is not available on ${capability.surface}`, status: 403 };\n }\n const hub = await resolvePeerNodeByCellId(capability.hubCellId).catch(() => null);\n if (!hub?.isPrimary || hub.self) return { error: \"canonical hub is unavailable\", status: 503 };\n try {\n const peerToken = await mintPeerToken(hub.cellId);\n const response = await fetch(\n `${hub.baseUrl.replace(/\\/+$/, \"\")}/api/v1/peer/bridge/canonical-mcp`,\n {\n method: \"POST\",\n headers: { authorization: `Bearer ${peerToken}`, \"content-type\": \"application/json\" },\n body: JSON.stringify({\n v: PEER_PROTOCOL_VERSION,\n surface: capability.surface,\n userId: capability.userId,\n hostTopicId: capability.hostTopicId,\n hostQueryId: capability.hostQueryId,\n tool: request.tool,\n input: request.input,\n }),\n signal: AbortSignal.timeout(FORWARD_TIMEOUT_MS),\n },\n );\n const body = (await response.json().catch(() => null)) as {\n ok?: boolean;\n result?: CanonicalToolResult;\n error?: string;\n } | null;\n if (!response.ok || !body?.ok || !body.result) {\n return {\n error: body?.error ?? `canonical hub failed (${response.status})`,\n status: response.status,\n };\n }\n return { result: body.result };\n } catch (cause) {\n return { error: (cause as Error).message || \"canonical hub unreachable\", status: 502 };\n }\n}\n\nexport interface CanonicalMcpBridgeHandle {\n url: string;\n stop(): void;\n}\n\nexport interface CanonicalMcpBridgeOptions {\n /** Test seam; production always forwards to the authenticated Otium hub. */\n forwardTool?: typeof forwardCanonicalTool;\n}\n\n/**\n * Give only placed-turn MCP subprocesses a short-lived, turn-scoped route to\n * canonical hub task/wiki state. Vault, skills, and browser/provider profiles\n * never enter this bridge and continue to resolve on the worker node.\n */\nexport function startCanonicalMcpBridge(\n options: CanonicalMcpBridgeOptions = {},\n): CanonicalMcpBridgeHandle {\n const capabilities = new Map<string, Capability>();\n let inflight = 0;\n\n function sweep(now = Date.now()): void {\n for (const [token, capability] of capabilities) {\n if (capability.expiresAt <= now) capabilities.delete(token);\n }\n while (capabilities.size >= MAX_CAPABILITIES) {\n const oldest = capabilities.keys().next().value as string | undefined;\n if (!oldest) break;\n capabilities.delete(oldest);\n }\n }\n\n const server = Bun.serve({\n hostname: \"127.0.0.1\",\n port: 0,\n async fetch(request) {\n if (request.method !== \"POST\") return new Response(\"method not allowed\", { status: 405 });\n const token = readAuthorization(request);\n if (!token) return new Response(\"unauthorized\", { status: 401 });\n const capability = capabilities.get(token);\n if (!capability || capability.expiresAt <= Date.now()) {\n capabilities.delete(token);\n return new Response(\"unauthorized\", { status: 401 });\n }\n if (inflight >= MAX_INFLIGHT) return new Response(\"busy\", { status: 503 });\n inflight += 1;\n try {\n const payload = await readLimitedJson(request);\n if (!payload) return new Response(\"invalid request\", { status: 400 });\n if (!TOOL_ALLOWLIST[capability.surface].has(payload.tool)) {\n return new Response(\"tool denied\", { status: 403 });\n }\n const result = await (options.forwardTool ?? forwardCanonicalTool)(capability, payload);\n return Response.json(result, { status: result.status ?? (result.result ? 200 : 502) });\n } finally {\n inflight -= 1;\n }\n },\n });\n const url = `http://127.0.0.1:${server.port}/`;\n const unregister = registerCanonicalMcpBridgeEnvProvider((scope: CanonicalMcpBridgeScope) => {\n sweep();\n const token = `${randomUUID()}${randomUUID()}`;\n capabilities.set(token, {\n surface: scope.surface,\n userId: scope.userId,\n hostTopicId: scope.peerBridge.hostTopicId,\n hostQueryId: scope.peerBridge.hostQueryId,\n hubCellId: scope.peerBridge.hubCellId,\n expiresAt: Date.now() + CAPABILITY_TTL_MS,\n });\n return {\n env: {\n NEGOTIUM_CANONICAL_MCP_BRIDGE_URL: url,\n NEGOTIUM_CANONICAL_MCP_BRIDGE_TOKEN: token,\n },\n revoke: () => {\n capabilities.delete(token);\n },\n };\n });\n let stopped = false;\n return {\n url,\n stop() {\n if (stopped) return;\n stopped = true;\n unregister();\n capabilities.clear();\n server.stop(true);\n },\n };\n}\n",
6
- "/**\n * Event backflow — worker → hub. Reconstructs otium's WsHub feed from\n * negotium's RuntimeBus (`bus.ts` publishes `ai-status` payloads with a\n * `kind` discriminator mirroring the WS `type` names precisely for this) and\n * forwards one placed turn's events to the hub as\n * `POST /api/v1/peer/event {v, requestId, seq, event}`.\n *\n * Contract (docs/OTIUM-COUPLING.md §1.4/§2.2, otium turn-runner.ts):\n * - seq starts at 1 per requestId and MUST be contiguous; sends are chained\n * (next POST only after the previous settled).\n * - delivery failure retries ≤ 5 times with 100ms-base exponential backoff;\n * once exhausted the forwarder hard-blocks — later seqs are NEVER sent\n * (losing seq N and sending N+1 is the one forbidden move). The hub's\n * 30-minute watchdog fails the turn.\n * - exactly one terminal event (ai_done | ai_error | ai_aborted) per\n * requestId; a superseding turn emits a synthetic\n * `ai_aborted(reason:\"superseded\")` for its predecessor via `finish()`.\n */\n\nimport { logger, type RuntimeBusEvent, runtimeBus } from \"@negotium/core\";\nimport { mintPeerToken, type PeerNode, resolvePeerNodeByCellId } from \"@/central\";\nimport { PEER_PROTOCOL_VERSION } from \"@/protocol\";\nimport { acknowledgePeerTerminal, listPeerTerminalOutbox, upsertPeerTerminalOutbox } from \"@/store\";\n\nconst FORWARDED_TYPES = new Set([\n \"message\",\n \"message_updated\",\n \"typing\",\n \"tool_call\",\n \"tool_output\",\n \"tool_status\",\n \"visual\",\n \"file_ready\",\n \"ai_done\",\n \"ai_error\",\n \"ai_aborted\",\n]);\n\nconst TERMINAL_TYPES = new Set([\"ai_done\", \"ai_error\", \"ai_aborted\"]);\nconst PEER_EVENT_MAX_ATTEMPTS = 5;\nconst PEER_EVENT_RETRY_BASE_MS = 100;\nconst PEER_EVENT_TIMEOUT_MS = 15_000;\nconst PEER_EVENT_MAX_PENDING = 256;\n\nexport type SendEventResult = { ok: true } | { ok: false; error: string; status?: number };\n\nexport type SendPeerEvent = (payload: {\n v: number;\n requestId: string;\n seq: number;\n event: Record<string, unknown>;\n}) => Promise<SendEventResult>;\n\n/** Production event sender — peer-token POST to the hub's event endpoint. */\nexport function hubEventSender(hubNode: PeerNode): SendPeerEvent {\n return async (payload) => {\n let token: string;\n try {\n token = await mintPeerToken(hubNode.cellId);\n } catch (err) {\n return { ok: false, error: `peer token mint failed: ${(err as Error).message}` };\n }\n let response: Response;\n try {\n response = await fetch(`${hubNode.baseUrl.replace(/\\/+$/, \"\")}/api/v1/peer/event`, {\n method: \"POST\",\n headers: {\n authorization: `Bearer ${token}`,\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify(payload),\n signal: AbortSignal.timeout(PEER_EVENT_TIMEOUT_MS),\n });\n } catch {\n return { ok: false, error: `hub \"${hubNode.nodeName ?? hubNode.cellId}\" unreachable` };\n }\n const parsed = (await response.json().catch(() => null)) as {\n ok?: boolean;\n error?: string;\n } | null;\n if (!response.ok || !parsed?.ok) {\n return {\n ok: false,\n error: parsed?.error ?? `peer event rejected (${response.status})`,\n status: response.status,\n };\n }\n return { ok: true };\n };\n}\n\n// ── Bus → WsServerMessage translation ────────────────────────────────\n\ntype RawEvent = Record<string, unknown>;\n\nfunction defined(record: RawEvent): RawEvent {\n const out: RawEvent = {};\n for (const [key, value] of Object.entries(record)) {\n if (value !== undefined) out[key] = value;\n }\n return out;\n}\n\n/**\n * Translate one RuntimeBus event into the otium `WsServerMessage`-shaped raw\n * object the hub applies verbatim (field names matter — the hub does no\n * schema validation). Returns null for events the worker must not forward.\n */\nexport function translateBusEvent(event: RuntimeBusEvent): RawEvent | null {\n const topicId = event.topicId;\n if (event.type === \"message\") {\n return { type: \"message\", topicId, message: event.payload };\n }\n if (event.type === \"message-updated\") {\n const payload = event.payload as { messageId: string; patch: Record<string, unknown> };\n return defined({\n type: \"message_updated\",\n topicId,\n messageId: payload.messageId,\n text: payload.patch.text,\n deleted: payload.patch.deleted,\n editedAt: payload.patch.editedAt,\n usage: payload.patch.usage,\n });\n }\n if (event.type !== \"ai-status\") return null;\n const status = event.payload as RawEvent;\n const kind = typeof status.kind === \"string\" ? status.kind : \"\";\n switch (kind) {\n case \"typing\":\n return { type: \"typing\", topicId, userId: status.userId ?? \"\" };\n case \"tool_call\":\n return defined({\n type: \"tool_call\",\n topicId,\n queryId: status.queryId,\n name: status.name,\n input: status.input,\n label: status.label,\n toolUseId: status.toolUseId,\n });\n case \"tool_output\":\n return defined({\n type: \"tool_output\",\n topicId,\n queryId: status.queryId,\n toolUseId: status.toolUseId,\n content: status.content,\n });\n case \"tool_status\":\n // bus.ts stores the WS `kind` field as `statusKind` (the outer `kind`\n // slot carries the event discriminator).\n return defined({\n type: \"tool_status\",\n topicId,\n queryId: status.queryId,\n kind: status.statusKind,\n content: status.content,\n toolName: status.toolName,\n elapsed: status.elapsed,\n });\n case \"file_ready\":\n return defined({\n type: \"file_ready\",\n topicId,\n queryId: status.queryId,\n path: status.path,\n source: status.source,\n });\n case \"visual\":\n return defined({\n type: \"visual\",\n topicId,\n queryId: status.queryId,\n url: status.url,\n id: status.id,\n title: status.title,\n kind: status.visualKind,\n });\n case \"ai_done\":\n return defined({\n type: \"ai_done\",\n topicId,\n queryId: status.queryId,\n usage: status.usage,\n agent: status.agent,\n model: status.model,\n });\n case \"ai_error\":\n return defined({\n type: \"ai_error\",\n topicId,\n queryId: status.queryId,\n error: status.error,\n });\n case \"ai_aborted\":\n return defined({\n type: \"ai_aborted\",\n topicId,\n queryId: status.queryId,\n reason: status.reason,\n });\n default:\n // ai_active and anything future-shaped is not in FORWARDED_TYPES.\n return null;\n }\n}\n\n// ── Per-turn forwarder ───────────────────────────────────────────────\n\nexport interface TurnForwarder {\n requestId: string;\n /** Local queryId of the running turn; events from other turns are dropped. */\n queryId: string | null;\n finished: boolean;\n deliveryBlocked: boolean;\n /** Number of closures retained by the ordered promise queue. */\n pendingEvents: number;\n seq: number;\n chain: Promise<void>;\n /** Feed one already-translated raw event through filter → seq → delivery. */\n tap: (raw: RawEvent) => void;\n /** Send a synthetic terminal (superseded / dispatch failure) and clean up. */\n finish: (event: RawEvent) => void;\n}\n\n/** localTopicId → the forwarder of its in-flight peer turn. */\nconst activeForwarders = new Map<string, TurnForwarder>();\n\nexport function getActiveForwarder(localTopicId: string): TurnForwarder | undefined {\n return activeForwarders.get(localTopicId);\n}\n\nexport function createTurnForwarder(opts: {\n hostNodeId: string;\n requestId: string;\n localTopicId: string;\n sendEvent: SendPeerEvent;\n /** Test seam — production keeps the contract's 100ms base backoff. */\n retryBaseMs?: number;\n /** Test/host seam. One slot is reserved for a synthetic overflow terminal. */\n maxPendingEvents?: number;\n}): TurnForwarder {\n const { hostNodeId, requestId, localTopicId, sendEvent } = opts;\n const retryBaseMs = opts.retryBaseMs ?? PEER_EVENT_RETRY_BASE_MS;\n const maxPendingEvents = Math.max(2, opts.maxPendingEvents ?? PEER_EVENT_MAX_PENDING);\n const forwarder: TurnForwarder = {\n requestId,\n queryId: null,\n finished: false,\n deliveryBlocked: false,\n pendingEvents: 0,\n seq: 0,\n chain: Promise.resolve(),\n tap: () => {},\n finish: () => {},\n };\n\n let terminalQueued = false;\n\n const detach = () => {\n forwarder.finished = true;\n if (activeForwarders.get(localTopicId) === forwarder) {\n activeForwarders.delete(localTopicId);\n }\n };\n\n const post = (event: RawEvent) => {\n const isTerminal = TERMINAL_TYPES.has(String(event.type ?? \"\"));\n if (isTerminal) terminalQueued = true;\n forwarder.seq += 1;\n const seq = forwarder.seq;\n forwarder.pendingEvents += 1;\n forwarder.chain = forwarder.chain.then(async () => {\n try {\n if (forwarder.deliveryBlocked) return;\n // Prior seqs are now acknowledged. Persist immediately before the\n // first terminal send, closing the crash window without retaining a\n // terminal that can never cross an earlier permanent gap.\n if (isTerminal) {\n upsertPeerTerminalOutbox({ hostNodeId, requestId, seq, event });\n }\n for (let attempt = 1; attempt <= PEER_EVENT_MAX_ATTEMPTS; attempt++) {\n const result = await sendEvent({ v: PEER_PROTOCOL_VERSION, requestId, seq, event });\n if (result.ok) {\n if (isTerminal) acknowledgePeerTerminal(hostNodeId, requestId);\n return;\n }\n logger.warn(\n { requestId, seq, type: event.type, attempt, error: result.error },\n \"otium: peer event delivery to hub failed\",\n );\n if (attempt < PEER_EVENT_MAX_ATTEMPTS) {\n const delayMs = retryBaseMs * 2 ** (attempt - 1);\n await new Promise((resolve) => setTimeout(resolve, delayMs));\n }\n }\n // Never send seq N+1 after seq N was lost. A terminal stays in the\n // durable outbox and the reconnect flusher retries its exact envelope.\n forwarder.deliveryBlocked = true;\n logger.error({ requestId, seq, type: event.type }, \"otium: peer event delivery exhausted\");\n } finally {\n forwarder.pendingEvents -= 1;\n }\n });\n };\n\n forwarder.tap = (raw: RawEvent) => {\n if (forwarder.finished) return;\n const type = String(raw.type ?? \"\");\n if (!FORWARDED_TYPES.has(type)) return;\n // Attribute only this turn's events: overlapping aborted events from a\n // preempted previous turn carry a different queryId and were already\n // settled by that turn's synthetic terminal.\n if (type === \"message\") {\n const message = raw.message as { queryId?: string; authorId?: string } | undefined;\n if (\n message?.authorId === \"ai\" &&\n forwarder.queryId &&\n message.queryId !== forwarder.queryId\n ) {\n return;\n }\n } else if (type !== \"typing\") {\n const queryId = raw.queryId;\n if (forwarder.queryId && typeof queryId === \"string\" && queryId !== forwarder.queryId) {\n return;\n }\n }\n const isTerminal = TERMINAL_TYPES.has(type);\n if (!isTerminal && forwarder.pendingEvents >= maxPendingEvents - 1) {\n // Do not retain an unbounded Promise chain under a noisy tool stream.\n // Since no seq was assigned to this dropped event, a synthetic terminal\n // remains contiguous and occupies the queue's reserved final slot.\n if (!terminalQueued) {\n post({\n type: \"ai_error\",\n topicId: localTopicId,\n queryId: forwarder.queryId ?? requestId,\n error: `worker event queue saturated (${maxPendingEvents})`,\n });\n detach();\n }\n return;\n }\n post(raw);\n if (isTerminal) detach();\n };\n\n forwarder.finish = (event: RawEvent) => {\n if (forwarder.finished) return;\n post(event);\n detach();\n };\n\n return forwarder;\n}\n\n/** Register the turn's forwarder as the topic's WsHub-tap equivalent. */\nexport function registerTurnForwarder(localTopicId: string, forwarder: TurnForwarder): void {\n activeForwarders.set(localTopicId, forwarder);\n ensureBackflowSubscription();\n}\n\n// ── Global bus subscription (otium's registerTopicTap equivalent) ────\n\nlet unsubscribe: (() => void) | null = null;\nlet terminalOutboxTimer: ReturnType<typeof setInterval> | null = null;\nlet terminalOutboxFlushInFlight = false;\n\n/** Retry exact terminal envelopes left by a lost ACK or worker restart. */\nexport async function flushPeerTerminalOutbox(): Promise<number> {\n if (terminalOutboxFlushInFlight) return 0;\n terminalOutboxFlushInFlight = true;\n let acknowledged = 0;\n try {\n for (const row of listPeerTerminalOutbox()) {\n const node = await resolvePeerNodeByCellId(row.host_node_id).catch(() => null);\n if (!node) continue;\n let event: RawEvent;\n try {\n event = JSON.parse(row.event_json) as RawEvent;\n } catch {\n continue;\n }\n const result = await hubEventSender(node)({\n v: PEER_PROTOCOL_VERSION,\n requestId: row.request_id,\n seq: row.seq,\n event,\n });\n if (result.ok && acknowledgePeerTerminal(row.host_node_id, row.request_id)) acknowledged += 1;\n }\n return acknowledged;\n } finally {\n terminalOutboxFlushInFlight = false;\n }\n}\n\nfunction onBusEvent(event: RuntimeBusEvent): void {\n const forwarder = activeForwarders.get(event.topicId);\n if (!forwarder) return;\n const raw = translateBusEvent(event);\n if (raw) forwarder.tap(raw);\n}\n\nfunction ensureBackflowSubscription(): void {\n if (!unsubscribe) unsubscribe = runtimeBus().subscribe(onBusEvent);\n}\n\n/** Subscribe the backflow tap to the RuntimeBus. Returns a stop function. */\nexport function startEventBackflow(): () => void {\n ensureBackflowSubscription();\n if (!terminalOutboxTimer) {\n void flushPeerTerminalOutbox();\n terminalOutboxTimer = setInterval(() => void flushPeerTerminalOutbox(), 5_000);\n terminalOutboxTimer.unref?.();\n }\n return stopEventBackflow;\n}\n\nexport function stopEventBackflow(): void {\n unsubscribe?.();\n unsubscribe = null;\n if (terminalOutboxTimer) clearInterval(terminalOutboxTimer);\n terminalOutboxTimer = null;\n activeForwarders.clear();\n}\n",
7
- "import { randomUUID } from \"node:crypto\";\nimport { copyFileSync, mkdirSync, rmSync, statSync } from \"node:fs\";\nimport { basename, extname, join } from \"node:path\";\nimport type { AttachmentDto } from \"@negotium/core\";\nimport { DATA_DIR, db, type FileHooks, fileHooks, setFileHooks } from \"@negotium/core\";\n\nconst PEER_FILES_DIR = join(DATA_DIR, \"otium-peer-files\");\n\ndb.exec(`\n CREATE TABLE IF NOT EXISTS otium_peer_files (\n id TEXT PRIMARY KEY,\n topic_id TEXT,\n owner_user_id TEXT,\n filename TEXT NOT NULL,\n mime_type TEXT NOT NULL,\n size_bytes INTEGER NOT NULL,\n path TEXT NOT NULL,\n created_at TEXT NOT NULL\n )\n`);\n\ninterface PeerFileRow {\n id: string;\n topic_id: string | null;\n owner_user_id: string | null;\n filename: string;\n mime_type: string;\n size_bytes: number;\n path: string;\n}\n\nfunction fileType(mimeType: string): AttachmentDto[\"type\"] {\n if (mimeType.startsWith(\"image/\")) return \"image\";\n if (mimeType.startsWith(\"audio/\")) return \"audio\";\n return \"file\";\n}\n\nfunction attachment(row: PeerFileRow): AttachmentDto {\n return {\n id: row.id,\n type: fileType(row.mime_type),\n filename: row.filename,\n url: `/api/v1/peer/files/${row.id}`,\n mimeType: row.mime_type,\n sizeBytes: row.size_bytes,\n };\n}\n\nfunction rowFor(fileId: string): PeerFileRow | null {\n return (\n db.query<PeerFileRow, [string]>(\"SELECT * FROM otium_peer_files WHERE id = ?\").get(fileId) ??\n null\n );\n}\n\nexport function peerFileAllowsAccess(\n fileId: string,\n access: { topicId: string; ownerUserId: string },\n): boolean {\n const row = rowFor(fileId);\n return row?.topic_id === access.topicId && row.owner_user_id === access.ownerUserId;\n}\n\nfunction safeFilename(filename: string): string {\n const value = basename(filename)\n .replace(/[^A-Za-z0-9._ -]/g, \"_\")\n .slice(0, 120);\n return value || \"upload\";\n}\n\nfunction mimeFromPath(path: string): string {\n const extension = extname(path).toLowerCase();\n const known: Record<string, string> = {\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n \".mp4\": \"video/mp4\",\n \".webm\": \"video/webm\",\n \".pdf\": \"application/pdf\",\n \".txt\": \"text/plain\",\n };\n return known[extension] ?? \"application/octet-stream\";\n}\n\nfunction recordFile(args: {\n id: string;\n path: string;\n sizeBytes: number;\n filename: string;\n mimeType: string;\n topicId?: string;\n ownerUserId?: string;\n}): AttachmentDto {\n db.run(\n `INSERT INTO otium_peer_files\n (id, topic_id, owner_user_id, filename, mime_type, size_bytes, path, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,\n [\n args.id,\n args.topicId ?? null,\n args.ownerUserId ?? null,\n args.filename,\n args.mimeType,\n args.sizeBytes,\n args.path,\n new Date().toISOString(),\n ],\n );\n return attachment({\n id: args.id,\n topic_id: args.topicId ?? null,\n owner_user_id: args.ownerUserId ?? null,\n filename: args.filename,\n mime_type: args.mimeType,\n size_bytes: args.sizeBytes,\n path: args.path,\n });\n}\n\nfunction insertLocalFile(args: {\n sourcePath: string;\n filename: string;\n mimeType: string;\n topicId?: string;\n ownerUserId?: string;\n}): AttachmentDto {\n const id = randomUUID();\n mkdirSync(PEER_FILES_DIR, { recursive: true });\n const path = join(PEER_FILES_DIR, `${id}-${safeFilename(args.filename)}`);\n copyFileSync(args.sourcePath, path);\n return recordFile({ id, path, sizeBytes: statSync(path).size, ...args });\n}\n\nfunction deletePeerFilesForTopic(topicId: string): void {\n const rows = db\n .query<Pick<PeerFileRow, \"path\">, [string]>(\n \"SELECT path FROM otium_peer_files WHERE topic_id = ?\",\n )\n .all(topicId);\n db.run(\"DELETE FROM otium_peer_files WHERE topic_id = ?\", [topicId]);\n for (const row of rows) rmSync(row.path, { force: true });\n}\n\nexport async function storePeerInputFile(\n file: File,\n access: { topicId: string; ownerUserId: string },\n): Promise<AttachmentDto> {\n const id = randomUUID();\n mkdirSync(PEER_FILES_DIR, { recursive: true });\n const filename = file.name || \"upload\";\n const path = join(PEER_FILES_DIR, `${id}-${safeFilename(filename)}`);\n const sizeBytes = await Bun.write(path, file);\n return recordFile({\n id,\n path,\n sizeBytes,\n filename,\n mimeType: file.type || \"application/octet-stream\",\n ...access,\n });\n}\n\nexport function installPeerFileHooks(): () => void {\n const previous = fileHooks();\n const hooks: FileHooks = {\n resolveAttachmentByFileId(fileId) {\n const row = rowFor(fileId);\n return row ? attachment(row) : previous.resolveAttachmentByFileId(fileId);\n },\n resolveUploadedFilePathByFileId(fileId) {\n return rowFor(fileId)?.path ?? previous.resolveUploadedFilePathByFileId(fileId);\n },\n storeLocalFileAsUpload(path, access) {\n const existing = previous.storeLocalFileAsUpload(path, access);\n if (existing) return existing;\n return insertLocalFile({\n sourcePath: path,\n filename: basename(path),\n mimeType: mimeFromPath(path),\n topicId: access?.topicId,\n ownerUserId: access?.ownerUserId,\n });\n },\n async deleteFilesForTopic(topicId) {\n await previous.deleteFilesForTopic?.(topicId);\n deletePeerFilesForTopic(topicId);\n },\n };\n setFileHooks(hooks);\n return () => {\n if (fileHooks() === hooks) setFileHooks(previous);\n };\n}\n",
8
- "/** Worker-side runtime MCP mutations that must execute on Otium's canonical hub. */\n\nimport { randomUUID } from \"node:crypto\";\n\nimport {\n errorResult,\n logger,\n type McpToolResult,\n type PeerRuntimeBridge,\n resolveAttachmentByFileId,\n resolveUploadedFilePathByFileId,\n} from \"@negotium/core\";\nimport { mintPeerToken, resolvePeerNodeByCellId } from \"@/central\";\nimport { getActiveForwarder } from \"@/event-backflow\";\n\nconst PEER_BRIDGE_TIMEOUT_MS = 15_000;\n\nfunction isMcpToolResult(value: unknown): value is McpToolResult {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n const result = value as Partial<McpToolResult>;\n return (\n Array.isArray(result.content) &&\n result.content.every(\n (entry) =>\n entry !== null &&\n typeof entry === \"object\" &&\n (entry as { type?: unknown }).type === \"text\" &&\n typeof (entry as { text?: unknown }).text === \"string\",\n ) &&\n (result.isError === undefined || result.isError === true)\n );\n}\n\nexport const otiumPeerRuntimeBridge = {\n async flushEvents(localTopicId) {\n const forwarder = getActiveForwarder(localTopicId);\n if (!forwarder) return false;\n await forwarder.chain;\n return !forwarder.deliveryBlocked;\n },\n async spawnSubagent(request) {\n const hubNode = await resolvePeerNodeByCellId(request.bridge.hubCellId).catch(() => null);\n if (!hubNode) return errorResult(\"Error: Hub node is no longer attached.\");\n\n let token: string;\n try {\n token = await mintPeerToken(hubNode.cellId);\n } catch (err) {\n return errorResult(`Error: Failed to spawn on hub: ${(err as Error).message}`);\n }\n\n let response: Response;\n try {\n response = await fetch(`${hubNode.baseUrl.replace(/\\/+$/, \"\")}/api/v1/peer/bridge/spawn`, {\n method: \"POST\",\n headers: {\n authorization: `Bearer ${token}`,\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify({\n hostQueryId: request.bridge.hostQueryId,\n userId: request.userId,\n agent: request.agent,\n ...(request.model ? { model: request.model } : {}),\n input: request.input,\n }),\n signal: AbortSignal.timeout(PEER_BRIDGE_TIMEOUT_MS),\n });\n } catch (err) {\n logger.warn({ err, node: hubNode.nodeName }, \"otium: spawn bridge hub unreachable\");\n return errorResult(\n `Error: Failed to spawn on hub: node \"${hubNode.nodeName ?? hubNode.cellId}\" unreachable`,\n );\n }\n\n const parsed = (await response.json().catch(() => null)) as {\n ok?: boolean;\n error?: string;\n result?: unknown;\n } | null;\n if (!response.ok || !parsed?.ok) {\n return errorResult(\n `Error: Failed to spawn on hub: ${parsed?.error ?? `peer call failed (${response.status})`}`,\n );\n }\n if (!isMcpToolResult(parsed.result)) {\n return errorResult(\"Error: Failed to spawn on hub: invalid tool result\");\n }\n return parsed.result;\n },\n async askUser(request) {\n const hubNode = await resolvePeerNodeByCellId(request.bridge.hubCellId).catch(() => null);\n if (!hubNode) return errorResult(\"Error: Hub node is no longer attached.\");\n let token: string;\n try {\n token = await mintPeerToken(hubNode.cellId);\n } catch (error) {\n return errorResult(`Error: Failed to open hub question: ${(error as Error).message}`);\n }\n const bridgeRequestId = `bridge-ask-${randomUUID()}`;\n const baseUrl = hubNode.baseUrl.replace(/\\/+$/, \"\");\n const post = async (path: string, body: Record<string, unknown>) => {\n const response = await fetch(`${baseUrl}${path}`, {\n method: \"POST\",\n headers: {\n authorization: `Bearer ${token}`,\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(PEER_BRIDGE_TIMEOUT_MS),\n });\n const parsed = (await response.json().catch(() => null)) as {\n ok?: boolean;\n pending?: boolean;\n result?: unknown;\n error?: string;\n } | null;\n return { response, parsed };\n };\n try {\n const started = await post(\"/api/v1/peer/bridge/ask/start\", {\n hostQueryId: request.bridge.hostQueryId,\n bridgeRequestId,\n userId: request.userId,\n agent: request.agent,\n ...(request.model ? { model: request.model } : {}),\n input: request.input,\n });\n if (!started.response.ok || !started.parsed?.ok) {\n return errorResult(\n `Error: Failed to open hub question: ${started.parsed?.error ?? `peer call failed (${started.response.status})`}`,\n );\n }\n for (;;) {\n await Bun.sleep(500);\n const polled = await post(\"/api/v1/peer/bridge/ask/result\", {\n hostQueryId: request.bridge.hostQueryId,\n bridgeRequestId,\n });\n if (!polled.response.ok || !polled.parsed?.ok) {\n return errorResult(\n `Error: Failed to read hub answer: ${polled.parsed?.error ?? `peer call failed (${polled.response.status})`}`,\n );\n }\n if (polled.parsed.pending !== false) continue;\n if (!isMcpToolResult(polled.parsed.result)) {\n return errorResult(\"Error: Failed to read hub answer: invalid tool result\");\n }\n return polled.parsed.result;\n }\n } catch (error) {\n return errorResult(`Error: Hub question bridge failed: ${(error as Error).message}`);\n }\n },\n async selfConfig(request) {\n const hubNode = await resolvePeerNodeByCellId(request.bridge.hubCellId).catch(() => null);\n if (!hubNode) return errorResult(\"Error: Hub node is no longer attached.\");\n try {\n const token = await mintPeerToken(hubNode.cellId);\n const response = await fetch(\n `${hubNode.baseUrl.replace(/\\/+$/, \"\")}/api/v1/peer/bridge/self-config`,\n {\n method: \"POST\",\n headers: {\n authorization: `Bearer ${token}`,\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify({\n hostQueryId: request.bridge.hostQueryId,\n userId: request.userId,\n tool: request.tool,\n input: request.input,\n ...(request.currentUserPrompt ? { currentUserPrompt: request.currentUserPrompt } : {}),\n }),\n signal: AbortSignal.timeout(PEER_BRIDGE_TIMEOUT_MS),\n },\n );\n const body = (await response.json().catch(() => null)) as {\n ok?: boolean;\n result?: unknown;\n error?: string;\n } | null;\n if (!response.ok || !body?.ok) {\n return errorResult(\n `Error: Failed to update hub topic config: ${body?.error ?? `peer call failed (${response.status})`}`,\n );\n }\n return isMcpToolResult(body.result)\n ? body.result\n : errorResult(\"Error: Failed to update hub topic config: invalid tool result\");\n } catch (error) {\n return errorResult(`Error: Hub self-config bridge failed: ${(error as Error).message}`);\n }\n },\n async showVisual(request) {\n const hubNode = await resolvePeerNodeByCellId(request.bridge.hubCellId).catch(() => null);\n if (!hubNode) return { ok: false, error: \"hub node is no longer attached\" };\n let token: string;\n try {\n token = await mintPeerToken(hubNode.cellId);\n } catch (error) {\n return { ok: false, error: `peer token mint failed: ${(error as Error).message}` };\n }\n\n let hubFileId = request.fileId;\n if (request.kind === \"image\" || request.kind === \"video\") {\n const localPath = request.fileId ? resolveUploadedFilePathByFileId(request.fileId) : null;\n const localAttachment = request.fileId ? resolveAttachmentByFileId(request.fileId) : null;\n if (!localPath || !localAttachment) {\n return { ok: false, error: \"worker media file is unavailable\" };\n }\n const form = new FormData();\n form.set(\"hostQueryId\", request.bridge.hostQueryId);\n form.set(\"userId\", request.userId);\n form.set(\"agent\", request.agent);\n if (request.model) form.set(\"model\", request.model);\n form.set(\"announce\", \"false\");\n form.set(\n \"file\",\n Bun.file(localPath, { type: localAttachment.mimeType }),\n localAttachment.filename,\n );\n const fileResponse = await fetch(\n `${hubNode.baseUrl.replace(/\\/+$/, \"\")}/api/v1/peer/bridge/file`,\n {\n method: \"POST\",\n headers: { authorization: `Bearer ${token}` },\n body: form,\n signal: AbortSignal.timeout(PEER_BRIDGE_TIMEOUT_MS),\n },\n ).catch(() => null);\n const fileBody = fileResponse\n ? ((await fileResponse.json().catch(() => null)) as {\n ok?: boolean;\n error?: string;\n attachment?: { id?: string };\n } | null)\n : null;\n if (!fileResponse?.ok || !fileBody?.ok || !fileBody.attachment?.id) {\n return { ok: false, error: fileBody?.error ?? \"hub media upload failed\" };\n }\n hubFileId = fileBody.attachment.id;\n }\n\n const response = await fetch(\n `${hubNode.baseUrl.replace(/\\/+$/, \"\")}/api/v1/peer/bridge/visual`,\n {\n method: \"POST\",\n headers: {\n authorization: `Bearer ${token}`,\n \"content-type\": \"application/json\",\n },\n body: JSON.stringify({\n hostQueryId: request.bridge.hostQueryId,\n userId: request.userId,\n kind: request.kind,\n ...(request.title ? { title: request.title } : {}),\n ...(request.html ? { html: request.html } : {}),\n ...(request.code ? { code: request.code } : {}),\n ...(request.theme ? { theme: request.theme } : {}),\n ...(hubFileId ? { fileId: hubFileId } : {}),\n ...(request.mimeType ? { mimeType: request.mimeType } : {}),\n ...(request.source ? { source: request.source } : {}),\n }),\n signal: AbortSignal.timeout(PEER_BRIDGE_TIMEOUT_MS),\n },\n ).catch(() => null);\n const body = response\n ? ((await response.json().catch(() => null)) as {\n ok?: boolean;\n error?: string;\n id?: number;\n url?: string;\n title?: string | null;\n } | null)\n : null;\n if (!response?.ok || !body?.ok || typeof body.id !== \"number\" || !body.url) {\n return { ok: false, error: body?.error ?? \"hub visual bridge failed\" };\n }\n return { ok: true, id: body.id, url: body.url, title: body.title ?? null };\n },\n async sendFile(request) {\n const hubNode = await resolvePeerNodeByCellId(request.bridge.hubCellId).catch(() => null);\n if (!hubNode) return { ok: false, error: \"hub node is no longer attached\" };\n try {\n const token = await mintPeerToken(hubNode.cellId);\n const form = new FormData();\n form.set(\"hostQueryId\", request.bridge.hostQueryId);\n form.set(\"userId\", request.userId);\n form.set(\"agent\", request.agent);\n if (request.model) form.set(\"model\", request.model);\n form.set(\"announce\", \"true\");\n form.set(\"file\", Bun.file(request.path), request.path.split(\"/\").pop() ?? \"output\");\n const response = await fetch(\n `${hubNode.baseUrl.replace(/\\/+$/, \"\")}/api/v1/peer/bridge/file`,\n {\n method: \"POST\",\n headers: { authorization: `Bearer ${token}` },\n body: form,\n signal: AbortSignal.timeout(PEER_BRIDGE_TIMEOUT_MS),\n },\n );\n const body = (await response.json().catch(() => null)) as {\n ok?: boolean;\n error?: string;\n } | null;\n return response.ok && body?.ok\n ? { ok: true }\n : { ok: false, error: body?.error ?? `peer call failed (${response.status})` };\n } catch (error) {\n return { ok: false, error: (error as Error).message };\n }\n },\n} satisfies PeerRuntimeBridge;\n",
9
- "import {\n clearPendingAsk,\n deliverAskCallbackToCaller,\n logger,\n type PeerForwardArgs,\n type PeerForwardResult,\n type PeerSessionBridge,\n type RemoteReplyRoute,\n} from \"@negotium/core\";\nimport {\n listPeerNodes,\n mintPeerToken,\n type PeerNode,\n resolvePeerNodeByCellId,\n selfPeerNode,\n} from \"@/central\";\nimport { PEER_PROTOCOL_VERSION, type PeerSessionEntry } from \"@/protocol\";\nimport {\n createRemoteAsk,\n deletePeerReplyOutbox,\n deleteRemoteAsk,\n getRemoteAsk,\n listPeerReplyOutbox,\n pruneRemoteAsks,\n upsertPeerReplyOutbox,\n} from \"@/store\";\n\nconst PEER_TIMEOUT_MS = 15_000;\nconst PENDING_ASK_TTL_MS = 15 * 60 * 1000;\n\nfunction prunePendingRemoteAsks(now = Date.now()): void {\n pruneRemoteAsks(now - PENDING_ASK_TTL_MS);\n}\n\nasync function postPeer<T = Record<string, never>>(\n node: PeerNode,\n path: string,\n body: Record<string, unknown>,\n): Promise<\n ({ ok: true } & T) | { ok: false; error: string; ambiguous?: boolean; status?: number }\n> {\n try {\n const token = await mintPeerToken(node.cellId);\n const response = await fetch(`${node.baseUrl.replace(/\\/+$/, \"\")}${path}`, {\n method: \"POST\",\n headers: { authorization: `Bearer ${token}`, \"content-type\": \"application/json\" },\n body: JSON.stringify(body),\n signal: AbortSignal.timeout(PEER_TIMEOUT_MS),\n });\n const parsed = (await response.json().catch(() => null)) as\n | ({ ok?: boolean; error?: string } & T)\n | null;\n if (!response.ok || !parsed?.ok) {\n return {\n ok: false,\n error: parsed?.error ?? `peer call failed (${response.status})`,\n status: response.status,\n ...(response.status >= 500 ? { ambiguous: true } : {}),\n };\n }\n return parsed as { ok: true } & T;\n } catch (error) {\n return {\n ok: false,\n error: (error as Error).message || \"peer node unreachable\",\n ambiguous: true,\n };\n }\n}\n\nasync function postPeerIdempotent<T = Record<string, never>>(\n node: PeerNode,\n path: string,\n body: Record<string, unknown>,\n): ReturnType<typeof postPeer<T>> {\n let result = await postPeer<T>(node, path, body);\n for (const delayMs of [50, 150]) {\n if (result.ok || !result.ambiguous) return result;\n await Bun.sleep(delayMs);\n result = await postPeer<T>(node, path, body);\n }\n return result;\n}\n\nasync function peerSupportsRemoteAsk(node: PeerNode): Promise<boolean> {\n try {\n const token = await mintPeerToken(node.cellId);\n const response = await fetch(`${node.baseUrl.replace(/\\/+$/, \"\")}/api/v1/peer/capabilities`, {\n headers: { authorization: `Bearer ${token}` },\n signal: AbortSignal.timeout(PEER_TIMEOUT_MS),\n });\n const body = (await response.json().catch(() => null)) as {\n ok?: boolean;\n features?: { remoteAsk?: boolean };\n } | null;\n return response.ok && body?.ok === true && body.features?.remoteAsk === true;\n } catch {\n return false;\n }\n}\n\nasync function findNode(nodeName: string): Promise<PeerNode | null> {\n const find = (nodes: PeerNode[]) => nodes.find((node) => node.nodeName === nodeName) ?? null;\n return find(await listPeerNodes()) ?? find(await listPeerNodes({ fresh: true }));\n}\n\nasync function originLabel(args: PeerForwardArgs): Promise<string> {\n const self = await selfPeerNode();\n const local = args.fromTitle?.trim() || args.fromKey?.trim() || \"peer\";\n return self?.nodeName ? `${self.nodeName}/${local}` : local;\n}\n\nasync function forward(args: PeerForwardArgs): Promise<PeerForwardResult> {\n const node = await findNode(args.toNode).catch(() => null);\n if (!node || node.self) return { ok: false, error: `unknown remote node \"${args.toNode}\"` };\n const self = await selfPeerNode().catch(() => null);\n if (!self) return { ok: false, error: \"local peer node is not attached\" };\n if (!self.isPrimary && !node.isPrimary) {\n return { ok: false, error: \"worker peer calls must target the primary hub\" };\n }\n const fromLabel = await originLabel(args);\n const requestId = args.requestId;\n\n if (args.action === \"ask\") {\n if (!requestId || !args.fromTopicId || !args.fromKey || !args.message) {\n return { ok: false, error: \"remote ask is missing caller metadata\" };\n }\n if (!(await peerSupportsRemoteAsk(node))) {\n return { ok: false, error: `node \"${args.toNode}\" does not support remote ask` };\n }\n prunePendingRemoteAsks();\n const created = createRemoteAsk({\n requestId,\n expectedCellId: node.cellId,\n userId: args.userId,\n callerTopicId: args.fromTopicId,\n from: args.fromKey,\n to: `${args.toNode}/${args.toTopic}`,\n ...(node.isPrimary && args.sourceQueryId ? { sourceQueryId: args.sourceQueryId } : {}),\n });\n if (!created) {\n return { ok: false, error: `remote ask requestId \"${requestId}\" is already pending` };\n }\n const result = await postPeerIdempotent(node, \"/api/v1/peer/ask\", {\n v: PEER_PROTOCOL_VERSION,\n requestId,\n userId: args.userId,\n toTopic: args.toTopic,\n fromLabel,\n message: args.message,\n fromDepth: args.fromDepth ?? 0,\n replyTo: { topicId: args.fromTopicId },\n ...(args.sourceQueryId ? { sourceQueryId: args.sourceQueryId } : {}),\n });\n if (!result.ok) {\n if (!result.ambiguous) {\n deleteRemoteAsk(requestId);\n return result;\n }\n // The peer may have accepted the idempotent request before its response\n // was lost. Keep the durable route so a late reply remains deliverable.\n logger.warn(\n { requestId, node: node.nodeName, error: result.error },\n \"otium: remote ask acceptance is uncertain; preserving durable reply route\",\n );\n return { ok: true };\n }\n return result;\n }\n\n if (args.action === \"tell\") {\n if (!requestId || !args.message) return { ok: false, error: \"remote tell is incomplete\" };\n const result = await postPeerIdempotent(node, \"/api/v1/peer/tell\", {\n v: PEER_PROTOCOL_VERSION,\n requestId,\n userId: args.userId,\n toTopic: args.toTopic,\n fromLabel,\n message: args.message,\n depth: args.depth ?? 0,\n ...(args.sourceQueryId ? { sourceQueryId: args.sourceQueryId } : {}),\n });\n if (!result.ok && result.ambiguous) {\n // tell is idempotently claimed by requestId at the receiver. Reporting a\n // hard failure here encourages callers to retry with a fresh requestId,\n // which can duplicate a tell that was accepted before its response was\n // lost. Same-id retries above are the safe retry boundary.\n logger.warn(\n { requestId, node: node.nodeName, error: result.error },\n \"otium: remote tell delivery is uncertain after idempotent retries\",\n );\n return { ok: true };\n }\n return result;\n }\n\n return postPeer(node, \"/api/v1/peer/abort\", {\n v: PEER_PROTOCOL_VERSION,\n userId: args.userId,\n toTopic: args.toTopic,\n ...(requestId ? { requestId } : {}),\n ...(args.sourceQueryId ? { sourceQueryId: args.sourceQueryId } : {}),\n });\n}\n\nasync function sessions(userId: string, sourceQueryId?: string) {\n const nodes = await listPeerNodes().catch(() => []);\n const self = nodes.find((node) => node.self);\n if (!self) return { ok: false, nodes: [] };\n return {\n ok: true,\n nodes: await Promise.all(\n nodes\n .filter((node) => !node.self && node.nodeName && (self.isPrimary || node.isPrimary))\n .map(async (node) => {\n const result = await postPeer<{ sessions: PeerSessionEntry[] }>(\n node,\n \"/api/v1/peer/sessions\",\n {\n v: PEER_PROTOCOL_VERSION,\n userId,\n ...(sourceQueryId ? { sourceQueryId } : {}),\n },\n );\n return result.ok\n ? { node: node.nodeName as string, sessions: result.sessions }\n : { node: node.nodeName as string, error: result.error };\n }),\n ),\n };\n}\n\nasync function reply(\n route: RemoteReplyRoute,\n sourceTitle: string,\n replyText: string,\n kind: \"reply\" | \"error\",\n): Promise<boolean> {\n upsertPeerReplyOutbox({\n nodeCellId: route.nodeCellId,\n requestId: route.requestId,\n nodeName: route.nodeName,\n topicId: route.topicId,\n userId: route.userId,\n sourceTitle,\n replyText,\n kind,\n });\n await flushPeerReplyOutbox();\n return true;\n}\n\nlet peerReplyFlush: Promise<void> | null = null;\n\nexport function flushPeerReplyOutbox(): Promise<void> {\n if (peerReplyFlush) return peerReplyFlush;\n peerReplyFlush = (async () => {\n for (const pending of listPeerReplyOutbox()) {\n const node = await resolvePeerNodeByCellId(pending.node_cell_id).catch(() => null);\n if (!node) continue;\n const fromLabel = await originLabel({\n action: \"ask\",\n toNode: pending.node_name,\n toTopic: \"\",\n userId: pending.user_id,\n fromTitle: pending.source_title,\n });\n const result = await postPeer(node, \"/api/v1/peer/reply\", {\n v: PEER_PROTOCOL_VERSION,\n requestId: pending.request_id,\n userId: pending.user_id,\n kind: pending.kind,\n replyText: pending.reply_text,\n fromLabel,\n });\n if (result.ok || !result.ambiguous) {\n deletePeerReplyOutbox(pending.node_cell_id, pending.request_id);\n if (!result.ok && result.status !== 404) {\n logger.warn(\n { requestId: pending.request_id, status: result.status, error: result.error },\n \"otium: dropping definitively rejected peer reply\",\n );\n }\n continue;\n }\n logger.warn(\n { requestId: pending.request_id, error: result.error },\n \"otium: peer reply delivery failed; retained for retry\",\n );\n }\n })().finally(() => {\n peerReplyFlush = null;\n });\n return peerReplyFlush;\n}\n\nexport function startPeerReplyOutboxWorker(): () => void {\n void flushPeerReplyOutbox();\n const timer = setInterval(() => void flushPeerReplyOutbox(), 5_000);\n timer.unref?.();\n return () => clearInterval(timer);\n}\n\nexport type AcceptRemoteAskReplyResult = \"accepted\" | \"retry\" | \"missing\";\n\nexport async function acceptRemoteAskReplyResult(args: {\n fromCellId: string;\n requestId: string;\n userId: string;\n fromLabel: string;\n replyText: string;\n kind: \"reply\" | \"error\";\n}): Promise<AcceptRemoteAskReplyResult> {\n prunePendingRemoteAsks();\n const pending = getRemoteAsk(args.requestId);\n if (!pending || pending.expected_cell_id !== args.fromCellId || pending.user_id !== args.userId) {\n return \"missing\";\n }\n if (pending.source_query_id) {\n const node = await resolvePeerNodeByCellId(pending.expected_cell_id).catch(() => null);\n if (!node?.isPrimary) return \"missing\";\n const delivered = await postPeer(node, \"/api/v1/peer/ask-callback\", {\n v: PEER_PROTOCOL_VERSION,\n requestId: args.requestId,\n sourceQueryId: pending.source_query_id,\n userId: pending.user_id,\n fromLabel: args.fromLabel,\n replyText: args.replyText,\n kind: args.kind,\n });\n if (!delivered.ok) {\n logger.warn(\n { requestId: args.requestId, error: delivered.error },\n \"otium: canonical remote ask callback failed\",\n );\n return delivered.ambiguous ? \"retry\" : \"missing\";\n }\n deleteRemoteAsk(args.requestId);\n clearPendingAsk({\n userId: pending.user_id,\n from: pending.from_key,\n to: pending.to_key,\n requestId: args.requestId,\n });\n return \"accepted\";\n }\n\n const delivered = await deliverAskCallbackToCaller(\n {\n requestId: args.requestId,\n callerTopicId: pending.caller_topic_id,\n callerUserId: pending.user_id,\n pendingAsk: {\n userId: pending.user_id,\n from: pending.from_key,\n to: pending.to_key,\n requestId: args.requestId,\n },\n },\n args.fromLabel,\n args.replyText,\n args.kind,\n );\n if (!delivered) return \"missing\";\n deleteRemoteAsk(args.requestId);\n return \"accepted\";\n}\n\n/** Backward-compatible boolean surface for in-process callers and tests. */\nexport async function acceptRemoteAskReply(\n args: Parameters<typeof acceptRemoteAskReplyResult>[0],\n): Promise<boolean> {\n return (await acceptRemoteAskReplyResult(args)) === \"accepted\";\n}\n\nexport const otiumPeerSessionBridge: PeerSessionBridge = { forward, sessions, reply };\n",
10
- "import { timingSafeEqual } from \"node:crypto\";\nimport type { PeerForwardArgs, PeerSessionBridge, RemoteReplyRoute } from \"@negotium/core\";\nimport { registerPeerSessionBridgeIpcConfig } from \"@negotium/core/peer-session-bridge-ipc\";\n\nconst MAX_BODY_BYTES = 1024 * 1024;\nconst MAX_INFLIGHT = 32;\nconst BODY_TIMEOUT_MS = 10_000;\n\ntype BridgeRequest =\n | { action: \"forward\"; args: PeerForwardArgs }\n | { action: \"sessions\"; userId: string; sourceQueryId?: string }\n | {\n action: \"reply\";\n route: RemoteReplyRoute;\n sourceTitle: string;\n replyText: string;\n kind: \"reply\" | \"error\";\n };\n\nfunction authorized(request: Request, token: string): boolean {\n const supplied = request.headers.get(\"authorization\")?.replace(/^Bearer\\s+/i, \"\") ?? \"\";\n const expectedBytes = Buffer.from(token);\n const suppliedBytes = Buffer.from(supplied);\n return (\n expectedBytes.length === suppliedBytes.length && timingSafeEqual(expectedBytes, suppliedBytes)\n );\n}\n\nfunction boundedString(value: unknown, max = 16_384): value is string {\n return typeof value === \"string\" && value.length > 0 && value.length <= max;\n}\n\nfunction validRequest(payload: BridgeRequest): boolean {\n if (!payload || typeof payload !== \"object\" || !boundedString(payload.action, 16)) return false;\n if (payload.action === \"sessions\") return boundedString(payload.userId, 512);\n if (payload.action === \"forward\") {\n const args = payload.args;\n return (\n Boolean(args) &&\n [\"tell\", \"ask\", \"abort\"].includes(args.action) &&\n boundedString(args.toNode, 512) &&\n boundedString(args.toTopic, 512) &&\n boundedString(args.userId, 512) &&\n (args.message === undefined || boundedString(args.message, 256 * 1024))\n );\n }\n if (payload.action === \"reply\") {\n return (\n Boolean(payload.route) &&\n boundedString(payload.route.userId, 512) &&\n boundedString(payload.route.requestId, 512) &&\n boundedString(payload.sourceTitle, 2048) &&\n boundedString(payload.replyText, 256 * 1024) &&\n [\"reply\", \"error\"].includes(payload.kind)\n );\n }\n return false;\n}\n\nasync function readLimitedJson(request: Request): Promise<BridgeRequest | null> {\n const declaredLength = Number(request.headers.get(\"content-length\") ?? \"0\");\n if (Number.isFinite(declaredLength) && declaredLength > MAX_BODY_BYTES) return null;\n const reader = request.body?.getReader();\n if (!reader) return null;\n const chunks: Uint8Array[] = [];\n let size = 0;\n const timeout = setTimeout(\n () => void reader.cancel(\"peer bridge request body timeout\").catch(() => undefined),\n BODY_TIMEOUT_MS,\n );\n try {\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n size += value.byteLength;\n if (size > MAX_BODY_BYTES) {\n await reader.cancel();\n return null;\n }\n chunks.push(value);\n }\n } catch {\n return null;\n } finally {\n clearTimeout(timeout);\n }\n try {\n return JSON.parse(Buffer.concat(chunks).toString(\"utf8\")) as BridgeRequest;\n } catch {\n return null;\n }\n}\n\nexport interface PeerSessionBridgeIpcHandle {\n url: string;\n stop(): void;\n}\n\n/** Expose the worker bridge to inherited MCP subprocesses over authenticated loopback IPC. */\nexport function startPeerSessionBridgeIpc(bridge: PeerSessionBridge): PeerSessionBridgeIpcHandle {\n const token = crypto.randomUUID() + crypto.randomUUID();\n let inflight = 0;\n const server = Bun.serve({\n hostname: \"127.0.0.1\",\n port: 0,\n async fetch(request) {\n if (request.method !== \"POST\") return new Response(\"method not allowed\", { status: 405 });\n if (!authorized(request, token)) return new Response(\"unauthorized\", { status: 401 });\n if (inflight >= MAX_INFLIGHT) return new Response(\"busy\", { status: 503 });\n inflight += 1;\n try {\n const payload = await readLimitedJson(request);\n if (!payload || !validRequest(payload)) {\n return new Response(\"invalid request\", { status: 400 });\n }\n if (payload.action === \"forward\") {\n return Response.json(await bridge.forward(payload.args));\n }\n if (payload.action === \"sessions\") {\n return Response.json(await bridge.sessions(payload.userId, payload.sourceQueryId));\n }\n if (payload.action === \"reply\") {\n return Response.json(\n await bridge.reply(payload.route, payload.sourceTitle, payload.replyText, payload.kind),\n );\n }\n return new Response(\"invalid action\", { status: 400 });\n } catch {\n return new Response(\"bridge failed\", { status: 502 });\n } finally {\n inflight -= 1;\n }\n },\n });\n const url = `http://127.0.0.1:${server.port}/`;\n const unregisterConfig = registerPeerSessionBridgeIpcConfig({ url, token });\n let stopped = false;\n\n return {\n url,\n stop() {\n if (stopped) return;\n stopped = true;\n unregisterConfig();\n server.stop(true);\n },\n };\n}\n",
11
- "/**\n * Relay tunnel wire protocol — JSON text frames over a single outbound\n * WebSocket from a runtime node to the central relay.\n *\n * Topology: the NODE always dials the relay (never the reverse), so nodes work\n * behind NAT/firewalls with no inbound connectivity. The node authenticates at\n * the WebSocket upgrade with its runtime-cell secret (Bearer), then sends\n * `register` as its first frame. The relay answers `registered` or\n * `register_error` — version compatibility is negotiated there, not per-frame.\n *\n * Two multiplexed streams ride the tunnel, correlated by `id`:\n * - HTTP: relay→node `http_req_head/chunk/end/abort`, node→relay\n * `http_res_head/chunk/end/error`. Bodies are chunked and base64-encoded.\n * - WebSocket bridging: relay→node `ws_open`, then `ws_data`/`ws_close`\n * flow in both directions.\n *\n * Both ends of this protocol live in this monorepo, but the tunnel is still a\n * network trust boundary. Decoders validate every field before dispatch so a\n * malformed or version-confused peer cannot throw inside a WebSocket callback.\n */\n\nexport const PROTOCOL_VERSION = 2;\n/** Oldest node protocol version the relay still accepts. */\nexport const MIN_PROTOCOL_VERSION = 2;\n\n/** Header list as ordered pairs — preserves duplicates (e.g. set-cookie). */\nexport type HeaderPairs = Array<[string, string]>;\n\n// ── Node → Relay ──────────────────────────────────────────────────\n\nexport type NodeToRelayFrame =\n | { type: \"register\"; protocolVersion: number; nodeVersion?: string }\n | { type: \"pong\"; ts: number }\n | { type: \"http_res_head\"; id: string; status: number; headers: HeaderPairs }\n | { type: \"http_res_chunk\"; id: string; dataB64: string }\n | { type: \"http_res_end\"; id: string }\n | { type: \"http_res_error\"; id: string; message: string }\n | { type: \"ws_open_ok\"; id: string }\n | { type: \"ws_open_error\"; id: string; message: string }\n | { type: \"ws_data\"; id: string; text?: string; dataB64?: string }\n | { type: \"ws_close\"; id: string; code?: number; reason?: string };\n\n// ── Relay → Node ──────────────────────────────────────────────────\n\nexport type RegisterErrorCode = \"upgrade_required\" | \"unauthorized\" | \"replaced\";\n\nexport type RelayToNodeFrame =\n | { type: \"registered\"; nodeId: string; protocolVersion: number; pingIntervalMs: number }\n | { type: \"register_error\"; code: RegisterErrorCode; message: string }\n | { type: \"ping\"; ts: number }\n | {\n type: \"http_req_head\";\n id: string;\n method: string;\n /** Pathname + query, already stripped of the relay's /n/:nodeId prefix. */\n path: string;\n headers: HeaderPairs;\n hasBody: boolean;\n }\n | { type: \"http_req_chunk\"; id: string; dataB64: string }\n | { type: \"http_req_end\"; id: string }\n | { type: \"http_req_abort\"; id: string }\n | {\n type: \"ws_open\";\n id: string;\n path: string;\n /** Authentication context from the public upgrade. Only cookie,\n * authorization, and the relay-selected subprotocol are permitted. */\n headers: HeaderPairs;\n }\n | { type: \"ws_data\"; id: string; text?: string; dataB64?: string }\n | { type: \"ws_close\"; id: string; code?: number; reason?: string };\n\n// ── Codec ─────────────────────────────────────────────────────────\n\nexport function encodeFrame(frame: NodeToRelayFrame | RelayToNodeFrame): string {\n const encoded = JSON.stringify(frame);\n if (\n encoded.length > MAX_FRAME_CHARS ||\n (!decodeNodeFrame(encoded) && !decodeRelayFrame(encoded))\n ) {\n throw new TypeError(\"relay frame exceeds protocol limits or is invalid\");\n }\n return encoded;\n}\n\ntype FrameRecord = Record<string, unknown> & { type: string };\n\nconst HEADER_NAME = /^[!#$%&'*+\\-.^_`|~0-9A-Za-z]+$/;\nconst BASE64 = /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/;\n\nconst MAX_FRAME_CHARS = 512 * 1024;\nexport const MAX_CHUNK_BYTES = 256 * 1024;\nexport const MAX_ENCODED_CHUNK_CHARS = Math.ceil(MAX_CHUNK_BYTES / 3) * 4;\nexport const MAX_HEADER_PAIRS = 128;\nexport const MAX_HEADER_BYTES = 64 * 1024;\nexport const MAX_ID_BYTES = 256;\nexport const MAX_PATH_BYTES = 16 * 1024;\nexport const MAX_MESSAGE_BYTES = 4 * 1024;\nexport const MAX_REASON_BYTES = 123;\nconst MAX_METHOD_BYTES = 32;\nconst MAX_NODE_ID_BYTES = 256;\nconst MAX_NODE_VERSION_BYTES = 256;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction isString(value: unknown): value is string {\n return typeof value === \"string\";\n}\n\nfunction hasMaxBytes(value: string, maxBytes: number): boolean {\n return value.length <= maxBytes && Buffer.byteLength(value, \"utf8\") <= maxBytes;\n}\n\nfunction isBoundedString(value: unknown, maxBytes: number): value is string {\n return isString(value) && hasMaxBytes(value, maxBytes);\n}\n\nfunction isNonEmptyBoundedString(value: unknown, maxBytes: number): value is string {\n return isBoundedString(value, maxBytes) && value.length > 0;\n}\n\nfunction isOptionalBoundedString(value: unknown, maxBytes: number): value is string | undefined {\n return value === undefined || isBoundedString(value, maxBytes);\n}\n\nfunction isFiniteNumber(value: unknown): value is number {\n return typeof value === \"number\" && Number.isFinite(value);\n}\n\nfunction isInteger(value: unknown): value is number {\n return isFiniteNumber(value) && Number.isInteger(value);\n}\n\nfunction isHeaders(value: unknown): value is HeaderPairs {\n if (!Array.isArray(value) || value.length > MAX_HEADER_PAIRS) return false;\n let totalBytes = 0;\n for (const pair of value) {\n if (\n !Array.isArray(pair) ||\n pair.length !== 2 ||\n !isString(pair[0]) ||\n !HEADER_NAME.test(pair[0]) ||\n !isString(pair[1]) ||\n /[\\0\\r\\n]/.test(pair[1])\n ) {\n return false;\n }\n totalBytes += Buffer.byteLength(pair[0]) + Buffer.byteLength(pair[1]);\n if (totalBytes > MAX_HEADER_BYTES) return false;\n }\n return true;\n}\n\nfunction isBase64(value: unknown): value is string {\n if (\n !isString(value) ||\n value.length > MAX_ENCODED_CHUNK_CHARS ||\n value.length % 4 !== 0 ||\n !BASE64.test(value)\n )\n return false;\n const padding = value.endsWith(\"==\") ? 2 : value.endsWith(\"=\") ? 1 : 0;\n return (value.length / 4) * 3 - padding <= MAX_CHUNK_BYTES;\n}\n\nfunction isWsData(frame: FrameRecord): boolean {\n return (\n (isBoundedString(frame.text, MAX_CHUNK_BYTES) && frame.dataB64 === undefined) ||\n (frame.text === undefined && isBase64(frame.dataB64))\n );\n}\n\nfunction isWsClose(frame: FrameRecord): boolean {\n return (\n isNonEmptyBoundedString(frame.id, MAX_ID_BYTES) &&\n (frame.code === undefined ||\n (isInteger(frame.code) && frame.code >= 0 && frame.code <= 65_535)) &&\n isOptionalBoundedString(frame.reason, MAX_REASON_BYTES)\n );\n}\n\nfunction decodeFrame(raw: unknown): FrameRecord | null {\n if (typeof raw !== \"string\" || raw.length > MAX_FRAME_CHARS) return null;\n try {\n const parsed = JSON.parse(raw);\n if (isRecord(parsed) && typeof parsed.type === \"string\") return parsed as FrameRecord;\n return null;\n } catch {\n return null;\n }\n}\n\nexport function decodeNodeFrame(raw: unknown): NodeToRelayFrame | null {\n const frame = decodeFrame(raw);\n if (!frame) return null;\n switch (frame.type) {\n case \"register\":\n return isInteger(frame.protocolVersion) &&\n frame.protocolVersion > 0 &&\n isOptionalBoundedString(frame.nodeVersion, MAX_NODE_VERSION_BYTES)\n ? (frame as NodeToRelayFrame)\n : null;\n case \"pong\":\n return isFiniteNumber(frame.ts) && frame.ts >= 0 ? (frame as NodeToRelayFrame) : null;\n case \"http_res_head\":\n return isNonEmptyBoundedString(frame.id, MAX_ID_BYTES) &&\n isInteger(frame.status) &&\n frame.status >= 200 &&\n frame.status <= 599 &&\n isHeaders(frame.headers)\n ? (frame as NodeToRelayFrame)\n : null;\n case \"http_res_chunk\":\n return isNonEmptyBoundedString(frame.id, MAX_ID_BYTES) && isBase64(frame.dataB64)\n ? (frame as NodeToRelayFrame)\n : null;\n case \"http_res_end\":\n case \"ws_open_ok\":\n return isNonEmptyBoundedString(frame.id, MAX_ID_BYTES) ? (frame as NodeToRelayFrame) : null;\n case \"http_res_error\":\n case \"ws_open_error\":\n return isNonEmptyBoundedString(frame.id, MAX_ID_BYTES) &&\n isBoundedString(frame.message, MAX_MESSAGE_BYTES)\n ? (frame as NodeToRelayFrame)\n : null;\n case \"ws_data\":\n return isNonEmptyBoundedString(frame.id, MAX_ID_BYTES) && isWsData(frame)\n ? (frame as NodeToRelayFrame)\n : null;\n case \"ws_close\":\n return isWsClose(frame) ? (frame as NodeToRelayFrame) : null;\n default:\n return null;\n }\n}\n\nexport function decodeRelayFrame(raw: unknown): RelayToNodeFrame | null {\n const frame = decodeFrame(raw);\n if (!frame) return null;\n switch (frame.type) {\n case \"registered\":\n return isNonEmptyBoundedString(frame.nodeId, MAX_NODE_ID_BYTES) &&\n isInteger(frame.protocolVersion) &&\n frame.protocolVersion > 0 &&\n isInteger(frame.pingIntervalMs) &&\n frame.pingIntervalMs > 0\n ? (frame as RelayToNodeFrame)\n : null;\n case \"register_error\":\n return (frame.code === \"upgrade_required\" ||\n frame.code === \"unauthorized\" ||\n frame.code === \"replaced\") &&\n isBoundedString(frame.message, MAX_MESSAGE_BYTES)\n ? (frame as RelayToNodeFrame)\n : null;\n case \"ping\":\n return isFiniteNumber(frame.ts) && frame.ts >= 0 ? (frame as RelayToNodeFrame) : null;\n case \"http_req_head\":\n return isNonEmptyBoundedString(frame.id, MAX_ID_BYTES) &&\n isNonEmptyBoundedString(frame.method, MAX_METHOD_BYTES) &&\n isBoundedString(frame.path, MAX_PATH_BYTES) &&\n frame.path.startsWith(\"/\") &&\n isHeaders(frame.headers) &&\n typeof frame.hasBody === \"boolean\"\n ? (frame as RelayToNodeFrame)\n : null;\n case \"http_req_chunk\":\n return isNonEmptyBoundedString(frame.id, MAX_ID_BYTES) && isBase64(frame.dataB64)\n ? (frame as RelayToNodeFrame)\n : null;\n case \"http_req_end\":\n case \"http_req_abort\":\n return isNonEmptyBoundedString(frame.id, MAX_ID_BYTES) ? (frame as RelayToNodeFrame) : null;\n case \"ws_open\":\n return isNonEmptyBoundedString(frame.id, MAX_ID_BYTES) &&\n isBoundedString(frame.path, MAX_PATH_BYTES) &&\n frame.path.startsWith(\"/\") &&\n isHeaders(frame.headers)\n ? (frame as RelayToNodeFrame)\n : null;\n case \"ws_data\":\n return isNonEmptyBoundedString(frame.id, MAX_ID_BYTES) && isWsData(frame)\n ? (frame as RelayToNodeFrame)\n : null;\n case \"ws_close\":\n return isWsClose(frame) ? (frame as RelayToNodeFrame) : null;\n default:\n return null;\n }\n}\n\n// ── Payload helpers ───────────────────────────────────────────────\n\nexport function toB64(bytes: Uint8Array): string {\n if (bytes.byteLength > MAX_CHUNK_BYTES) {\n throw new RangeError(`relay chunk exceeds ${MAX_CHUNK_BYTES} bytes`);\n }\n return Buffer.from(bytes).toString(\"base64\");\n}\n\nexport function fromB64(dataB64: string): Uint8Array {\n if (!isBase64(dataB64)) {\n throw new RangeError(`invalid relay chunk or chunk exceeds ${MAX_CHUNK_BYTES} bytes`);\n }\n return new Uint8Array(Buffer.from(dataB64, \"base64\"));\n}\n\n/** Re-split an arbitrary chunk into frame-sized slices. */\nexport function* chunkBytes(bytes: Uint8Array): Generator<Uint8Array> {\n for (let offset = 0; offset < bytes.length; offset += MAX_CHUNK_BYTES) {\n yield bytes.subarray(offset, offset + MAX_CHUNK_BYTES);\n }\n}\n\n/** `close(code)` only accepts 1000 or 3000-4999; anything else (1001, 1006, …)\n * throws. Bridged closes map other codes to a plain 1000. */\nexport function sanitizeCloseCode(code: number | undefined): number | undefined {\n if (code === undefined) return undefined;\n if (code === 1000 || (code >= 3000 && code <= 4999)) return code;\n return 1000;\n}\n\n/** Hop-by-hop headers never forwarded in either direction. `content-length`\n * and `content-encoding` are dropped too: fetch() transparently decompresses\n * bodies and re-chunks streams, so both would lie after transit. */\nconst DROPPED_HEADERS = new Set([\n \"connection\",\n \"keep-alive\",\n \"proxy-authenticate\",\n \"proxy-authorization\",\n \"proxy-connection\",\n \"te\",\n \"trailer\",\n \"transfer-encoding\",\n \"upgrade\",\n \"host\",\n \"accept-encoding\",\n \"content-length\",\n \"content-encoding\",\n]);\n\nexport function forwardableHeaders(headers: Headers): HeaderPairs {\n const pairs: HeaderPairs = [];\n headers.forEach((value, name) => {\n if (!DROPPED_HEADERS.has(name.toLowerCase())) pairs.push([name, value]);\n });\n return pairs;\n}\n",
12
- "/**\n * TunnelClient — the node side of the relay tunnel.\n *\n * Runs inside (or beside) a runtime-api process. Dials the relay with an\n * outbound WebSocket, registers, then services multiplexed HTTP requests and\n * bridged client WebSockets by replaying them against the local runtime-api\n * over loopback. The runtime-api itself needs zero changes: the tunnel is a\n * pure reverse proxy, so auth (JWT), routes, and streaming all work as-is.\n *\n * Reliability model: everything on the tunnel is request-scoped. If the relay\n * connection drops, every proxied request/socket is dead by definition, so\n * there is no outbound queue to maintain — abort local work, reconnect with\n * exponential backoff, and let clients retry.\n */\n\nimport {\n chunkBytes,\n decodeRelayFrame,\n encodeFrame,\n fromB64,\n type HeaderPairs,\n type NodeToRelayFrame,\n PROTOCOL_VERSION,\n type RelayToNodeFrame,\n sanitizeCloseCode,\n toB64,\n} from \"./relay-protocol\";\nimport { assertSecureRelayUrl } from \"./secure-transport\";\n\ntype LogFn = (obj: Record<string, unknown>, msg: string) => void;\n\nexport interface TunnelLogger {\n info: LogFn;\n warn: LogFn;\n error: LogFn;\n}\n\nexport interface TunnelClientOptions {\n /** Relay origin — http(s):// or ws(s)://, with or without trailing slash. */\n relayUrl: string;\n /** Node credential — the runtime-cell secret (rcs_…) or a static dev token. */\n token: string;\n /** Local runtime-api origin, e.g. http://127.0.0.1:4000 */\n targetOrigin: string;\n nodeVersion?: string;\n logger?: TunnelLogger;\n minReconnectDelayMs?: number;\n maxReconnectDelayMs?: number;\n /** Test/embedding hook. Defaults to Bun's WebSocket constructor. */\n webSocketFactory?: (url: string, options: { headers: Record<string, string> }) => WebSocket;\n}\n\nexport type TunnelStatus =\n | \"idle\"\n | \"connecting\"\n | \"registered\"\n | \"stopped\"\n | \"unsupported\"\n | \"superseded\";\n\n/** Bun's WebSocket client accepts a non-standard `headers` option; the DOM lib\n * typing doesn't know it. */\ntype BunWebSocketCtor = new (\n url: string,\n options?: { headers?: Record<string, string> },\n) => WebSocket;\n\nconst MAX_WS_UPGRADE_HEADER_BYTES = 32 * 1024;\nconst WS_PROTOCOL_TOKEN = /^[!#$%&'*+\\-.^_`|~0-9A-Za-z]+$/;\n\nfunction localWebSocketOptions(headers: HeaderPairs): {\n headers: Record<string, string>;\n} | null {\n const forwarded: Record<string, string> = {};\n let totalBytes = 0;\n for (const pair of headers) {\n if (!Array.isArray(pair) || pair.length !== 2) return null;\n const [rawName, value] = pair;\n if (typeof rawName !== \"string\" || typeof value !== \"string\" || /[\\0\\r\\n]/.test(value)) {\n return null;\n }\n const name = rawName.toLowerCase();\n if (name !== \"cookie\" && name !== \"authorization\" && name !== \"sec-websocket-protocol\") {\n return null;\n }\n totalBytes += Buffer.byteLength(name) + Buffer.byteLength(value);\n if (totalBytes > MAX_WS_UPGRADE_HEADER_BYTES || name in forwarded) {\n return null;\n }\n if (name === \"sec-websocket-protocol\") {\n if (!WS_PROTOCOL_TOKEN.test(value)) return null;\n }\n forwarded[name] = value;\n }\n return { headers: forwarded };\n}\n\nconst DEFAULT_MIN_RECONNECT_MS = 1_000;\nconst DEFAULT_MAX_RECONNECT_MS = 30_000;\nconst RECONNECT_JITTER_RATIO = 0.2;\n/** Liveness: relay pings every pingIntervalMs; absent ANY frame for this many\n * intervals the socket is considered half-open and torn down for reconnect. */\nconst LIVENESS_INTERVALS = 3;\n\ninterface PendingHttp {\n abort: AbortController;\n /** Set while a chunked request body is being replayed into local fetch. */\n bodyController: ReadableStreamDefaultController<Uint8Array> | null;\n}\n\ninterface BridgedSocket {\n ws: WebSocket;\n opened: boolean;\n /** relay→local data frames buffered until the local socket opens. */\n buffer: Array<Extract<RelayToNodeFrame, { type: \"ws_data\" }>>;\n}\n\nconst noop: LogFn = () => {};\nconst silentLogger: TunnelLogger = { info: noop, warn: noop, error: noop };\n\nexport class TunnelClient {\n private readonly opts: Required<\n Pick<TunnelClientOptions, \"relayUrl\" | \"token\" | \"targetOrigin\">\n > &\n TunnelClientOptions;\n private readonly log: TunnelLogger;\n private ws: WebSocket | null = null;\n private connectionGeneration = 0;\n private statusValue: TunnelStatus = \"idle\";\n private reconnectDelayMs: number;\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private livenessTimer: ReturnType<typeof setTimeout> | null = null;\n private pingIntervalMs = 30_000;\n private readonly pendingHttp = new Map<string, PendingHttp>();\n private readonly bridgedSockets = new Map<string, BridgedSocket>();\n\n constructor(options: TunnelClientOptions) {\n assertSecureRelayUrl(options.relayUrl);\n this.opts = options;\n this.log = options.logger ?? silentLogger;\n this.reconnectDelayMs = options.minReconnectDelayMs ?? DEFAULT_MIN_RECONNECT_MS;\n }\n\n get status(): TunnelStatus {\n return this.statusValue;\n }\n\n start(): void {\n if (this.statusValue !== \"idle\" && this.statusValue !== \"stopped\") return;\n this.connect();\n }\n\n stop(): void {\n this.statusValue = \"stopped\";\n if (this.reconnectTimer) clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n this.clearLiveness();\n this.cleanupInFlight();\n const ws = this.ws;\n this.ws = null;\n this.connectionGeneration += 1;\n ws?.close(1000, \"tunnel stopped\");\n }\n\n // ── Connection lifecycle ────────────────────────────────────────\n\n private tunnelUrl(): string {\n const base = this.opts.relayUrl.replace(/\\/+$/, \"\").replace(/^http/, \"ws\");\n return `${base}/tunnel`;\n }\n\n private connect(): void {\n this.statusValue = \"connecting\";\n const WS = WebSocket as unknown as BunWebSocketCtor;\n const options = { headers: { authorization: `Bearer ${this.opts.token}` } };\n const ws = this.opts.webSocketFactory\n ? this.opts.webSocketFactory(this.tunnelUrl(), options)\n : new WS(this.tunnelUrl(), options);\n const generation = ++this.connectionGeneration;\n this.ws = ws;\n\n ws.onopen = () => {\n if (!this.isActiveConnection(ws, generation)) return;\n this.send({\n type: \"register\",\n protocolVersion: PROTOCOL_VERSION,\n nodeVersion: this.opts.nodeVersion,\n });\n this.resetLiveness();\n };\n\n ws.onmessage = (event) => {\n if (!this.isActiveConnection(ws, generation)) return;\n try {\n const frame = decodeRelayFrame(event.data);\n if (!frame) {\n this.rejectProtocolFrame(ws, generation, \"invalid relay frame\");\n return;\n }\n this.resetLiveness(ws, generation);\n this.handleFrame(frame);\n } catch (err) {\n this.log.error(\n { error: err instanceof Error ? err.message : String(err) },\n \"relay frame dispatch failed\",\n );\n this.rejectProtocolFrame(ws, generation, \"relay frame dispatch failed\");\n }\n };\n\n ws.onclose = (event) => {\n this.disconnectActiveConnection(ws, generation, {\n code: event.code,\n reason: event.reason,\n });\n };\n\n ws.onerror = () => {\n // onclose follows; reconnect is handled there.\n };\n }\n\n private isActiveConnection(ws: WebSocket, generation: number): boolean {\n return this.ws === ws && this.connectionGeneration === generation;\n }\n\n private rejectProtocolFrame(ws: WebSocket, generation: number, reason: string): void {\n this.log.warn({ reason }, \"closing relay tunnel after protocol error\");\n this.disconnectActiveConnection(ws, generation, { reason });\n try {\n ws.close(1002, reason);\n } catch {\n // The active connection was already invalidated and reconnect is scheduled.\n }\n }\n\n /** Invalidate before closing: a half-open socket may never emit `close`. */\n private disconnectActiveConnection(\n ws: WebSocket,\n generation: number,\n details: Record<string, unknown>,\n close = false,\n ): void {\n if (!this.isActiveConnection(ws, generation)) return;\n this.ws = null;\n this.connectionGeneration += 1;\n this.clearLiveness();\n this.cleanupInFlight();\n if (\n this.statusValue !== \"stopped\" &&\n this.statusValue !== \"unsupported\" &&\n this.statusValue !== \"superseded\"\n ) {\n this.statusValue = \"connecting\";\n this.log.warn(details, \"relay tunnel disconnected\");\n this.scheduleReconnect();\n }\n if (close) {\n try {\n ws.close();\n } catch {\n // The connection is already invalidated and reconnect is scheduled.\n }\n }\n }\n\n private scheduleReconnect(): void {\n if (this.reconnectTimer) return;\n // Spread reconnects after relay/edge restarts so every cell does not hit\n // the verifier and Docker DNS in the same millisecond.\n const jitter = 1 + (Math.random() * 2 - 1) * RECONNECT_JITTER_RATIO;\n const delay = Math.max(1, Math.round(this.reconnectDelayMs * jitter));\n this.reconnectDelayMs = Math.min(\n this.reconnectDelayMs * 2,\n this.opts.maxReconnectDelayMs ?? DEFAULT_MAX_RECONNECT_MS,\n );\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n if (\n this.statusValue === \"stopped\" ||\n this.statusValue === \"unsupported\" ||\n this.statusValue === \"superseded\"\n )\n return;\n this.connect();\n }, delay);\n }\n\n private resetLiveness(ws = this.ws, generation = this.connectionGeneration): void {\n this.clearLiveness();\n if (!ws) return;\n this.livenessTimer = setTimeout(() => {\n this.log.warn({}, \"relay tunnel silent past liveness window — reconnecting\");\n this.disconnectActiveConnection(ws, generation, { reason: \"liveness timeout\" }, true);\n }, this.pingIntervalMs * LIVENESS_INTERVALS);\n }\n\n private clearLiveness(): void {\n if (this.livenessTimer) clearTimeout(this.livenessTimer);\n this.livenessTimer = null;\n }\n\n private cleanupInFlight(): void {\n for (const pending of this.pendingHttp.values()) {\n pending.abort.abort();\n try {\n pending.bodyController?.error(new Error(\"relay tunnel disconnected\"));\n } catch {\n // already closed\n }\n }\n this.pendingHttp.clear();\n for (const bridged of this.bridgedSockets.values()) {\n try {\n bridged.ws.close(1000, \"relay tunnel disconnected\");\n } catch {\n // already closed\n }\n }\n this.bridgedSockets.clear();\n }\n\n private send(frame: NodeToRelayFrame): void {\n if (this.ws?.readyState === WebSocket.OPEN) this.ws.send(encodeFrame(frame));\n }\n\n // ── Frame dispatch ──────────────────────────────────────────────\n\n private handleFrame(frame: RelayToNodeFrame): void {\n switch (frame.type) {\n case \"registered\":\n this.statusValue = \"registered\";\n this.pingIntervalMs = frame.pingIntervalMs;\n this.reconnectDelayMs = this.opts.minReconnectDelayMs ?? DEFAULT_MIN_RECONNECT_MS;\n this.resetLiveness(this.ws, this.connectionGeneration);\n this.log.info({ nodeId: frame.nodeId }, \"relay tunnel registered\");\n break;\n case \"register_error\":\n if (frame.code === \"upgrade_required\") {\n // Version mismatch is not recoverable by retrying — stop and demand\n // operator attention instead of hammering the relay forever.\n this.statusValue = \"unsupported\";\n this.log.error(\n { message: frame.message },\n \"relay rejected protocol version — update this node\",\n );\n } else if (frame.code === \"unauthorized\") {\n // Token may be fixed out-of-band; keep retrying, but only at the cap.\n this.reconnectDelayMs = this.opts.maxReconnectDelayMs ?? DEFAULT_MAX_RECONNECT_MS;\n this.log.error({ message: frame.message }, \"relay rejected node credentials\");\n } else {\n // A newer process owns this credential. Retrying would displace it and\n // create an endless replacement storm, so this instance is terminal\n // until an operator explicitly stop/starts it.\n this.statusValue = \"superseded\";\n this.log.info({ message: frame.message }, \"relay tunnel superseded by newer connection\");\n const ws = this.ws;\n if (ws) {\n this.disconnectActiveConnection(\n ws,\n this.connectionGeneration,\n { reason: \"tunnel superseded\" },\n true,\n );\n }\n }\n break;\n case \"ping\":\n this.send({ type: \"pong\", ts: frame.ts });\n break;\n case \"http_req_head\":\n this.startHttpRequest(frame);\n break;\n case \"http_req_chunk\": {\n const pending = this.pendingHttp.get(frame.id);\n try {\n pending?.bodyController?.enqueue(fromB64(frame.dataB64));\n } catch {\n // request already settled locally\n }\n break;\n }\n case \"http_req_end\": {\n const pending = this.pendingHttp.get(frame.id);\n try {\n pending?.bodyController?.close();\n } catch {\n // request already settled locally\n }\n break;\n }\n case \"http_req_abort\": {\n const pending = this.pendingHttp.get(frame.id);\n if (pending) {\n this.pendingHttp.delete(frame.id);\n pending.abort.abort();\n try {\n pending.bodyController?.error(new Error(\"aborted by relay\"));\n } catch {\n // already closed\n }\n }\n break;\n }\n case \"ws_open\":\n this.openBridgedSocket(frame.id, frame.path, frame.headers);\n break;\n case \"ws_data\": {\n const bridged = this.bridgedSockets.get(frame.id);\n if (!bridged) break;\n if (!bridged.opened) {\n bridged.buffer.push(frame);\n break;\n }\n this.deliverToLocal(bridged.ws, frame);\n break;\n }\n case \"ws_close\": {\n const bridged = this.bridgedSockets.get(frame.id);\n if (!bridged) break;\n this.bridgedSockets.delete(frame.id);\n try {\n bridged.ws.close(sanitizeCloseCode(frame.code), frame.reason);\n } catch {\n // already closed\n }\n break;\n }\n }\n }\n\n // ── HTTP replay ─────────────────────────────────────────────────\n\n private startHttpRequest(frame: Extract<RelayToNodeFrame, { type: \"http_req_head\" }>): void {\n const abort = new AbortController();\n const pending: PendingHttp = { abort, bodyController: null };\n this.pendingHttp.set(frame.id, pending);\n\n let body: ReadableStream<Uint8Array> | undefined;\n if (frame.hasBody) {\n body = new ReadableStream<Uint8Array>({\n start: (controller) => {\n pending.bodyController = controller;\n },\n });\n }\n\n const headers = new Headers();\n for (const [name, value] of frame.headers) headers.append(name, value);\n\n void this.replayHttp(frame.id, frame.method, frame.path, headers, body, abort).finally(() => {\n this.pendingHttp.delete(frame.id);\n });\n }\n\n private async replayHttp(\n id: string,\n method: string,\n path: string,\n headers: Headers,\n body: ReadableStream<Uint8Array> | undefined,\n abort: AbortController,\n ): Promise<void> {\n try {\n const res = await fetch(`${this.opts.targetOrigin}${path}`, {\n method,\n headers,\n body,\n signal: abort.signal,\n // Pass redirects through verbatim — the browser client owns redirect\n // behavior, not the tunnel.\n redirect: \"manual\",\n });\n const pairs: Array<[string, string]> = [];\n res.headers.forEach((value, name) => {\n const lower = name.toLowerCase();\n // fetch already decompressed the body and the relay re-chunks it, so\n // these would be wrong on the other side. The relay's server adds its\n // own date header — forwarding the node's would duplicate it.\n if (\n lower === \"content-encoding\" ||\n lower === \"content-length\" ||\n lower === \"transfer-encoding\" ||\n lower === \"date\"\n )\n return;\n pairs.push([name, value]);\n });\n this.send({ type: \"http_res_head\", id, status: res.status, headers: pairs });\n if (res.body) {\n const reader = res.body.getReader();\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n for (const chunk of chunkBytes(value)) {\n this.send({ type: \"http_res_chunk\", id, dataB64: toB64(chunk) });\n }\n }\n }\n this.send({ type: \"http_res_end\", id });\n } catch (err) {\n if (!abort.signal.aborted) {\n this.send({\n type: \"http_res_error\",\n id,\n message: err instanceof Error ? err.message : String(err),\n });\n }\n }\n }\n\n // ── WebSocket bridging ──────────────────────────────────────────\n\n private openBridgedSocket(id: string, path: string, headers: HeaderPairs): void {\n const wsOrigin = this.opts.targetOrigin.replace(/^http/, \"ws\");\n let local: WebSocket;\n try {\n const upgrade = localWebSocketOptions(headers);\n if (!upgrade) throw new Error(\"invalid websocket upgrade headers\");\n const WS = WebSocket as unknown as BunWebSocketCtor;\n local = new WS(`${wsOrigin}${path}`, { headers: upgrade.headers });\n } catch (err) {\n this.send({\n type: \"ws_open_error\",\n id,\n message: err instanceof Error ? err.message : String(err),\n });\n return;\n }\n const bridged: BridgedSocket = { ws: local, opened: false, buffer: [] };\n this.bridgedSockets.set(id, bridged);\n\n local.onopen = () => {\n bridged.opened = true;\n this.send({ type: \"ws_open_ok\", id });\n for (const frame of bridged.buffer) this.deliverToLocal(local, frame);\n bridged.buffer = [];\n };\n\n local.onmessage = (event) => {\n if (typeof event.data === \"string\") {\n this.send({ type: \"ws_data\", id, text: event.data });\n } else {\n const bytes =\n event.data instanceof ArrayBuffer\n ? new Uint8Array(event.data)\n : new Uint8Array(event.data as Uint8Array);\n this.send({ type: \"ws_data\", id, dataB64: toB64(bytes) });\n }\n };\n\n local.onclose = (event) => {\n if (this.bridgedSockets.get(id) !== bridged) return;\n this.bridgedSockets.delete(id);\n this.send({ type: \"ws_close\", id, code: event.code, reason: event.reason });\n };\n\n local.onerror = () => {\n if (!bridged.opened) {\n this.bridgedSockets.delete(id);\n this.send({ type: \"ws_open_error\", id, message: \"local websocket failed\" });\n }\n // Post-open errors surface through onclose.\n };\n }\n\n private deliverToLocal(\n local: WebSocket,\n frame: Extract<RelayToNodeFrame, { type: \"ws_data\" }>,\n ): void {\n if (local.readyState !== WebSocket.OPEN) return;\n if (frame.text !== undefined) local.send(frame.text);\n else if (frame.dataB64 !== undefined) local.send(fromB64(frame.dataB64));\n }\n}\n",
13
- "/**\n * Worker peer surface — the inbound HTTP contract from\n * docs/OTIUM-COUPLING.md §2.1, mounted in front of the host's other handlers:\n *\n * Bun.serve({ fetch: async (req) =>\n * (await handleOtiumPeerRequest(req)) ?? (await handleNegotiumMcpRequest(req)) ?? … })\n *\n * Auth model (mirrors otium routes.ts `requirePeer`):\n * ① no join credentials → 403 \"multi-node is disabled\" (fail-closed)\n * ② missing Bearer → 401 \"missing peer token\"\n * ③ central `POST /peer/verify` failure → 401 \"invalid peer token\"\n * (30s positive cache in #central)\n * ④ body `v` check → 400 on newer protocol\n * Hub-only writes additionally require `verified.fromIsPrimary`.\n *\n * Implements the worker peer protocol, including cross-node session messages,\n * file transfer, and runtime visual bridging.\n */\n\nimport { statfsSync } from \"node:fs\";\nimport { cpus, freemem, loadavg, totalmem } from \"node:os\";\nimport {\n appendJsonlEntry,\n checkAgentAuth,\n DATA_DIR,\n flushSessionInbox,\n getRegistry,\n getTopic,\n getTopicByNameForUser,\n getTopicSessionId,\n isTopicShared,\n listTopics,\n logger,\n MAX_TELL_DEPTH,\n NEGOTIUM_VERSION,\n normalizeVaultKey,\n OPTIONAL_FORUM_MCP_SERVERS,\n SUPPORTED_AGENTS,\n sessionInboxPath,\n VAULT_DESCRIPTION_MAX_LENGTH,\n VAULT_VALUE_MAX_BYTES,\n VAULT_VALUE_MIN_BYTES,\n validateVaultKey,\n vaultDel,\n vaultList,\n vaultSet,\n} from \"@negotium/core\";\nimport { bindOtiumTopic, unbindOtiumTopic } from \"@/bindings\";\nimport {\n otiumCentralConfig,\n resolvePeerNodeByCellId,\n type VerifiedPeer,\n verifyPeerToken,\n} from \"@/central\";\nimport { storePeerInputFile } from \"@/peer-files\";\nimport {\n MAX_PEER_INPUT_FILE_BYTES,\n MAX_PEER_INPUT_REQUEST_BYTES,\n MAX_PEER_MESSAGE_LENGTH,\n PEER_PROTOCOL_VERSION,\n type PeerSessionEntry,\n type PeerTurnRequest,\n parseExecutionSpec,\n} from \"@/protocol\";\nimport { acceptRemoteAskReplyResult } from \"@/session-bridge\";\nimport {\n claimPeerInboxRequest,\n getPeerSession,\n type PeerInboxKind,\n peerInboxPayloadHash,\n releasePeerInboxRequest,\n} from \"@/store\";\nimport { abortHostedPeerTurn, provisionMirrorTopic, runPeerTurn } from \"@/turn-bridge\";\n\nconst RUNTIME_VERSION = NEGOTIUM_VERSION;\n\nfunction jsonError(error: string, status: number): Response {\n return Response.json({ ok: false, error }, { status });\n}\n\nfunction bearer(req: Request): string | null {\n const auth = req.headers.get(\"authorization\");\n return auth?.startsWith(\"Bearer \") ? auth.slice(7) : null;\n}\n\nasync function readBody(req: Request): Promise<Record<string, unknown> | null> {\n const body = (await req.json().catch(() => null)) as unknown;\n if (!body || typeof body !== \"object\" || Array.isArray(body)) return null;\n return body as Record<string, unknown>;\n}\n\nfunction str(body: Record<string, unknown>, field: string): string | null {\n const value = body[field];\n return typeof value === \"string\" && value.trim() ? value : null;\n}\n\nfunction checkProtocol(body: Record<string, unknown>): Response | null {\n const v = body.v;\n if (typeof v !== \"number\" || v > PEER_PROTOCOL_VERSION) {\n return jsonError(`unsupported peer protocol version (mine: ${PEER_PROTOCOL_VERSION})`, 400);\n }\n return null;\n}\n\ntype PeerAuth = { ok: false; response: Response } | { ok: true; verified: VerifiedPeer };\n\nasync function requirePeer(req: Request): Promise<PeerAuth> {\n if (!otiumCentralConfig()) {\n return { ok: false, response: jsonError(\"multi-node is disabled\", 403) };\n }\n const token = bearer(req);\n if (!token) return { ok: false, response: jsonError(\"missing peer token\", 401) };\n const verified = await verifyPeerToken(token);\n if (!verified) return { ok: false, response: jsonError(\"invalid peer token\", 401) };\n return { ok: true, verified };\n}\n\nfunction requirePrimaryOrigin(peer: Extract<PeerAuth, { ok: true }>): Response | null {\n return peer.verified.fromIsPrimary\n ? null\n : jsonError(\"only the workspace hub may call this endpoint\", 403);\n}\n\n// ── Capability / health snapshots ────────────────────────────────────\n\nfunction localCapabilities() {\n const agents = SUPPORTED_AGENTS.map((kind) => {\n const auth = checkAgentAuth(kind);\n const registry = getRegistry(kind);\n return {\n kind,\n available: auth.ok,\n defaultModel: registry.defaultModel,\n validEfforts: registry.validEfforts,\n ...(!auth.ok ? { error: auth.error } : {}),\n };\n });\n return {\n protocolVersion: PEER_PROTOCOL_VERSION,\n runtimeVersion: RUNTIME_VERSION,\n features: {\n remoteAsk: true,\n inputFiles: true,\n outputFiles: true,\n visualBridge: true,\n askUserBridge: true,\n selfConfigBridge: true,\n },\n agents,\n // These are negotium MCP catalog names — a hub room whose MCP\n // override uses otium-only names will fail placement with 409.\n optionalMcp: OPTIONAL_FORUM_MCP_SERVERS,\n };\n}\n\nfunction localHealth() {\n const memory = process.memoryUsage();\n let disk: { totalBytes: number; freeBytes: number } | undefined;\n try {\n const stats = statfsSync(DATA_DIR);\n disk = {\n totalBytes: Number(stats.blocks) * Number(stats.bsize),\n freeBytes: Number(stats.bavail) * Number(stats.bsize),\n };\n } catch {\n disk = undefined;\n }\n return {\n uptimeSeconds: process.uptime(),\n cpu: { cores: cpus().length, loadAverage: loadavg() },\n memory: {\n totalBytes: totalmem(),\n freeBytes: freemem(),\n processRssBytes: memory.rss,\n processHeapUsedBytes: memory.heapUsed,\n },\n ...(disk ? { disk } : {}),\n };\n}\n\n// ── Handlers ─────────────────────────────────────────────────────────\n\nasync function handleProvision(req: Request): Promise<Response> {\n const peer = await requirePeer(req);\n if (!peer.ok) return peer.response;\n const originError = requirePrimaryOrigin(peer);\n if (originError) return originError;\n const body = await readBody(req);\n if (!body) return jsonError(\"invalid JSON body\", 400);\n const protocolError = checkProtocol(body);\n if (protocolError) return protocolError;\n const userId = str(body, \"userId\");\n const hostTopicId = str(body, \"hostTopicId\");\n const topicTitle = str(body, \"topicTitle\");\n const execution = parseExecutionSpec(body.execution);\n if (!userId || !hostTopicId || !topicTitle || !execution) {\n return jsonError(\"invalid peer provision request\", 400);\n }\n const result = provisionMirrorTopic(peer.verified.fromCellId, {\n userId,\n hostTopicId,\n topicTitle,\n execution,\n });\n if (!result.ok) return jsonError(result.error, result.status);\n logger.info(\n { hostTopicId, localTopicId: result.localTopicId, fromNode: peer.verified.fromNodeName },\n \"otium: hidden mirror room provisioned\",\n );\n return Response.json({ ok: true });\n}\n\nasync function handleBind(req: Request): Promise<Response> {\n const peer = await requirePeer(req);\n if (!peer.ok) return peer.response;\n const originError = requirePrimaryOrigin(peer);\n if (originError) return originError;\n const body = await readBody(req);\n if (!body) return jsonError(\"invalid JSON body\", 400);\n const protocolError = checkProtocol(body);\n if (protocolError) return protocolError;\n const userId = str(body, \"userId\");\n const hostTopicId = str(body, \"hostTopicId\");\n const localTopicId = str(body, \"localTopicId\");\n if (!userId || !hostTopicId || !localTopicId) {\n return jsonError(\"invalid peer bind request\", 400);\n }\n const result = bindOtiumTopic({\n hostNodeId: peer.verified.fromCellId,\n hostTopicId,\n localTopicId,\n userId,\n });\n if (!result.ok) return jsonError(result.error, result.status);\n return Response.json({ ok: true, localTopicId: result.localTopicId, replaced: result.replaced });\n}\n\nasync function handleUnbind(req: Request): Promise<Response> {\n const peer = await requirePeer(req);\n if (!peer.ok) return peer.response;\n const originError = requirePrimaryOrigin(peer);\n if (originError) return originError;\n const body = await readBody(req);\n if (!body) return jsonError(\"invalid JSON body\", 400);\n const protocolError = checkProtocol(body);\n if (protocolError) return protocolError;\n const hostTopicId = str(body, \"hostTopicId\");\n if (!hostTopicId) return jsonError(\"hostTopicId is required\", 400);\n const removed = unbindOtiumTopic(peer.verified.fromCellId, hostTopicId);\n return Response.json({ ok: true, removed });\n}\n\nasync function handleTurn(req: Request): Promise<Response> {\n const peer = await requirePeer(req);\n if (!peer.ok) return peer.response;\n const originError = requirePrimaryOrigin(peer);\n if (originError) return originError;\n const body = await readBody(req);\n if (!body) return jsonError(\"invalid JSON body\", 400);\n const protocolError = checkProtocol(body);\n if (protocolError) return protocolError;\n\n const requestId = str(body, \"requestId\");\n const userId = str(body, \"userId\");\n const hostTopicId = str(body, \"hostTopicId\");\n const topicTitle = str(body, \"topicTitle\");\n const execution = parseExecutionSpec(body.execution);\n if (body.execution !== undefined && !execution) {\n return jsonError(\"invalid placed-topic execution spec\", 400);\n }\n const agent = execution?.agent ?? str(body, \"agent\");\n const message = str(body, \"message\");\n if (!requestId || !userId || !hostTopicId || !topicTitle || !agent || !message) {\n return jsonError(\n \"requestId, userId, hostTopicId, topicTitle, agent, message are required\",\n 400,\n );\n }\n if (message.length > MAX_PEER_MESSAGE_LENGTH) return jsonError(\"message too long\", 400);\n\n const hubNode = await resolvePeerNodeByCellId(peer.verified.fromCellId).catch(() => null);\n if (!hubNode) return jsonError(\"calling node is not in this workspace\", 403);\n\n const payload: PeerTurnRequest = {\n v: PEER_PROTOCOL_VERSION,\n requestId,\n userId,\n hostTopicId,\n topicTitle,\n ...(execution ? { execution } : {}),\n ...(agent ? { agent } : {}),\n ...(str(body, \"model\") ? { model: str(body, \"model\") as string } : {}),\n ...(str(body, \"effort\") ? { effort: str(body, \"effort\") as string } : {}),\n ...(Array.isArray(body.attachments) &&\n body.attachments.every((entry) => typeof entry === \"string\")\n ? { attachments: body.attachments as string[] }\n : {}),\n message,\n };\n const result = runPeerTurn(hubNode, peer.verified.fromCellId, payload);\n if (!result.ok) return jsonError(result.error, result.status);\n logger.info(\n { requestId, hostTopicId, fromNode: peer.verified.fromNodeName },\n \"otium: peer turn accepted\",\n );\n return Response.json({ ok: true });\n}\n\nasync function handleAbort(req: Request): Promise<Response> {\n const peer = await requirePeer(req);\n if (!peer.ok) return peer.response;\n const originError = requirePrimaryOrigin(peer);\n if (originError) return originError;\n const body = await readBody(req);\n if (!body) return jsonError(\"invalid JSON body\", 400);\n const protocolError = checkProtocol(body);\n if (protocolError) return protocolError;\n\n const userId = str(body, \"userId\");\n const toTopic = str(body, \"toTopic\");\n if (!userId || !toTopic) return jsonError(\"userId and toTopic are required\", 400);\n const requestId = str(body, \"requestId\");\n if (requestId) {\n const aborted = abortHostedPeerTurn(peer.verified.fromCellId, requestId, userId, toTopic);\n if (!aborted) return jsonError(\"turn not found or already completed\", 404);\n logger.info(\n { fromNode: peer.verified.fromNodeName, toTopic, requestId },\n \"otium: exact peer turn abort accepted\",\n );\n return Response.json({ ok: true });\n }\n const topic = getTopicByNameForUser(toTopic, userId);\n if (!topic || !isTopicShared(topic)) {\n return jsonError(`shared topic \"${toTopic}\" not found on this node`, 404);\n }\n appendJsonlEntry(sessionInboxPath(userId, topic.id), {\n type: \"abort\",\n timestamp: new Date().toISOString(),\n });\n void flushSessionInbox();\n logger.info({ fromNode: peer.verified.fromNodeName, toTopic }, \"otium: peer abort accepted\");\n return Response.json({ ok: true });\n}\n\nasync function handleTell(req: Request): Promise<Response> {\n const peer = await requirePeer(req);\n if (!peer.ok) return peer.response;\n const originError = requirePrimaryOrigin(peer);\n if (originError) return originError;\n const body = await readBody(req);\n if (!body) return jsonError(\"invalid JSON body\", 400);\n const protocolError = checkProtocol(body);\n if (protocolError) return protocolError;\n\n const requestId = str(body, \"requestId\");\n const userId = str(body, \"userId\");\n const toTopic = str(body, \"toTopic\");\n const fromLabel = str(body, \"fromLabel\");\n const message = str(body, \"message\");\n const depth = typeof body.depth === \"number\" ? body.depth : Number.NaN;\n if (!requestId || !userId || !toTopic || !fromLabel || !message) {\n return jsonError(\"requestId, userId, toTopic, fromLabel, message are required\", 400);\n }\n if (message.length > MAX_PEER_MESSAGE_LENGTH) return jsonError(\"message too long\", 400);\n if (!Number.isInteger(depth) || depth < 0) {\n return jsonError(\"depth must be a non-negative integer\", 400);\n }\n if (depth > MAX_TELL_DEPTH) {\n return jsonError(`tell depth limit exceeded (max ${MAX_TELL_DEPTH})`, 400);\n }\n\n const topic = getTopicByNameForUser(toTopic, userId);\n if (!topic || !isTopicShared(topic)) {\n return jsonError(`shared topic \"${toTopic}\" not found on this node`, 404);\n }\n\n const claim = claimInboundPeerMessage({\n fromCellId: peer.verified.fromCellId,\n requestId,\n kind: \"tell\",\n topicId: topic.id,\n payload: { userId, toTopic, fromLabel, message, depth },\n });\n if (claim === \"conflict\") return jsonError(\"requestId already belongs to another tell\", 409);\n if (claim === \"replay\") return Response.json({ ok: true, replayed: true });\n try {\n appendJsonlEntry(sessionInboxPath(userId, topic.id), {\n type: \"tell\",\n requestId,\n from: fromLabel,\n fromTitle: fromLabel,\n message,\n depth,\n timestamp: new Date().toISOString(),\n });\n } catch (error) {\n releasePeerInboxRequest(peer.verified.fromCellId, requestId, \"tell\");\n throw error;\n }\n void flushSessionInbox();\n logger.info(\n { from: fromLabel, fromNode: peer.verified.fromNodeName, toTopic, requestId },\n \"otium: peer tell accepted\",\n );\n return Response.json({ ok: true });\n}\n\nfunction claimInboundPeerMessage(args: {\n fromCellId: string;\n requestId: string;\n kind: PeerInboxKind;\n topicId: string;\n payload: unknown;\n}): \"claimed\" | \"replay\" | \"conflict\" {\n return claimPeerInboxRequest({\n fromCellId: args.fromCellId,\n requestId: args.requestId,\n kind: args.kind,\n topicId: args.topicId,\n payloadHash: peerInboxPayloadHash(args.payload),\n }).outcome;\n}\n\nasync function handleSessions(req: Request): Promise<Response> {\n const peer = await requirePeer(req);\n if (!peer.ok) return peer.response;\n const originError = requirePrimaryOrigin(peer);\n if (originError) return originError;\n const body = await readBody(req);\n if (!body) return jsonError(\"invalid JSON body\", 400);\n const protocolError = checkProtocol(body);\n if (protocolError) return protocolError;\n const userId = str(body, \"userId\");\n if (!userId) return jsonError(\"userId is required\", 400);\n\n const sessions: PeerSessionEntry[] = listTopics()\n .filter(\n (topic) =>\n topic.kind !== \"manager\" &&\n !topic.isSubagent &&\n isTopicShared(topic) &&\n topic.participants.some((p) => p.userId === userId),\n )\n .map((topic) => ({\n topicId: topic.id,\n name: topic.title,\n agent: topic.agent ?? null,\n hasSession: Boolean(getTopicSessionId(topic.id)),\n ...(topic.description ? { description: topic.description } : {}),\n }));\n return Response.json({ ok: true, sessions });\n}\n\nasync function handleAsk(req: Request): Promise<Response> {\n const peer = await requirePeer(req);\n if (!peer.ok) return peer.response;\n const originError = requirePrimaryOrigin(peer);\n if (originError) return originError;\n const body = await readBody(req);\n if (!body) return jsonError(\"invalid JSON body\", 400);\n const protocolError = checkProtocol(body);\n if (protocolError) return protocolError;\n const requestId = str(body, \"requestId\");\n const userId = str(body, \"userId\");\n const toTopic = str(body, \"toTopic\");\n const fromLabel = str(body, \"fromLabel\");\n const message = str(body, \"message\");\n const fromDepth =\n body.fromDepth === undefined\n ? 0\n : typeof body.fromDepth === \"number\"\n ? body.fromDepth\n : Number.NaN;\n const replyTo = body.replyTo as { topicId?: unknown } | undefined;\n const replyTopicId = typeof replyTo?.topicId === \"string\" ? replyTo.topicId : null;\n if (!requestId || !userId || !toTopic || !fromLabel || !message || !replyTopicId) {\n return jsonError(\n \"requestId, userId, toTopic, fromLabel, message, replyTo.topicId are required\",\n 400,\n );\n }\n if (message.length > MAX_PEER_MESSAGE_LENGTH) return jsonError(\"message too long\", 400);\n if (!Number.isInteger(fromDepth) || fromDepth < 0) {\n return jsonError(\"fromDepth must be a non-negative integer\", 400);\n }\n const topic = getTopicByNameForUser(toTopic, userId);\n if (!topic || !isTopicShared(topic)) {\n return jsonError(`shared topic \"${toTopic}\" not found on this node`, 404);\n }\n if (!topic.agent) return jsonError(`topic \"${toTopic}\" has no AI invited`, 409);\n\n const claim = claimInboundPeerMessage({\n fromCellId: peer.verified.fromCellId,\n requestId,\n kind: \"ask\",\n topicId: topic.id,\n payload: { userId, toTopic, fromLabel, message, fromDepth, replyTopicId },\n });\n if (claim === \"conflict\") return jsonError(\"requestId already belongs to another ask\", 409);\n if (claim === \"replay\") return Response.json({ ok: true, replayed: true });\n try {\n appendJsonlEntry(sessionInboxPath(userId, topic.id), {\n type: \"ask\",\n requestId,\n from: fromLabel,\n fromTitle: fromLabel,\n message,\n fromDepth,\n timestamp: new Date().toISOString(),\n remoteReply: {\n nodeName: peer.verified.fromNodeName ?? \"\",\n nodeCellId: peer.verified.fromCellId,\n topicId: replyTopicId,\n userId,\n requestId,\n },\n });\n } catch (error) {\n releasePeerInboxRequest(peer.verified.fromCellId, requestId, \"ask\");\n throw error;\n }\n void flushSessionInbox();\n return Response.json({ ok: true });\n}\n\nasync function handleReply(req: Request): Promise<Response> {\n const peer = await requirePeer(req);\n if (!peer.ok) return peer.response;\n const originError = requirePrimaryOrigin(peer);\n if (originError) return originError;\n const body = await readBody(req);\n if (!body) return jsonError(\"invalid JSON body\", 400);\n const protocolError = checkProtocol(body);\n if (protocolError) return protocolError;\n const requestId = str(body, \"requestId\");\n const userId = str(body, \"userId\");\n const replyText = typeof body.replyText === \"string\" ? body.replyText : null;\n const fromLabel = str(body, \"fromLabel\") ?? \"peer\";\n const kind = body.kind === \"error\" ? \"error\" : \"reply\";\n if (!requestId || !userId || replyText === null) {\n return jsonError(\"requestId, userId and replyText are required\", 400);\n }\n const accepted = await acceptRemoteAskReplyResult({\n fromCellId: peer.verified.fromCellId,\n requestId,\n userId,\n fromLabel,\n replyText,\n kind,\n });\n if (accepted === \"accepted\") return Response.json({ ok: true });\n if (accepted === \"retry\") return jsonError(\"ask callback delivery is retryable\", 503);\n return jsonError(\"no pending ask for this requestId\", 404);\n}\n\nasync function handleInputFile(req: Request): Promise<Response> {\n const peer = await requirePeer(req);\n if (!peer.ok) return peer.response;\n const originError = requirePrimaryOrigin(peer);\n if (originError) return originError;\n const contentLength = Number(req.headers.get(\"content-length\"));\n if (Number.isFinite(contentLength) && contentLength > MAX_PEER_INPUT_REQUEST_BYTES) {\n return jsonError(\"file too large\", 413);\n }\n const form = await req.formData().catch(() => null);\n if (!form) return jsonError(\"expected multipart/form-data\", 400);\n const hostTopicId = form.get(\"hostTopicId\");\n const userId = form.get(\"userId\");\n const file = form.get(\"file\");\n if (typeof hostTopicId !== \"string\" || typeof userId !== \"string\" || !(file instanceof File)) {\n return jsonError(\"hostTopicId, userId, and file are required\", 400);\n }\n if (file.size > MAX_PEER_INPUT_FILE_BYTES) return jsonError(\"file too large\", 413);\n const session = getPeerSession(peer.verified.fromCellId, hostTopicId);\n const topic = session ? getTopic(session.local_topic_id) : null;\n if (!session || !topic?.participants.some((participant) => participant.userId === userId)) {\n return jsonError(\"provisioned peer room not found\", 404);\n }\n const stored = await storePeerInputFile(file, {\n topicId: session.local_topic_id,\n ownerUserId: userId,\n });\n return Response.json({ ok: true, fileId: stored.id });\n}\n\n/** Hub-mediated management of this device's encrypted, node-local vault.\n * Secret values are accepted only for `set` and are never returned or logged. */\nasync function handleDeviceVault(req: Request): Promise<Response> {\n const peer = await requirePeer(req);\n if (!peer.ok) return peer.response;\n const originError = requirePrimaryOrigin(peer);\n if (originError) return originError;\n const body = await readBody(req);\n if (!body) return jsonError(\"invalid JSON body\", 400);\n const protocolError = checkProtocol(body);\n if (protocolError) return protocolError;\n const userId = str(body, \"userId\");\n const operation = str(body, \"operation\");\n if (!userId || !operation) return jsonError(\"userId and operation are required\", 400);\n\n if (operation === \"list\") {\n return Response.json({ ok: true, entries: vaultList(userId) });\n }\n\n const rawKey = str(body, \"key\");\n if (!rawKey || !validateVaultKey(rawKey)) return jsonError(\"invalid vault key\", 400);\n const key = normalizeVaultKey(rawKey);\n if (operation === \"delete\") {\n return vaultDel(userId, key)\n ? Response.json({ ok: true, deleted: key })\n : jsonError(`vault key \"${key}\" not found`, 404);\n }\n if (operation !== \"set\") return jsonError(\"invalid vault operation\", 400);\n\n const value = typeof body.value === \"string\" ? body.value : \"\";\n const valueBytes = Buffer.byteLength(value, \"utf8\");\n if (valueBytes < VAULT_VALUE_MIN_BYTES || valueBytes > VAULT_VALUE_MAX_BYTES) {\n return jsonError(\n `value must be between ${VAULT_VALUE_MIN_BYTES} and ${VAULT_VALUE_MAX_BYTES} bytes`,\n 400,\n );\n }\n const description = body.description === undefined ? \"\" : body.description;\n if (typeof description !== \"string\" || description.length > VAULT_DESCRIPTION_MAX_LENGTH) {\n return jsonError(`description must be at most ${VAULT_DESCRIPTION_MAX_LENGTH} characters`, 400);\n }\n vaultSet(userId, key, value, description);\n return Response.json({ ok: true, key, ...(description ? { description } : {}) });\n}\n\n// ── Router ───────────────────────────────────────────────────────────\n\n/**\n * Handle one inbound request if it belongs to the otium worker surface.\n * Returns null for every other path so the host can chain its own handlers.\n */\nexport async function handleOtiumPeerRequest(req: Request): Promise<Response | null> {\n const url = new URL(req.url);\n const path = url.pathname;\n\n if (path === \"/ready\" && req.method === \"GET\") {\n // Unauthenticated hub probe (3s timeout hub-side). Only claim readiness\n // when the worker is actually joined; otherwise let the host decide.\n if (!otiumCentralConfig()) return null;\n return Response.json({ ok: true });\n }\n\n if (!path.startsWith(\"/api/v1/peer/\")) return null;\n\n if (req.method === \"GET\") {\n if (path === \"/api/v1/peer/capabilities\") {\n const peer = await requirePeer(req);\n if (!peer.ok) return peer.response;\n return Response.json({ ok: true, ...localCapabilities() });\n }\n if (path === \"/api/v1/peer/health\") {\n const peer = await requirePeer(req);\n if (!peer.ok) return peer.response;\n return Response.json({ ok: true, ...localHealth() });\n }\n return jsonError(\"not found\", 404);\n }\n\n if (req.method !== \"POST\") return jsonError(\"not found\", 404);\n switch (path) {\n case \"/api/v1/peer/provision\":\n return handleProvision(req);\n case \"/api/v1/peer/bind\":\n return handleBind(req);\n case \"/api/v1/peer/unbind\":\n return handleUnbind(req);\n case \"/api/v1/peer/turn\":\n return handleTurn(req);\n case \"/api/v1/peer/abort\":\n return handleAbort(req);\n case \"/api/v1/peer/tell\":\n return handleTell(req);\n case \"/api/v1/peer/ask\":\n return handleAsk(req);\n case \"/api/v1/peer/sessions\":\n return handleSessions(req);\n case \"/api/v1/peer/reply\":\n return handleReply(req);\n case \"/api/v1/peer/input-file\":\n return handleInputFile(req);\n case \"/api/v1/peer/device-vault\":\n return handleDeviceVault(req);\n default:\n return jsonError(\"not found\", 404);\n }\n}\n",
14
- "/**\n * Worker-side peer turn execution. Each hub room maps to one hidden local\n * mirror topic (otium_peer_sessions) that reuses negotium's normal turn\n * pipeline — session resume, MCP catalog, project cwd, abort/preempt.\n *\n * Port of otium's `apps/runtime-api/src/peer/turn-runner.ts` on top of the\n * `@negotium/core` barrel:\n * - executionSpec has no direct `triggerTopicAiTurn` parameter, so the\n * hub-resolved model/effort/mcp are pinned via\n * `setApiTopicConfig` right before the turn — config override wins over\n * topic defaults in `startAiTurn`, which makes the hub spec authoritative.\n * - agent/model changes invalidate the stored provider session\n * (`peer-execution-spec-changed`), matching otium.\n * - hub-resolved config is pinned on the mirror topic,\n * while `peerBridge` carries canonical-room mutations such as\n * spawn_subagent back to Otium.\n */\n\nimport { randomUUID } from \"node:crypto\";\nimport {\n type AgentKind,\n abortRoom,\n clearTopicSessionId,\n type EffortLevel,\n type ExecuteExternalUserTurnParams,\n executeExternalUserTurn,\n getApiTopicConfig,\n getRoomQuery,\n getTopic,\n isAgentKind,\n isTopicShared,\n isTopicVisible,\n logger,\n setApiTopicConfig,\n upsertTopic,\n} from \"@negotium/core\";\nimport type { PeerNode } from \"@/central\";\nimport {\n createTurnForwarder,\n getActiveForwarder,\n hubEventSender,\n registerTurnForwarder,\n type SendPeerEvent,\n} from \"@/event-backflow\";\nimport { peerFileAllowsAccess } from \"@/peer-files\";\nimport type { PeerProvisionRequest, PeerTurnRequest, PlacedTopicExecutionSpec } from \"@/protocol\";\nimport {\n claimPeerTurnRequest,\n createPeerSession,\n getPeerSession,\n getPeerTurnRequest,\n markPeerTurnRequestFailed,\n markPeerTurnRequestRunning,\n} from \"@/store\";\n\nconst EFFORT_LEVELS: readonly string[] = [\"low\", \"medium\", \"high\", \"xhigh\", \"max\"];\n\nfunction executionFor(payload: PeerTurnRequest): PlacedTopicExecutionSpec | null {\n if (payload.execution) return payload.execution;\n if (!payload.agent) return null;\n return {\n agent: payload.agent,\n model: payload.model ?? \"\",\n effort: payload.effort ?? \"medium\",\n mcp: [],\n canSpawnSubagents: false,\n };\n}\n\nexport type ProvisionResult =\n | { ok: true; localTopicId: string; bindingMode: \"mirror\" | \"shared\" }\n | { ok: false; error: string; status: number };\n\n/**\n * Idempotent hidden-mirror upsert keyed on (hostCellId, hostTopicId). The\n * mirror has explicit `visibility: hidden`. `isSubagent` remains separate\n * execution metadata (MCP whitelist not inherited); `canSpawnSubagents` is\n * carried separately in the per-turn peerBridge context.\n */\nexport function provisionMirrorTopic(\n hostCellId: string,\n payload: Omit<PeerProvisionRequest, \"v\">,\n): ProvisionResult {\n const execution = payload.execution;\n if (!isAgentKind(execution.agent)) {\n return { ok: false, error: `unknown agent \"${execution.agent}\"`, status: 400 };\n }\n const existing = getPeerSession(hostCellId, payload.hostTopicId);\n if (existing?.binding_mode === \"shared\") {\n const shared = getTopic(existing.local_topic_id);\n if (!shared) {\n return { ok: false, error: \"bound local topic no longer exists\", status: 404 };\n }\n if (!isTopicVisible(shared)) {\n return { ok: false, error: \"bound local topic is hidden\", status: 409 };\n }\n if (!isTopicShared(shared)) {\n return { ok: false, error: \"bound local topic is private\", status: 409 };\n }\n if (!shared.participants.some((participant) => participant.userId === payload.userId)) {\n return { ok: false, error: \"bound local topic is not visible to this user\", status: 403 };\n }\n return { ok: true, localTopicId: shared.id, bindingMode: \"shared\" };\n }\n const localTopicId = existing?.local_topic_id ?? `peer-${randomUUID()}`;\n const now = new Date().toISOString();\n const current = existing ? getTopic(localTopicId) : null;\n const currentConfig = current ? getApiTopicConfig(localTopicId) : undefined;\n const currentModel = currentConfig?.model ?? current?.defaultModel ?? \"\";\n const nextModel = execution.model || current?.defaultModel || \"\";\n const providerSessionIsStale =\n Boolean(current) && (current?.agent !== execution.agent || currentModel !== nextModel);\n upsertTopic({\n id: localTopicId,\n title: payload.topicTitle,\n kind: \"agent\",\n agent: execution.agent as AgentKind,\n aiMode: \"always\",\n defaultModel: nextModel,\n defaultEffort: EFFORT_LEVELS.includes(execution.effort)\n ? (execution.effort as EffortLevel)\n : (current?.defaultEffort ?? \"medium\"),\n participants: [{ userId: payload.userId, role: \"owner\" }],\n isSubagent: true,\n visibility: \"hidden\",\n accessMode: \"shared\",\n ...(execution.description ? { description: execution.description } : {}),\n createdAt: current?.createdAt ?? now,\n lastMessageAt: now,\n });\n // Pin the hub-resolved execution spec as the topic's\n // config override so startAiTurn resolves exactly the hub's values.\n setApiTopicConfig(localTopicId, {\n ...(execution.model ? { model: execution.model } : {}),\n ...(EFFORT_LEVELS.includes(execution.effort)\n ? { effort: execution.effort as EffortLevel }\n : {}),\n mcp: execution.mcp,\n });\n if (providerSessionIsStale) {\n clearTopicSessionId(localTopicId, \"peer-execution-spec-changed\");\n }\n if (!existing) createPeerSession(hostCellId, payload.hostTopicId, localTopicId);\n return { ok: true, localTopicId, bindingMode: \"mirror\" };\n}\n\nexport type RunPeerTurnResult = { ok: true } | { ok: false; error: string; status: number };\n\ntype TurnTrigger = NonNullable<ExecuteExternalUserTurnParams[\"dispatch\"]>;\n\nlet turnTrigger: TurnTrigger | undefined;\n\n/** Test seam — replace the turn dispatcher so tests never start a real\n * provider turn (and never spend agent API tokens). */\nexport function __setTurnTriggerForTests(trigger: TurnTrigger | null): void {\n turnTrigger = trigger ?? undefined;\n}\n\n/**\n * Resolve (or create) the hidden execution topic for a hub room and run one\n * turn on it. Accepting is synchronous ({ok:true} means \"claimed and\n * started\"); every result flows back through `/api/v1/peer/event`.\n */\nexport function runPeerTurn(\n hubNode: PeerNode,\n hostCellId: string,\n payload: PeerTurnRequest,\n opts: { sendEvent?: SendPeerEvent } = {},\n): RunPeerTurnResult {\n const execution = executionFor(payload);\n if (!execution || !isAgentKind(execution.agent)) {\n return { ok: false, error: `unknown agent \"${execution?.agent ?? \"\"}\"`, status: 400 };\n }\n\n // Durable exactly-once claim (at-least-once senders): a replay of a\n // non-failed request acks without re-execution; the same requestId bound to\n // another room is a hard conflict.\n const claim = claimPeerTurnRequest(hostCellId, payload.requestId, payload.hostTopicId);\n if (!claim.claimed) {\n if (claim.row.host_topic_id !== payload.hostTopicId) {\n return { ok: false, error: \"requestId already belongs to another room\", status: 409 };\n }\n if (claim.row.status === \"failed\") {\n return { ok: false, error: claim.row.error ?? \"previous attempt failed\", status: 409 };\n }\n logger.info(\n { requestId: payload.requestId, hostTopicId: payload.hostTopicId, status: claim.row.status },\n \"otium: peer turn replay acknowledged without re-execution\",\n );\n return { ok: true };\n }\n\n const provisioned = provisionMirrorTopic(hostCellId, {\n userId: payload.userId,\n hostTopicId: payload.hostTopicId,\n topicTitle: payload.topicTitle,\n execution,\n });\n if (!provisioned.ok) {\n markPeerTurnRequestFailed(hostCellId, payload.requestId, provisioned.error);\n return provisioned;\n }\n const localTopicId = provisioned.localTopicId;\n const localTopic = getTopic(localTopicId);\n if (\n payload.attachments?.some(\n (fileId) =>\n !peerFileAllowsAccess(fileId, { topicId: localTopicId, ownerUserId: payload.userId }),\n )\n ) {\n markPeerTurnRequestFailed(hostCellId, payload.requestId, \"attachment access denied\");\n return { ok: false, error: \"attachment access denied\", status: 403 };\n }\n const turnAgent =\n provisioned.bindingMode === \"shared\" && localTopic?.agent\n ? localTopic.agent\n : (execution.agent as AgentKind);\n\n // A new turn for a room whose previous turn is still streaming supersedes\n // it (user preemption). Settle the old forwarder so the hub's old\n // peer_turn reaches a terminal state instead of dangling until the\n // watchdog.\n const previous = getActiveForwarder(localTopicId);\n if (previous) {\n previous.finish({\n type: \"ai_aborted\",\n queryId: previous.queryId ?? previous.requestId,\n topicId: localTopicId,\n reason: \"superseded\",\n });\n }\n\n const forwarder = createTurnForwarder({\n hostNodeId: hostCellId,\n requestId: payload.requestId,\n localTopicId,\n sendEvent: opts.sendEvent ?? hubEventSender(hubNode),\n });\n registerTurnForwarder(localTopicId, forwarder);\n\n let queryId: string | null = null;\n try {\n queryId = executeExternalUserTurn({\n topicId: localTopicId,\n userId: payload.userId,\n text: payload.message,\n agent: turnAgent,\n options: {\n // \"user\" origin: a fresh hub message preempts a running turn, exactly\n // like a local room.\n origin: \"user\",\n requestId: payload.requestId,\n injectAuthorId: payload.userId,\n attachments: payload.attachments,\n visualTools: true,\n // Provider session recovery dispatches a fresh queryId. Keep the\n // forwarder on that retry so its messages and terminal are not filtered\n // as stale events from the superseded provider attempt.\n onDispatched: (dispatchedQueryId) => {\n forwarder.queryId = dispatchedQueryId;\n },\n peerBridge: {\n hubCellId: hostCellId,\n hostTopicId: payload.hostTopicId,\n hostQueryId: payload.requestId,\n canSpawnSubagents: execution.canSpawnSubagents,\n },\n },\n ...(turnTrigger ? { dispatch: turnTrigger } : {}),\n });\n } catch (err) {\n forwarder.finish({\n type: \"ai_error\",\n queryId: payload.requestId,\n topicId: localTopicId,\n error: `worker dispatch crashed: ${(err as Error).message}`,\n });\n return { ok: false, error: \"failed to start turn\", status: 500 };\n }\n if (!queryId) {\n forwarder.finish({\n type: \"ai_error\",\n queryId: payload.requestId,\n topicId: localTopicId,\n error: \"worker could not start the turn\",\n });\n return { ok: false, error: \"failed to start turn\", status: 500 };\n }\n // Test seams and older dispatchers may return an id without invoking the\n // hook; the returned initial id remains the fallback.\n forwarder.queryId = queryId;\n markPeerTurnRequestRunning(hostCellId, payload.requestId);\n logger.info(\n { requestId: payload.requestId, localTopicId, queryId, title: payload.topicTitle },\n \"otium: peer turn running\",\n );\n return { ok: true };\n}\n\n/**\n * Abort one exact hub request — only when that request is still the room's\n * active turn, so a stale abort cannot terminate a successor turn that\n * started while it was in flight. The worker's `ai_aborted` event (emitted by\n * the dying turn through the bus) is the authoritative terminal.\n */\nexport function abortHostedPeerTurn(\n hostNodeId: string,\n requestId: string,\n userId: string,\n topicTitle: string,\n): boolean {\n const request = getPeerTurnRequest(hostNodeId, requestId);\n if (!request || request.status !== \"running\") return false;\n const session = getPeerSession(hostNodeId, request.host_topic_id);\n if (!session) return false;\n const topic = getTopic(session.local_topic_id);\n if (\n !topic ||\n topic.title !== topicTitle ||\n !topic.participants.some((participant) => participant.userId === userId)\n ) {\n return false;\n }\n const forwarder = getActiveForwarder(session.local_topic_id);\n if (!forwarder || forwarder.requestId !== requestId) return false;\n if (!getRoomQuery(session.local_topic_id)) return false;\n return abortRoom(session.local_topic_id);\n}\n",
15
- "/**\n * @negotium/adapter-otium public API.\n *\n * Turns an embedded negotium runtime into an otium workspace **worker node**\n * (docs/OTIUM-COUPLING.md). A host wires it in three lines:\n *\n * const worker = startOtiumWorker(); // no-op when not joined\n * Bun.serve({ fetch: async (req) =>\n * (await handleOtiumPeerRequest(req)) ?? (await handleNegotiumMcpRequest(req)) ?? … });\n */\n\nimport { defineNegotiumAdapter, type NegotiumAdapterHandle } from \"@negotium/adapter-sdk\";\nimport {\n failInterruptedRemoteAskCallbacks,\n logger,\n NEGOTIUM_VERSION,\n registerPeerRuntimeBridge,\n registerPeerSessionBridge,\n runtimeBus,\n} from \"@negotium/core\";\nimport { startCanonicalMcpBridge } from \"@/canonical-mcp-bridge\";\nimport { configureOtiumCentral, selfPeerNode } from \"@/central\";\nimport { startEventBackflow } from \"@/event-backflow\";\nimport { loadJoin, type OtiumJoin } from \"@/join\";\nimport { installPeerFileHooks } from \"@/peer-files\";\nimport { otiumPeerRuntimeBridge } from \"@/runtime-bridge\";\nimport { otiumPeerSessionBridge, startPeerReplyOutboxWorker } from \"@/session-bridge\";\nimport { startPeerSessionBridgeIpc } from \"@/session-bridge-ipc\";\nimport { cleanupPeerStateForLocalTopic, failInterruptedPeerTurnRequestsOnStartup } from \"@/store\";\nimport { TunnelClient, type TunnelClientOptions } from \"@/tunnel-client\";\n\nexport {\n bindOtiumTopic,\n listOtiumTopicBindings,\n type OtiumTopicBinding,\n type OtiumTopicBindingResult,\n type OtiumTopicPrivateResult,\n setOtiumTopicPrivate,\n shareOtiumTopic,\n unbindOtiumTopic,\n} from \"@/bindings\";\n\nexport {\n configureOtiumCentral,\n listPeerNodes,\n mintPeerToken,\n otiumCentralConfig,\n type PeerNode,\n resetPeerCentralCaches,\n resolvePeerNodeByCellId,\n selfPeerNode,\n type VerifiedPeer,\n verifyPeerToken,\n} from \"@/central\";\nexport {\n claimEnrollment,\n commitEnrollment,\n type EnrollmentCredentialEnvelope,\n type EnrollmentInvite,\n isEnrollmentPending,\n parseEnrollmentInvite,\n pendingEnrollmentPath,\n previewEnrollment,\n} from \"@/enrollment\";\nexport {\n createTurnForwarder,\n getActiveForwarder,\n hubEventSender,\n registerTurnForwarder,\n type SendPeerEvent,\n startEventBackflow,\n stopEventBackflow,\n type TurnForwarder,\n translateBusEvent,\n} from \"@/event-backflow\";\nexport {\n isJoinPersisted,\n joinFilePath,\n loadJoin,\n type OtiumJoin,\n parseInviteCode,\n type SaveJoinOptions,\n saveJoin,\n} from \"@/join\";\nexport { handleOtiumPeerRequest } from \"@/peer-server\";\nexport {\n PEER_PROTOCOL_VERSION,\n type PeerEventRequest,\n type PeerProvisionRequest,\n type PeerTurnRequest,\n type PlacedTopicExecutionSpec,\n} from \"@/protocol\";\nexport {\n type HeaderPairs as RelayHeaderPairs,\n PROTOCOL_VERSION as RELAY_PROTOCOL_VERSION,\n} from \"@/relay-protocol\";\nexport { otiumPeerRuntimeBridge } from \"@/runtime-bridge\";\nexport { cleanupPeerStateForLocalTopic, failInterruptedPeerTurnRequestsOnStartup } from \"@/store\";\nexport {\n TunnelClient,\n type TunnelClientOptions,\n type TunnelLogger,\n type TunnelStatus,\n} from \"@/tunnel-client\";\nexport {\n abortHostedPeerTurn,\n provisionMirrorTopic,\n type RunPeerTurnResult,\n runPeerTurn,\n} from \"@/turn-bridge\";\n\nexport interface OtiumAdapterOptions {\n join: OtiumJoin;\n}\n\nexport interface OtiumWorkerHandle extends NegotiumAdapterHandle<\"otium\"> {\n join: OtiumJoin;\n startTunnel(options: Pick<TunnelClientOptions, \"targetOrigin\"> & { relayUrl?: string }): void;\n}\n\n/** Start the configured Otium channel adapter. */\nexport function startOtiumAdapter(options: OtiumAdapterOptions): OtiumWorkerHandle {\n const { join } = options;\n configureOtiumCentral(join);\n const failed = failInterruptedPeerTurnRequestsOnStartup();\n if (failed > 0) {\n logger.warn({ failed }, \"otium: failed interrupted peer turns from previous process\");\n }\n const stopBackflow = startEventBackflow();\n const unregisterRuntimeBridge = registerPeerRuntimeBridge(otiumPeerRuntimeBridge);\n const unregisterSessionBridge = registerPeerSessionBridge(otiumPeerSessionBridge);\n const sessionBridgeIpc = startPeerSessionBridgeIpc(otiumPeerSessionBridge);\n const canonicalMcpBridge = startCanonicalMcpBridge();\n const stopPeerReplyOutbox = startPeerReplyOutboxWorker();\n void failInterruptedRemoteAskCallbacks().then((failedAsks) => {\n if (failedAsks > 0) {\n logger.warn({ failedAsks }, \"otium: failed remote asks interrupted by previous process\");\n }\n });\n const uninstallFileHooks = installPeerFileHooks();\n const unsubscribeTopicCleanup = runtimeBus().subscribe((event) => {\n if (event.type !== \"topic-deleted\") return;\n const removed = cleanupPeerStateForLocalTopic(event.topicId);\n if (removed.sessions + removed.turns + removed.inboxRequests + removed.remoteAsks > 0) {\n logger.info(\n { topicId: event.topicId, ...removed },\n \"otium: removed peer state for deleted local topic\",\n );\n }\n });\n let stopped = false;\n let tunnel: TunnelClient | null = null;\n logger.info({ central: join.central, cellId: join.cellId }, \"otium: worker mode enabled\");\n void selfPeerNode()\n .then((self) => {\n if (self) {\n logger.info(\n { nodeName: self.nodeName, baseUrl: self.baseUrl },\n \"otium: attached to workspace\",\n );\n }\n })\n .catch((err) => {\n logger.warn({ err }, \"otium: self check against central failed (will retry per request)\");\n });\n return {\n name: \"otium\",\n join,\n startTunnel: ({ targetOrigin, relayUrl }) => {\n if (stopped || tunnel) return;\n const selectedRelay = relayUrl?.trim() || join.relay || process.env.OTIUM_RELAY_URL?.trim();\n if (!selectedRelay) {\n logger.info({}, \"otium: relay tunnel disabled (no relay URL configured)\");\n return;\n }\n tunnel = new TunnelClient({\n relayUrl: selectedRelay,\n token: join.secret,\n targetOrigin,\n nodeVersion: `negotium@${NEGOTIUM_VERSION}`,\n logger,\n });\n tunnel.start();\n },\n stop: () => {\n if (stopped) return;\n stopped = true;\n tunnel?.stop();\n tunnel = null;\n unsubscribeTopicCleanup();\n unregisterRuntimeBridge();\n unregisterSessionBridge();\n sessionBridgeIpc.stop();\n canonicalMcpBridge.stop();\n stopPeerReplyOutbox();\n uninstallFileHooks();\n stopBackflow();\n configureOtiumCentral(null);\n },\n };\n}\n\n/** Declarative form used by hosts that load adapters from a registry. */\nexport const otiumAdapter = defineNegotiumAdapter({\n name: \"otium\",\n capabilities: {\n localUserInput: false,\n topicManagement: false,\n externalPlacedTurn: true,\n },\n projection: {\n transcript: \"full\",\n // The hub has no generic bound-topic projection/backfill endpoint yet.\n historyBackfill: false,\n externalAuthors: \"relayed\",\n },\n start: startOtiumAdapter,\n});\n\n/**\n * Wire this node up as an otium worker: load the join file (or env triple),\n * point the central client at it, fail interrupted turns from a previous\n * process, and start the bus → hub event backflow. Returns null (and mounts\n * nothing) when the node has not joined a workspace. Otium-aware hosts call\n * this before starting the shared node.\n */\nexport function startOtiumWorker(): OtiumWorkerHandle | null {\n const join = loadJoin();\n if (!join) return null;\n return startOtiumAdapter({ join });\n}\n"
16
- ],
17
- "mappings": "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",
18
- "debugId": "F8CF1BBB03F509B664756E2164756E21",
19
- "names": []
20
- }