@athenaintel/react 0.53.1 → 0.54.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/README.md +18 -1
  2. package/dist/agent-runtime/src/call-recap.cjs +2 -3
  3. package/dist/agent-runtime/src/call-recap.cjs.map +1 -1
  4. package/dist/agent-runtime/src/call-recap.d.ts +1 -2
  5. package/dist/agent-runtime/src/call-recap.js +1 -2
  6. package/dist/agent-runtime/src/call-recap.js.map +1 -1
  7. package/dist/agent-runtime/src/deep-agent-transport-recipe.cjs +7 -3
  8. package/dist/agent-runtime/src/deep-agent-transport-recipe.cjs.map +1 -1
  9. package/dist/agent-runtime/src/deep-agent-transport-recipe.d.ts +10 -2
  10. package/dist/agent-runtime/src/deep-agent-transport-recipe.js +8 -4
  11. package/dist/agent-runtime/src/deep-agent-transport-recipe.js.map +1 -1
  12. package/dist/agent-runtime/src/dictation-session.d.ts +158 -0
  13. package/dist/agent-runtime/src/edit-command.cjs +6 -0
  14. package/dist/agent-runtime/src/edit-command.cjs.map +1 -1
  15. package/dist/agent-runtime/src/edit-command.d.ts +8 -0
  16. package/dist/agent-runtime/src/edit-command.js +6 -0
  17. package/dist/agent-runtime/src/edit-command.js.map +1 -1
  18. package/dist/agent-runtime/src/generated/runconfig-contract.cjs +6 -0
  19. package/dist/agent-runtime/src/generated/runconfig-contract.cjs.map +1 -1
  20. package/dist/agent-runtime/src/generated/runconfig-contract.d.ts +13 -0
  21. package/dist/agent-runtime/src/generated/runconfig-contract.js +6 -0
  22. package/dist/agent-runtime/src/generated/runconfig-contract.js.map +1 -1
  23. package/dist/agent-runtime/src/index.d.ts +6 -6
  24. package/dist/agent-runtime/src/message-window.cjs +111 -7
  25. package/dist/agent-runtime/src/message-window.cjs.map +1 -1
  26. package/dist/agent-runtime/src/message-window.d.ts +66 -6
  27. package/dist/agent-runtime/src/message-window.js +112 -8
  28. package/dist/agent-runtime/src/message-window.js.map +1 -1
  29. package/dist/agent-runtime/src/offline-status.cjs.map +1 -1
  30. package/dist/agent-runtime/src/offline-status.d.ts +33 -0
  31. package/dist/agent-runtime/src/offline-status.js.map +1 -1
  32. package/dist/agent-runtime/src/runtime.d.ts +4 -3
  33. package/dist/agent-runtime/src/subagent-transcripts.cjs +23 -1
  34. package/dist/agent-runtime/src/subagent-transcripts.cjs.map +1 -1
  35. package/dist/agent-runtime/src/subagent-transcripts.js +25 -3
  36. package/dist/agent-runtime/src/subagent-transcripts.js.map +1 -1
  37. package/dist/agent-runtime/src/subagents.cjs +112 -0
  38. package/dist/agent-runtime/src/subagents.cjs.map +1 -1
  39. package/dist/agent-runtime/src/subagents.d.ts +103 -0
  40. package/dist/agent-runtime/src/subagents.js +113 -1
  41. package/dist/agent-runtime/src/subagents.js.map +1 -1
  42. package/dist/agent-runtime/src/thread-handoff-protocol.d.ts +37 -9
  43. package/dist/agent-runtime/src/thread-handoff.d.ts +1 -1
  44. package/dist/agent-runtime/src/tool-metadata.cjs +8 -0
  45. package/dist/agent-runtime/src/tool-metadata.cjs.map +1 -1
  46. package/dist/agent-runtime/src/tool-metadata.js +8 -0
  47. package/dist/agent-runtime/src/tool-metadata.js.map +1 -1
  48. package/dist/agent-runtime/src/use-deep-agent-thread.cjs +6 -0
  49. package/dist/agent-runtime/src/use-deep-agent-thread.cjs.map +1 -1
  50. package/dist/agent-runtime/src/use-deep-agent-thread.js +7 -1
  51. package/dist/agent-runtime/src/use-deep-agent-thread.js.map +1 -1
  52. package/dist/agent-runtime/src/use-deep-agent-window-sync.cjs +39 -10
  53. package/dist/agent-runtime/src/use-deep-agent-window-sync.cjs.map +1 -1
  54. package/dist/agent-runtime/src/use-deep-agent-window-sync.d.ts +14 -4
  55. package/dist/agent-runtime/src/use-deep-agent-window-sync.js +41 -12
  56. package/dist/agent-runtime/src/use-deep-agent-window-sync.js.map +1 -1
  57. package/dist/agent-runtime/src/use-thread-handoff-flow.d.ts +5 -9
  58. package/dist/agent-runtime/src/voice-presentation.cjs +34 -0
  59. package/dist/agent-runtime/src/voice-presentation.cjs.map +1 -1
  60. package/dist/agent-runtime/src/voice-presentation.d.ts +35 -0
  61. package/dist/agent-runtime/src/voice-presentation.js +34 -0
  62. package/dist/agent-runtime/src/voice-presentation.js.map +1 -1
  63. package/dist/assets/AthenaAssetEmbed.cjs +4 -2
  64. package/dist/assets/AthenaAssetEmbed.cjs.map +1 -1
  65. package/dist/assets/AthenaAssetEmbed.d.ts +17 -8
  66. package/dist/assets/AthenaAssetEmbed.js +4 -2
  67. package/dist/assets/AthenaAssetEmbed.js.map +1 -1
  68. package/dist/assets/use-asset-embed.cjs.map +1 -1
  69. package/dist/assets/use-asset-embed.d.ts +7 -5
  70. package/dist/assets/use-asset-embed.js.map +1 -1
  71. package/dist/auth/account-identity.cjs +69 -0
  72. package/dist/auth/account-identity.cjs.map +1 -0
  73. package/dist/auth/account-identity.d.ts +57 -0
  74. package/dist/auth/account-identity.js +69 -0
  75. package/dist/auth/account-identity.js.map +1 -0
  76. package/dist/chat/AthenaChat.cjs +1 -1
  77. package/dist/chat/AthenaChat.cjs.map +1 -1
  78. package/dist/chat/AthenaChat.js +1 -1
  79. package/dist/chat/AthenaChat.js.map +1 -1
  80. package/dist/chat/super-grouping/toolkit-map.cjs +1 -0
  81. package/dist/chat/super-grouping/toolkit-map.cjs.map +1 -1
  82. package/dist/chat/super-grouping/toolkit-map.js +1 -0
  83. package/dist/chat/super-grouping/toolkit-map.js.map +1 -1
  84. package/dist/chat/use-statewire-approval-request.cjs +5 -5
  85. package/dist/chat/use-statewire-approval-request.cjs.map +1 -1
  86. package/dist/chat/use-statewire-approval-request.d.ts +7 -0
  87. package/dist/chat/use-statewire-approval-request.js +5 -5
  88. package/dist/chat/use-statewire-approval-request.js.map +1 -1
  89. package/dist/chat-ui/mentions/use-account-workspace-id.cjs +18 -58
  90. package/dist/chat-ui/mentions/use-account-workspace-id.cjs.map +1 -1
  91. package/dist/chat-ui/mentions/use-account-workspace-id.js +18 -58
  92. package/dist/chat-ui/mentions/use-account-workspace-id.js.map +1 -1
  93. package/dist/chat-ui/messages/voice-delegation-card.cjs +93 -25
  94. package/dist/chat-ui/messages/voice-delegation-card.cjs.map +1 -1
  95. package/dist/chat-ui/messages/voice-delegation-card.d.ts +16 -7
  96. package/dist/chat-ui/messages/voice-delegation-card.js +95 -27
  97. package/dist/chat-ui/messages/voice-delegation-card.js.map +1 -1
  98. package/dist/chat-ui/thread/handoff-cursor.cjs +2 -2
  99. package/dist/chat-ui/thread/handoff-cursor.cjs.map +1 -1
  100. package/dist/chat-ui/thread/handoff-cursor.js +3 -3
  101. package/dist/chat-ui/thread/handoff-cursor.js.map +1 -1
  102. package/dist/collab/client.cjs +94 -6
  103. package/dist/collab/client.cjs.map +1 -1
  104. package/dist/collab/client.d.ts +27 -0
  105. package/dist/collab/client.js +94 -6
  106. package/dist/collab/client.js.map +1 -1
  107. package/dist/collab/index.d.ts +1 -1
  108. package/dist/keryx-http/src/initial-sync.cjs +121 -0
  109. package/dist/keryx-http/src/initial-sync.cjs.map +1 -0
  110. package/dist/keryx-http/src/initial-sync.d.ts +77 -0
  111. package/dist/keryx-http/src/initial-sync.js +104 -0
  112. package/dist/keryx-http/src/initial-sync.js.map +1 -0
  113. package/dist/keryx-http/src/unconfirmed-update-attributions.cjs +8 -0
  114. package/dist/keryx-http/src/unconfirmed-update-attributions.cjs.map +1 -1
  115. package/dist/keryx-http/src/unconfirmed-update-attributions.d.ts +6 -0
  116. package/dist/keryx-http/src/unconfirmed-update-attributions.js +8 -0
  117. package/dist/keryx-http/src/unconfirmed-update-attributions.js.map +1 -1
  118. package/dist/react/package.json.cjs +1 -1
  119. package/dist/react/package.json.js +1 -1
  120. package/dist/styles.css +1 -1
  121. package/dist/threads/api.cjs +1 -2
  122. package/dist/threads/api.cjs.map +1 -1
  123. package/dist/threads/api.d.ts +3 -2
  124. package/dist/threads/api.js +1 -2
  125. package/dist/threads/api.js.map +1 -1
  126. package/dist/threads/statewire-thread-list.cjs +5 -7
  127. package/dist/threads/statewire-thread-list.cjs.map +1 -1
  128. package/dist/threads/statewire-thread-list.js +7 -9
  129. package/dist/threads/statewire-thread-list.js.map +1 -1
  130. package/dist/tools/subagent-task-tool-ui.cjs +15 -5
  131. package/dist/tools/subagent-task-tool-ui.cjs.map +1 -1
  132. package/dist/tools/subagent-task-tool-ui.d.ts +5 -4
  133. package/dist/tools/subagent-task-tool-ui.js +16 -6
  134. package/dist/tools/subagent-task-tool-ui.js.map +1 -1
  135. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"deep-agent-transport-recipe.js","sources":["../../../../agent-runtime/src/deep-agent-transport-recipe.ts"],"sourcesContent":["import type { ResourceElement } from \"@assistant-ui/tap\";\nimport type { Statewire, StatewireClient } from \"statewire\";\nimport {\n type DeepAgentMessageWindowDeclaration,\n withDeclaredMessageWindow,\n} from \"./message-window\";\nimport { withDeclaredProtocolVersion } from \"./protocol\";\nimport {\n attachRetryGate,\n type AttachRetryGate,\n createAttachInstrumentation,\n type DeepAgentAttachTimingEvent,\n type DeepAgentWakeRefusal,\n parseRetryAfterHeaderMs,\n} from \"./statewire-attach-observer\";\nimport {\n resolveStatewireTransportKind,\n statewireTransport,\n type StatewireTransportOptions,\n} from \"./statewire-transport\";\n\n/** Auth-header resolver for the transport; `staleAuth` is true right after an\n * auth rejection, so resolvers that can force-renew should honor it. */\nexport type DeepAgentHeadersResolver = (ctx: {\n staleAuth: boolean;\n}) => Record<string, string> | Promise<Record<string, string>>;\n\n/** The statewire attach URL for a thread: the host's `…/v2/threads` mount plus the id. */\nexport function deepAgentThreadUrl({\n baseUrl,\n threadId,\n}: {\n baseUrl: string;\n threadId: string;\n}): string {\n return `${baseUrl.replace(/\\/+$/, \"\")}/${encodeURIComponent(threadId)}`;\n}\n\nexport interface DeepAgentAttachTransportOptions {\n /** Base URL of the deep-agent statewire host (the `…/v2/threads` mount). */\n baseUrl: string;\n threadId: string;\n headers: DeepAgentHeadersResolver;\n /** SSE when true, WebSocket otherwise (`resolveStatewireTransportKind`). */\n sse?: boolean;\n /** A never-started chat: the transport makes no network calls until the first command send. */\n isNew?: boolean;\n /** Host session store (mobile); browser hosts mount `storage.session` on the thread instead. */\n sessionStore?: StatewireClient.SessionStorage | undefined;\n /** Observes every headers resolve (the diagnostics recorder's stale-auth seam). */\n onAuthResolve?: ((ctx: { staleAuth: boolean }) => void) | undefined;\n /** Attach timing + retry hints (see `statewire-attach-observer`). */\n onAttachTiming?: ((event: DeepAgentAttachTimingEvent) => void) | undefined;\n /** Dial floors from server retry hints; the process-wide gate by default. */\n retryGate?: AttachRetryGate;\n /**\n * The head window declared on the attach (`x-athena-deep-agent-window`,\n * see `message-window.ts`): the hello of a client the host does not\n * remember carries the newest `size` messages. Part of the recipe so a\n * pooled dial asks for the same shape as the thread's own attach — a pooled\n * hello then seeds the very state the attach will reconcile. Omitted, the\n * shared default is declared.\n */\n messageWindow?: DeepAgentMessageWindowDeclaration | undefined;\n /**\n * The surface pages cut lanes (see `DeepAgentProtocolDeclaration`), so its\n * attach declares the lane-cut contract version. Part of the recipe so a\n * pooled dial declares what the thread's own attach would; omitted, the\n * default version is declared.\n */\n laneHistory?: boolean | undefined;\n}\n\n/**\n * The ONE recipe for a deep-agent thread transport — shared by the mounted\n * thread (`useDeepAgentThread`) and the prewarm pool, so a pre-dialed\n * connection is byte-for-byte the connection the thread would have opened\n * itself: same URL, same auth + wire-contract headers, same session lane, same\n * instrumentation.\n *\n * Every attach declares the surface's wire-contract version alongside the\n * host's auth headers (first WS frame / SSE request headers) — the server\n * half of version negotiation reads it in `authorize`. The headers resolve\n * also waits out any server `Retry-After` floor for the thread: both statewire\n * attach paths resolve headers before they dial, so this is the seam where a\n * hint can hold the next dial without touching the library's backoff.\n */\nexport function createDeepAgentAttachTransport<TState = unknown>({\n baseUrl,\n threadId,\n headers,\n sse = false,\n isNew = false,\n sessionStore,\n onAuthResolve,\n onAttachTiming,\n retryGate = attachRetryGate,\n messageWindow,\n laneHistory = false,\n}: DeepAgentAttachTransportOptions): ResourceElement<\n Statewire<TState | undefined>\n> {\n const url = deepAgentThreadUrl({ baseUrl, threadId });\n // The instrumentation wraps the transport actually built: SSE needs the\n // fetch wrapper that reads a refused attach's `Retry-After`.\n const useSse = resolveStatewireTransportKind({ sse }) === \"sse\";\n const instrumentation = createAttachInstrumentation({\n url,\n sse: useSse,\n onEvent: onAttachTiming,\n retryGate,\n });\n const options: StatewireTransportOptions = {\n url,\n ...(isNew && { isNew: true }),\n headers: async (ctx: { staleAuth: boolean }) => {\n await retryGate.waitForDial(url);\n onAuthResolve?.(ctx);\n return withDeclaredMessageWindow(\n withDeclaredProtocolVersion(await headers(ctx), { laneHistory }),\n messageWindow,\n );\n },\n ...(sessionStore && { sessionStore }),\n // Structural types: this package compiles without the DOM lib, while\n // statewire's option types name the browser `WebSocket`/`fetch`.\n ...(instrumentation.webSocket && {\n webSocket:\n instrumentation.webSocket as unknown as StatewireTransportOptions[\"webSocket\"],\n }),\n ...(instrumentation.fetch && {\n fetch:\n instrumentation.fetch as unknown as StatewireTransportOptions[\"fetch\"],\n }),\n };\n return statewireTransport<TState>(options, { sse: useSse });\n}\n\n/** What `POST …/prewarm` answered. */\nexport interface DeepAgentWakeResult {\n status: number;\n /** The host activated the thread and its history is resident. */\n warm: boolean;\n /**\n * `'warm'` when the history was already memoized, `'fresh_load'` when this\n * call loaded it; `null` when the host did not say (a refusal, or a host\n * without the route).\n */\n history: \"fresh_load\" | \"warm\" | null;\n /**\n * The dial floor recorded for the thread off a 503/429 `Retry-After` — the\n * header's value, except a 503 `\"worker\"` refusal, capped at\n * {@link WAKE_WORKER_REFUSAL_FLOOR_MS}.\n */\n retryAfterMs: number | null;\n /** Who refused a 503/429 (see {@link DeepAgentWakeRefusal}); `null` for any other answer. */\n refusal: DeepAgentWakeRefusal;\n durationMs: number;\n}\n\n/**\n * Dial floor for a 503 the pinned worker produced about one instance's\n * lifecycle. Pinned answers every retriable 503 with a blanket\n * `Retry-After: 1`, but what those name — an instance record mid-teardown\n * (\"instance closing; retry\": fence release + placement release, ≈100 ms), a\n * full activation queue — clears far sooner than that, and the thread's own\n * attach is the request that carries the next activation. Holding it a full\n * second traded a ≈100 ms gap for a ≈1 s stall on every refused wake. A 429\n * is rate limiting and keeps its hint whatever the body says.\n */\nexport const WAKE_WORKER_REFUSAL_FLOOR_MS = 250;\n\n/**\n * The pinboard's own placement-refusal vocabulary — the `error` strings of\n * `@assistant-ui/pinboard` (`src/refusals.ts` plus the two inline refusals in\n * `src/server.ts`). Mirrors `PINBOARD_PLACEMENT_REFUSAL_ERRORS` in\n * `iris/scaler/src/v2AccessLog.ts`, whose test pins it to the installed\n * library; keep the two lists identical. A body with any other `error`\n * string is `\"unknown\"`, never `\"placement\"`.\n */\nexport const PINBOARD_PLACEMENT_REFUSAL_ERRORS: ReadonlySet<string> = new Set([\n \"no live backends for namespace\",\n \"registry cold start, retry\",\n \"not the serving fleet\",\n \"no live workers for hostname\",\n \"hostname binding displaced, retry\",\n \"hostname bindings inconsistent, retry\",\n \"takeover in progress, retry\",\n \"placement held by another hostname\",\n \"worker inflight cap exceeded, retry\",\n \"worker refused activation, retry\",\n]);\n\n/**\n * Pinned's instance-lifecycle refusals (`pinned/hosting/directory.py`,\n * `pinned/hosting/_records.py`): each names one instance on the worker the\n * thread is already placed on and clears in the time a teardown or an\n * activation slot takes. Anything else the worker answers 503 with — \"Thread\n * history load failed\", \"The regional conversation store is temporarily\n * unavailable\", a lease that expired — is not about one instance and keeps\n * the full hint.\n */\nexport const PINNED_TRANSIENT_WORKER_REFUSALS: ReadonlySet<string> = new Set([\n \"instance closing; retry\",\n \"instance aborted\",\n \"activation queue full; retry\",\n \"host draining; retry\",\n \"instance capacity reached; retry\",\n \"instance past its wind-down deadline; retry\",\n]);\n\n/**\n * Classify a 503/429 body (see {@link DeepAgentWakeRefusal}): a known pinboard\n * `error` is `\"placement\"`, a known pinned `detail` is `\"worker\"`, everything\n * else — including unfamiliar strings in either field — is `\"unknown\"`.\n */\nexport function classifyWakeRefusal(\n body: unknown,\n): Exclude<DeepAgentWakeRefusal, null> {\n if (typeof body === \"object\" && body !== null) {\n const record = body as Record<string, unknown>;\n if (\n typeof record.error === \"string\" &&\n PINBOARD_PLACEMENT_REFUSAL_ERRORS.has(record.error)\n ) {\n return \"placement\";\n }\n if (\n typeof record.detail === \"string\" &&\n PINNED_TRANSIENT_WORKER_REFUSALS.has(record.detail)\n ) {\n return \"worker\";\n }\n }\n return \"unknown\";\n}\n\n/** Structural `fetch` for the wake call — this package compiles without the DOM lib. */\nexport type DeepAgentWakeFetch = (\n input: string,\n init?: {\n method?: string;\n headers?: Record<string, string>;\n keepalive?: boolean;\n },\n) => Promise<{\n ok: boolean;\n status: number;\n headers: { get(name: string): string | null };\n json(): Promise<unknown>;\n}>;\n\nexport interface DeepAgentWakeOptions {\n /** Base URL of the deep-agent statewire host (the `…/v2/threads` mount). */\n baseUrl: string;\n threadId: string;\n headers: DeepAgentHeadersResolver;\n fetch?: DeepAgentWakeFetch | undefined;\n /** Dial floors from server retry hints; the process-wide gate by default. */\n retryGate?: AttachRetryGate;\n onAttachTiming?: ((event: DeepAgentAttachTimingEvent) => void) | undefined;\n now?: () => number;\n /** The surface pages cut lanes: declare what its attach declares (see `DeepAgentAttachTransportOptions`). */\n laneHistory?: boolean | undefined;\n}\n\n/**\n * Wake a thread's server instance ahead of its attach. `POST …/prewarm` runs\n * the host's `authorize` and history load — the fence adopt, graph compile and\n * checkpoint read that make a cold attach's hello take ≈1 s — and answers with\n * no thread content, only whether the history was already resident. Fire it\n * on hover intent, before a pooled attach or the click's own dial, so the\n * activation overlaps the handshake and the attach that follows finds the\n * instance warm.\n *\n * Fire-and-forget by contract: every failure resolves `null`, and a host\n * without the route (404) is reported like any other non-OK answer. A 503/429\n * `Retry-After` is recorded as a dial floor for the thread, so the attach that\n * follows waits it out instead of bouncing — in full, except a 503 that names\n * one of pinned's instance-lifecycle refusals (one instance mid-teardown on\n * the worker the thread already has; see {@link DeepAgentWakeRefusal}), whose\n * floor is capped at {@link WAKE_WORKER_REFUSAL_FLOOR_MS}.\n */\nexport async function wakeDeepAgentThread({\n baseUrl,\n threadId,\n headers,\n fetch: fetchOverride,\n retryGate = attachRetryGate,\n onAttachTiming,\n now = () => Date.now(),\n laneHistory = false,\n}: DeepAgentWakeOptions): Promise<DeepAgentWakeResult | null> {\n const fetchImpl =\n fetchOverride ?? (globalThis as { fetch?: DeepAgentWakeFetch }).fetch;\n if (typeof fetchImpl !== \"function\") return null;\n const threadUrl = deepAgentThreadUrl({ baseUrl, threadId });\n const emit = (event: DeepAgentAttachTimingEvent): void => {\n try {\n onAttachTiming?.(event);\n } catch {\n // Observers are best-effort.\n }\n };\n const startedAt = now();\n try {\n const resolved = withDeclaredProtocolVersion(\n await headers({ staleAuth: false }),\n { laneHistory },\n );\n const response = await fetchImpl(`${threadUrl}/prewarm`, {\n method: \"POST\",\n headers: resolved,\n keepalive: true,\n });\n const durationMs = now() - startedAt;\n let retryAfterMs: number | null = null;\n let refusal: DeepAgentWakeRefusal = null;\n if (response.status === 503 || response.status === 429) {\n let body: unknown = null;\n try {\n body = await response.json();\n } catch {\n // A refusal without a readable body is classified by nothing.\n }\n refusal = classifyWakeRefusal(body);\n const hinted = parseRetryAfterHeaderMs(\n response.headers.get(\"retry-after\"),\n now,\n );\n if (hinted !== null) {\n retryAfterMs =\n response.status === 503 && refusal === \"worker\"\n ? Math.min(hinted, WAKE_WORKER_REFUSAL_FLOOR_MS)\n : hinted;\n if (retryAfterMs > 0) {\n retryGate.noteRetryAfter(threadUrl, retryAfterMs);\n emit({\n type: \"retry-after\",\n url: threadUrl,\n delayMs: retryAfterMs,\n source: \"http-header\",\n });\n }\n }\n }\n let warm = false;\n let history: DeepAgentWakeResult[\"history\"] = null;\n if (response.ok) {\n try {\n const body = (await response.json()) as {\n warm?: unknown;\n history?: unknown;\n } | null;\n warm = body?.warm === true;\n history =\n body?.history === \"warm\" || body?.history === \"fresh_load\"\n ? body.history\n : null;\n } catch {\n // A 200 without a JSON body still means the instance is up.\n warm = true;\n }\n }\n emit({\n type: \"wake\",\n url: threadUrl,\n status: response.status,\n durationMs,\n history,\n refusal,\n });\n return {\n status: response.status,\n warm,\n history,\n retryAfterMs,\n refusal,\n durationMs,\n };\n } catch {\n return null;\n }\n}\n"],"names":[],"mappings":";;;;AA4BO,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AACF,GAGW;AACT,SAAO,GAAG,QAAQ,QAAQ,QAAQ,EAAE,CAAC,IAAI,mBAAmB,QAAQ,CAAC;AACvE;AAmDO,SAAS,+BAAiD;AAAA,EAC/D;AAAA,EACA;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA,cAAc;AAChB,GAEE;AACA,QAAM,MAAM,mBAAmB,EAAE,SAAS,UAAU;AAGpD,QAAM,SAAS,8BAA8B,EAAE,IAAA,CAAK,MAAM;AAC1D,QAAM,kBAAkB,4BAA4B;AAAA,IAClD;AAAA,IACA,KAAK;AAAA,IACL,SAAS;AAAA,IACT;AAAA,EAAA,CACD;AACD,QAAM,UAAqC;AAAA,IACzC;AAAA,IACA,GAAI,SAAS,EAAE,OAAO,KAAA;AAAA,IACtB,SAAS,OAAO,QAAgC;AAC9C,YAAM,UAAU,YAAY,GAAG;AAC/B,qDAAgB;AAChB,aAAO;AAAA,QACL,4BAA4B,MAAM,QAAQ,GAAG,GAAG,EAAE,aAAa;AAAA,QAC/D;AAAA,MAAA;AAAA,IAEJ;AAAA,IACA,GAAI,gBAAgB,EAAE,aAAA;AAAA;AAAA;AAAA,IAGtB,GAAI,gBAAgB,aAAa;AAAA,MAC/B,WACE,gBAAgB;AAAA,IAAA;AAAA,IAEpB,GAAI,gBAAgB,SAAS;AAAA,MAC3B,OACE,gBAAgB;AAAA,IAAA;AAAA,EACpB;AAEF,SAAO,mBAA2B,SAAS,EAAE,KAAK,QAAQ;AAC5D;"}
1
+ {"version":3,"file":"deep-agent-transport-recipe.js","sources":["../../../../agent-runtime/src/deep-agent-transport-recipe.ts"],"sourcesContent":["import type { ResourceElement } from \"@assistant-ui/tap\";\nimport type { Statewire, StatewireClient } from \"statewire\";\nimport {\n type DeepAgentInterestDeclaration,\n type DeepAgentMessageWindowDeclaration,\n withDeclaredInterests,\n withDeclaredMessageWindow,\n} from \"./message-window\";\nimport { withDeclaredProtocolVersion } from \"./protocol\";\nimport {\n attachRetryGate,\n type AttachRetryGate,\n createAttachInstrumentation,\n type DeepAgentAttachTimingEvent,\n type DeepAgentWakeRefusal,\n parseRetryAfterHeaderMs,\n} from \"./statewire-attach-observer\";\nimport {\n resolveStatewireTransportKind,\n statewireTransport,\n type StatewireTransportOptions,\n} from \"./statewire-transport\";\n\n/** Auth-header resolver for the transport; `staleAuth` is true right after an\n * auth rejection, so resolvers that can force-renew should honor it. */\nexport type DeepAgentHeadersResolver = (ctx: {\n staleAuth: boolean;\n}) => Record<string, string> | Promise<Record<string, string>>;\n\n/** The statewire attach URL for a thread: the host's `…/v2/threads` mount plus the id. */\nexport function deepAgentThreadUrl({\n baseUrl,\n threadId,\n}: {\n baseUrl: string;\n threadId: string;\n}): string {\n return `${baseUrl.replace(/\\/+$/, \"\")}/${encodeURIComponent(threadId)}`;\n}\n\nexport interface DeepAgentAttachTransportOptions {\n /** Base URL of the deep-agent statewire host (the `…/v2/threads` mount). */\n baseUrl: string;\n threadId: string;\n headers: DeepAgentHeadersResolver;\n /** SSE when true, WebSocket otherwise (`resolveStatewireTransportKind`). */\n sse?: boolean;\n /** A never-started chat: the transport makes no network calls until the first command send. */\n isNew?: boolean;\n /** Host session store (mobile); browser hosts mount `storage.session` on the thread instead. */\n sessionStore?: StatewireClient.SessionStorage | undefined;\n /** Observes every headers resolve (the diagnostics recorder's stale-auth seam). */\n onAuthResolve?: ((ctx: { staleAuth: boolean }) => void) | undefined;\n /** Attach timing + retry hints (see `statewire-attach-observer`). */\n onAttachTiming?: ((event: DeepAgentAttachTimingEvent) => void) | undefined;\n /** Dial floors from server retry hints; the process-wide gate by default. */\n retryGate?: AttachRetryGate;\n /**\n * The head window declared on the attach (`x-athena-deep-agent-window`,\n * see `message-window.ts`): the hello of a client the host does not\n * remember carries the newest `size` messages. Part of the recipe so a\n * pooled dial asks for the same shape as the thread's own attach — a pooled\n * hello then seeds the very state the attach will reconcile. Omitted, the\n * shared default is declared.\n */\n messageWindow?: DeepAgentMessageWindowDeclaration | undefined;\n /**\n * The view this thread's attach holds, read at every attach's header\n * resolve (`x-athena-deep-agent-interests`, see `message-window.ts`): a\n * re-attach's hello then carries the pages it had loaded on whichever host\n * instance it lands on. `null` (a first attach) declares nothing. Not part\n * of a pooled dial, which never held a view.\n */\n declaredInterests?: (() => DeepAgentInterestDeclaration | null) | undefined;\n /**\n * The surface pages cut lanes (see `DeepAgentProtocolDeclaration`), so its\n * attach declares the lane-cut contract version. Part of the recipe so a\n * pooled dial declares what the thread's own attach would; omitted, the\n * default version is declared.\n */\n laneHistory?: boolean | undefined;\n}\n\n/**\n * The ONE recipe for a deep-agent thread transport — shared by the mounted\n * thread (`useDeepAgentThread`) and the prewarm pool, so a pre-dialed\n * connection is byte-for-byte the connection the thread would have opened\n * itself: same URL, same auth + wire-contract headers, same session lane, same\n * instrumentation.\n *\n * Every attach declares the surface's wire-contract version alongside the\n * host's auth headers (first WS frame / SSE request headers) — the server\n * half of version negotiation reads it in `authorize`. The headers resolve\n * also waits out any server `Retry-After` floor for the thread: both statewire\n * attach paths resolve headers before they dial, so this is the seam where a\n * hint can hold the next dial without touching the library's backoff.\n */\nexport function createDeepAgentAttachTransport<TState = unknown>({\n baseUrl,\n threadId,\n headers,\n sse = false,\n isNew = false,\n sessionStore,\n onAuthResolve,\n onAttachTiming,\n retryGate = attachRetryGate,\n messageWindow,\n declaredInterests,\n laneHistory = false,\n}: DeepAgentAttachTransportOptions): ResourceElement<\n Statewire<TState | undefined>\n> {\n const url = deepAgentThreadUrl({ baseUrl, threadId });\n // The instrumentation wraps the transport actually built: SSE needs the\n // fetch wrapper that reads a refused attach's `Retry-After`.\n const useSse = resolveStatewireTransportKind({ sse }) === \"sse\";\n const instrumentation = createAttachInstrumentation({\n url,\n sse: useSse,\n onEvent: onAttachTiming,\n retryGate,\n });\n const options: StatewireTransportOptions = {\n url,\n ...(isNew && { isNew: true }),\n headers: async (ctx: { staleAuth: boolean }) => {\n await retryGate.waitForDial(url);\n onAuthResolve?.(ctx);\n return withDeclaredInterests(\n withDeclaredMessageWindow(\n withDeclaredProtocolVersion(await headers(ctx), { laneHistory }),\n messageWindow,\n ),\n declaredInterests?.() ?? null,\n );\n },\n ...(sessionStore && { sessionStore }),\n // Structural types: this package compiles without the DOM lib, while\n // statewire's option types name the browser `WebSocket`/`fetch`.\n ...(instrumentation.webSocket && {\n webSocket:\n instrumentation.webSocket as unknown as StatewireTransportOptions[\"webSocket\"],\n }),\n ...(instrumentation.fetch && {\n fetch:\n instrumentation.fetch as unknown as StatewireTransportOptions[\"fetch\"],\n }),\n };\n return statewireTransport<TState>(options, { sse: useSse });\n}\n\n/** What `POST …/prewarm` answered. */\nexport interface DeepAgentWakeResult {\n status: number;\n /** The host activated the thread and its history is resident. */\n warm: boolean;\n /**\n * `'warm'` when the history was already memoized, `'fresh_load'` when this\n * call loaded it; `null` when the host did not say (a refusal, or a host\n * without the route).\n */\n history: \"fresh_load\" | \"warm\" | null;\n /**\n * The dial floor recorded for the thread off a 503/429 `Retry-After` — the\n * header's value, except a 503 `\"worker\"` refusal, capped at\n * {@link WAKE_WORKER_REFUSAL_FLOOR_MS}.\n */\n retryAfterMs: number | null;\n /** Who refused a 503/429 (see {@link DeepAgentWakeRefusal}); `null` for any other answer. */\n refusal: DeepAgentWakeRefusal;\n durationMs: number;\n}\n\n/**\n * Dial floor for a 503 the pinned worker produced about one instance's\n * lifecycle. Pinned answers every retriable 503 with a blanket\n * `Retry-After: 1`, but what those name — an instance record mid-teardown\n * (\"instance closing; retry\": fence release + placement release, ≈100 ms), a\n * full activation queue — clears far sooner than that, and the thread's own\n * attach is the request that carries the next activation. Holding it a full\n * second traded a ≈100 ms gap for a ≈1 s stall on every refused wake. A 429\n * is rate limiting and keeps its hint whatever the body says.\n */\nexport const WAKE_WORKER_REFUSAL_FLOOR_MS = 250;\n\n/**\n * The pinboard's own placement-refusal vocabulary — the `error` strings of\n * `@assistant-ui/pinboard` (`src/refusals.ts` plus the two inline refusals in\n * `src/server.ts`). Mirrors `PINBOARD_PLACEMENT_REFUSAL_ERRORS` in\n * `iris/scaler/src/v2AccessLog.ts`, whose test pins it to the installed\n * library; keep the two lists identical. A body with any other `error`\n * string is `\"unknown\"`, never `\"placement\"`.\n */\nexport const PINBOARD_PLACEMENT_REFUSAL_ERRORS: ReadonlySet<string> = new Set([\n \"no live backends for namespace\",\n \"registry cold start, retry\",\n \"not the serving fleet\",\n \"no live workers for hostname\",\n \"hostname binding displaced, retry\",\n \"hostname bindings inconsistent, retry\",\n \"takeover in progress, retry\",\n \"placement held by another hostname\",\n \"worker inflight cap exceeded, retry\",\n \"worker refused activation, retry\",\n]);\n\n/**\n * Pinned's instance-lifecycle refusals (`pinned/hosting/directory.py`,\n * `pinned/hosting/_records.py`): each names one instance on the worker the\n * thread is already placed on and clears in the time a teardown or an\n * activation slot takes. Anything else the worker answers 503 with — \"Thread\n * history load failed\", \"The regional conversation store is temporarily\n * unavailable\", a lease that expired — is not about one instance and keeps\n * the full hint.\n */\nexport const PINNED_TRANSIENT_WORKER_REFUSALS: ReadonlySet<string> = new Set([\n \"instance closing; retry\",\n \"instance aborted\",\n \"activation queue full; retry\",\n \"host draining; retry\",\n \"instance capacity reached; retry\",\n \"instance past its wind-down deadline; retry\",\n]);\n\n/**\n * Classify a 503/429 body (see {@link DeepAgentWakeRefusal}): a known pinboard\n * `error` is `\"placement\"`, a known pinned `detail` is `\"worker\"`, everything\n * else — including unfamiliar strings in either field — is `\"unknown\"`.\n */\nexport function classifyWakeRefusal(\n body: unknown,\n): Exclude<DeepAgentWakeRefusal, null> {\n if (typeof body === \"object\" && body !== null) {\n const record = body as Record<string, unknown>;\n if (\n typeof record.error === \"string\" &&\n PINBOARD_PLACEMENT_REFUSAL_ERRORS.has(record.error)\n ) {\n return \"placement\";\n }\n if (\n typeof record.detail === \"string\" &&\n PINNED_TRANSIENT_WORKER_REFUSALS.has(record.detail)\n ) {\n return \"worker\";\n }\n }\n return \"unknown\";\n}\n\n/** Structural `fetch` for the wake call — this package compiles without the DOM lib. */\nexport type DeepAgentWakeFetch = (\n input: string,\n init?: {\n method?: string;\n headers?: Record<string, string>;\n keepalive?: boolean;\n },\n) => Promise<{\n ok: boolean;\n status: number;\n headers: { get(name: string): string | null };\n json(): Promise<unknown>;\n}>;\n\nexport interface DeepAgentWakeOptions {\n /** Base URL of the deep-agent statewire host (the `…/v2/threads` mount). */\n baseUrl: string;\n threadId: string;\n headers: DeepAgentHeadersResolver;\n fetch?: DeepAgentWakeFetch | undefined;\n /** Dial floors from server retry hints; the process-wide gate by default. */\n retryGate?: AttachRetryGate;\n onAttachTiming?: ((event: DeepAgentAttachTimingEvent) => void) | undefined;\n now?: () => number;\n /** The surface pages cut lanes: declare what its attach declares (see `DeepAgentAttachTransportOptions`). */\n laneHistory?: boolean | undefined;\n}\n\n/**\n * Wake a thread's server instance ahead of its attach. `POST …/prewarm` runs\n * the host's `authorize` and history load — the fence adopt, graph compile and\n * checkpoint read that make a cold attach's hello take ≈1 s — and answers with\n * no thread content, only whether the history was already resident. Fire it\n * on hover intent, before a pooled attach or the click's own dial, so the\n * activation overlaps the handshake and the attach that follows finds the\n * instance warm.\n *\n * Fire-and-forget by contract: every failure resolves `null`, and a host\n * without the route (404) is reported like any other non-OK answer. A 503/429\n * `Retry-After` is recorded as a dial floor for the thread, so the attach that\n * follows waits it out instead of bouncing — in full, except a 503 that names\n * one of pinned's instance-lifecycle refusals (one instance mid-teardown on\n * the worker the thread already has; see {@link DeepAgentWakeRefusal}), whose\n * floor is capped at {@link WAKE_WORKER_REFUSAL_FLOOR_MS}.\n */\nexport async function wakeDeepAgentThread({\n baseUrl,\n threadId,\n headers,\n fetch: fetchOverride,\n retryGate = attachRetryGate,\n onAttachTiming,\n now = () => Date.now(),\n laneHistory = false,\n}: DeepAgentWakeOptions): Promise<DeepAgentWakeResult | null> {\n const fetchImpl =\n fetchOverride ?? (globalThis as { fetch?: DeepAgentWakeFetch }).fetch;\n if (typeof fetchImpl !== \"function\") return null;\n const threadUrl = deepAgentThreadUrl({ baseUrl, threadId });\n const emit = (event: DeepAgentAttachTimingEvent): void => {\n try {\n onAttachTiming?.(event);\n } catch {\n // Observers are best-effort.\n }\n };\n const startedAt = now();\n try {\n const resolved = withDeclaredProtocolVersion(\n await headers({ staleAuth: false }),\n { laneHistory },\n );\n const response = await fetchImpl(`${threadUrl}/prewarm`, {\n method: \"POST\",\n headers: resolved,\n keepalive: true,\n });\n const durationMs = now() - startedAt;\n let retryAfterMs: number | null = null;\n let refusal: DeepAgentWakeRefusal = null;\n if (response.status === 503 || response.status === 429) {\n let body: unknown = null;\n try {\n body = await response.json();\n } catch {\n // A refusal without a readable body is classified by nothing.\n }\n refusal = classifyWakeRefusal(body);\n const hinted = parseRetryAfterHeaderMs(\n response.headers.get(\"retry-after\"),\n now,\n );\n if (hinted !== null) {\n retryAfterMs =\n response.status === 503 && refusal === \"worker\"\n ? Math.min(hinted, WAKE_WORKER_REFUSAL_FLOOR_MS)\n : hinted;\n if (retryAfterMs > 0) {\n retryGate.noteRetryAfter(threadUrl, retryAfterMs);\n emit({\n type: \"retry-after\",\n url: threadUrl,\n delayMs: retryAfterMs,\n source: \"http-header\",\n });\n }\n }\n }\n let warm = false;\n let history: DeepAgentWakeResult[\"history\"] = null;\n if (response.ok) {\n try {\n const body = (await response.json()) as {\n warm?: unknown;\n history?: unknown;\n } | null;\n warm = body?.warm === true;\n history =\n body?.history === \"warm\" || body?.history === \"fresh_load\"\n ? body.history\n : null;\n } catch {\n // A 200 without a JSON body still means the instance is up.\n warm = true;\n }\n }\n emit({\n type: \"wake\",\n url: threadUrl,\n status: response.status,\n durationMs,\n history,\n refusal,\n });\n return {\n status: response.status,\n warm,\n history,\n retryAfterMs,\n refusal,\n durationMs,\n };\n } catch {\n return null;\n }\n}\n"],"names":[],"mappings":";;;;AA8BO,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AACF,GAGW;AACT,SAAO,GAAG,QAAQ,QAAQ,QAAQ,EAAE,CAAC,IAAI,mBAAmB,QAAQ,CAAC;AACvE;AA2DO,SAAS,+BAAiD;AAAA,EAC/D;AAAA,EACA;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA;AAAA,EACA,cAAc;AAChB,GAEE;AACA,QAAM,MAAM,mBAAmB,EAAE,SAAS,UAAU;AAGpD,QAAM,SAAS,8BAA8B,EAAE,IAAA,CAAK,MAAM;AAC1D,QAAM,kBAAkB,4BAA4B;AAAA,IAClD;AAAA,IACA,KAAK;AAAA,IACL,SAAS;AAAA,IACT;AAAA,EAAA,CACD;AACD,QAAM,UAAqC;AAAA,IACzC;AAAA,IACA,GAAI,SAAS,EAAE,OAAO,KAAA;AAAA,IACtB,SAAS,OAAO,QAAgC;AAC9C,YAAM,UAAU,YAAY,GAAG;AAC/B,qDAAgB;AAChB,aAAO;AAAA,QACL;AAAA,UACE,4BAA4B,MAAM,QAAQ,GAAG,GAAG,EAAE,aAAa;AAAA,UAC/D;AAAA,QAAA;AAAA,SAEF,6DAAyB;AAAA,MAAA;AAAA,IAE7B;AAAA,IACA,GAAI,gBAAgB,EAAE,aAAA;AAAA;AAAA;AAAA,IAGtB,GAAI,gBAAgB,aAAa;AAAA,MAC/B,WACE,gBAAgB;AAAA,IAAA;AAAA,IAEpB,GAAI,gBAAgB,SAAS;AAAA,MAC3B,OACE,gBAAgB;AAAA,IAAA;AAAA,EACpB;AAEF,SAAO,mBAA2B,SAAS,EAAE,KAAK,QAAQ;AAC5D;"}
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Live dictation through Athena's relay to Deepgram, shared by every surface
3
+ * that dictates: Olympus's speech-to-text overlay (Ctrl+Ctrl) and voice memo
4
+ * live transcript, and the phone app's composer mic. Audio is 16-bit PCM
5
+ * pushed as it is captured; results come back as interim and final text.
6
+ */
7
+ export declare const DEEPGRAM_DICTATION_SAMPLE_RATE = 16000;
8
+ export type DeepgramSocketStatus = 'closed' | 'opening' | 'open';
9
+ /** One word of a final result; times are seconds of this socket's audio. */
10
+ export interface DictationWord {
11
+ word: string;
12
+ punctuatedWord: string;
13
+ start: number;
14
+ end: number;
15
+ }
16
+ export type DeepgramDictationEvent = {
17
+ type: 'status';
18
+ status: DeepgramSocketStatus;
19
+ } | {
20
+ type: 'transcript';
21
+ text: string;
22
+ } | {
23
+ type: 'connection-lost';
24
+ }
25
+ /**
26
+ * A final result's words. Their times and `audioSecondsSent` share this socket's clock, so
27
+ * `audioSecondsSent - word.end` is how far behind the live audio a word is. `speechFinal`:
28
+ * Deepgram heard the speaker pause right after them (an endpoint); false when it cut the
29
+ * result mid-speech.
30
+ */
31
+ | {
32
+ type: 'final-words';
33
+ words: DictationWord[];
34
+ audioSecondsSent: number;
35
+ speechFinal: boolean;
36
+ }
37
+ /** Deepgram's `UtteranceEnd` (sent only with `utterance_end_ms`): nobody spoke after `lastWordEnd`. */
38
+ | {
39
+ type: 'utterance-end';
40
+ lastWordEnd: number;
41
+ audioSecondsSent: number;
42
+ }
43
+ /**
44
+ * An interim result's last word: speech runs at least to `lastWordEnd` although none of it is
45
+ * final yet (Deepgram can take seconds to finalize a phrase). Same clock as `final-words`.
46
+ */
47
+ | {
48
+ type: 'interim-words';
49
+ lastWordEnd: number;
50
+ audioSecondsSent: number;
51
+ }
52
+ /**
53
+ * Deepgram has listened to the stream up to `until` (a result's `start + duration`, with words
54
+ * or without): a pause before it is one Deepgram heard. Same clock as `final-words`.
55
+ */
56
+ | {
57
+ type: 'listened';
58
+ until: number;
59
+ audioSecondsSent: number;
60
+ };
61
+ type DeepgramDictationListener = (event: DeepgramDictationEvent) => void;
62
+ export type DictationSocketLike = Pick<WebSocket, 'send' | 'close' | 'readyState' | 'binaryType'> & {
63
+ onopen: ((event: Event) => void) | null;
64
+ onmessage: ((event: MessageEvent) => void) | null;
65
+ onerror: ((event: Event) => void) | null;
66
+ onclose: ((event: CloseEvent) => void) | null;
67
+ };
68
+ export interface CreateDictationSocketOptions {
69
+ url: string;
70
+ protocols: string[];
71
+ }
72
+ export interface DeepgramDictationSessionOptions {
73
+ fetchToken: () => Promise<string>;
74
+ /** Agora origin (http(s)) hosting the dictation relay, e.g. `CONFIG.serverUrl`. */
75
+ serverUrl: string;
76
+ /** Extra Deepgram listen parameters (e.g. `keyterm`, `utterance_end_ms`), one value each. */
77
+ listenParams?: Record<string, string>;
78
+ createSocket?: (options: CreateDictationSocketOptions) => DictationSocketLike;
79
+ keepAliveIntervalMs?: number;
80
+ idleCloseMs?: number;
81
+ finalizeTimeoutMs?: number;
82
+ }
83
+ export declare function buildDictationStreamUrl({ serverUrl, listenParams, }: {
84
+ serverUrl: string;
85
+ listenParams?: Record<string, string>;
86
+ }): string;
87
+ /**
88
+ * Owns one browser -> Deepgram streaming socket for dictation.
89
+ *
90
+ * The socket is opened lazily with a short-lived JWT from agora and kept warm
91
+ * between recordings with `KeepAlive` frames, so the second Ctrl-to-talk only
92
+ * pays for the microphone. It closes itself after `idleCloseMs` without demand.
93
+ */
94
+ export declare class DeepgramDictationSession {
95
+ private readonly fetchToken;
96
+ private readonly streamUrl;
97
+ private readonly createSocket;
98
+ private readonly keepAliveIntervalMs;
99
+ private readonly idleCloseMs;
100
+ private readonly finalizeTimeoutMs;
101
+ private socket;
102
+ private socketGeneration;
103
+ private connectPromise;
104
+ private rejectPendingOpen;
105
+ private keepAliveTimer;
106
+ private idleTimer;
107
+ private pendingAudio;
108
+ private pendingAudioBytes;
109
+ private hasUnfinalizedAudio;
110
+ private pendingFinalize;
111
+ private audioSecondsSent;
112
+ /** Results for audio before this stream offset belong to an already-reset recording. */
113
+ private staleResultsBefore;
114
+ private retained;
115
+ private disposed;
116
+ private finalSegments;
117
+ private interimSegment;
118
+ private listeners;
119
+ status: DeepgramSocketStatus;
120
+ constructor({ fetchToken, serverUrl, listenParams, createSocket, keepAliveIntervalMs, idleCloseMs, finalizeTimeoutMs, }: DeepgramDictationSessionOptions);
121
+ get transcript(): string;
122
+ /** Finalized results only, excluding the in-flight interim segment. */
123
+ get finalizedTranscript(): string;
124
+ subscribe(listener: DeepgramDictationListener): () => void;
125
+ /** Marks active demand: cancels the idle close and keeps the socket warm. */
126
+ retain(): void;
127
+ /** Ends active demand: flushes pending results and schedules the idle close. */
128
+ release(): void;
129
+ /** Resolves once a socket is open. Reuses an open or opening socket. */
130
+ connect(): Promise<void>;
131
+ sendAudio(chunk: ArrayBuffer): void;
132
+ /**
133
+ * Asks Deepgram to flush any buffered audio into a final result and resolves
134
+ * with the transcript once that result lands (or after `finalizeTimeoutMs`).
135
+ * Resolves immediately when there is nothing left to flush.
136
+ */
137
+ finalize(): Promise<string>;
138
+ /**
139
+ * Clears the transcript for a new recording. If the previous recording is
140
+ * still waiting on its `from_finalize` result, results for audio sent before
141
+ * that `Finalize` belong to the old recording and are dropped when they land.
142
+ */
143
+ resetTranscript(): void;
144
+ close(): void;
145
+ dispose(): void;
146
+ private openSocket;
147
+ private handleMessage;
148
+ private settleFinalize;
149
+ private flushPendingAudio;
150
+ private sendJson;
151
+ private startKeepAlive;
152
+ private clearKeepAlive;
153
+ private scheduleIdleClose;
154
+ private clearIdleTimer;
155
+ private setStatus;
156
+ private emit;
157
+ }
158
+ export {};
@@ -78,6 +78,11 @@ async function loadOlderDeepAgentHistoryPage({
78
78
  await extras.invoke(runconfigContract.DEEP_AGENT_INTEREST_PROTOCOL, "set", [requests]);
79
79
  return true;
80
80
  }
81
+ function isHistoryPageLostToReconnect(error) {
82
+ if (typeof error !== "object" || error === null || !("failure" in error)) return false;
83
+ const { failure } = error;
84
+ return typeof failure === "object" && failure !== null && "cause" in failure && failure.cause === "session-lost";
85
+ }
81
86
  const MAX_EDIT_ANCHOR_HISTORY_LOADS = 5;
82
87
  async function resolveDeepAgentEditCommand({
83
88
  readExtras,
@@ -106,6 +111,7 @@ async function resolveDeepAgentEditCommand({
106
111
  exports.MAX_EDIT_ANCHOR_HISTORY_LOADS = MAX_EDIT_ANCHOR_HISTORY_LOADS;
107
112
  exports.buildDeepAgentEditCommand = buildDeepAgentEditCommand;
108
113
  exports.deepAgentHistoryHasOlder = deepAgentHistoryHasOlder;
114
+ exports.isHistoryPageLostToReconnect = isHistoryPageLostToReconnect;
109
115
  exports.isSourceBelowLoadedWindow = isSourceBelowLoadedWindow;
110
116
  exports.loadOlderDeepAgentHistoryPage = loadOlderDeepAgentHistoryPage;
111
117
  exports.readDeepAgentStatewireExtras = readDeepAgentStatewireExtras;
@@ -1 +1 @@
1
- {"version":3,"file":"edit-command.cjs","sources":["../../../../agent-runtime/src/edit-command.ts"],"sourcesContent":["import type { StatewireThread } from '@assistant-ui/react-statewire';\nimport { DEEP_AGENT_INTEREST_PROTOCOL } from './generated/runconfig-contract';\nimport {\n type DeepAgentMessageWindow,\n pageInterestRequests,\n readDeepAgentMessageWindow,\n} from './message-window';\nimport { hasStatewireThreadExtras } from './thread-extras';\n\n/**\n * Wire-accurate `run/edit` construction for deep-agent retry/edit, shared by\n * every surface that resubmits a user message.\n *\n * assistant-ui builds the command's `runAnchorMessageId` from the CONVERTED\n * thread messages (`resolveEditCommand`: `messages[index - 1].id`), but the\n * deep-agent host validates that anchor against the edited message's parent in\n * its RAW message list (`harness_sdk.linear_thread`: the entry before it in\n * `state[\"messages\"]`). Those two lists do not line up:\n *\n * - the converter chunks an assistant turn and its tool messages into ONE\n * thread message carrying only the FIRST wire id, so the anchor names the\n * head of the previous turn instead of its last tool message;\n * - `sanitizeLangChainMessages` drops hidden-from-frontend and unconvertible\n * entries, so a dropped tail message is invisible to the anchor too.\n *\n * Either way the host rejects the command with `wrong-anchor`\n * (`runAnchorMessageId … is not the source's parent`) AFTER the composer's\n * synchronous `send()` returned, so the retry/edit silently does nothing.\n *\n * Building the command here off the replicated raw state makes the anchor the\n * same value the host computes.\n *\n * The raw list is the loaded interest window, so the first loaded message's\n * parent is not in it while older messages exist — an edit there must not\n * anchor on `null` (the root, rejected `wrong-anchor`); a message below the\n * window has no parent on this client at all. {@link resolveDeepAgentEditCommand}\n * states older page interests until the parent is loaded.\n */\n\n/**\n * Host metadata frozen at submission, settling once the async capture does.\n * The message-metadata preparation surface — `prepareMessageMetadata`,\n * `discardPreparedMessageMetadata`, `sendPreparedEdit` and `sendCommand`'s\n * `preparedMetadata` option — is what the monorepo patches into\n * `@assistant-ui/react-statewire@0.31.0` (`patches/`). It is declared\n * structurally here rather than as `StatewireThread.Extras[...]` so that the\n * published sources also compile against the unpatched upstream typings, where\n * those members are absent and the edit path's optional calls never run.\n */\nexport type DeepAgentPreparedMessageMetadata = Promise<Record<string, unknown> | undefined>;\n\n/** The pieces of the statewire thread extras the edit path reads. */\nexport interface DeepAgentStatewireExtras {\n /** The library's dispatch; it resolves with the host's reply to the command. */\n sendCommand: (\n command: StatewireThread.Command,\n options?: { preparedMetadata?: DeepAgentPreparedMessageMetadata | undefined },\n ) => Promise<unknown> | void;\n /** Optional on older hosts; capture before loading an edit's history anchor. */\n prepareMessageMetadata?: (() => DeepAgentPreparedMessageMetadata) | undefined;\n discardPreparedMessageMetadata?:\n | ((prepared: DeepAgentPreparedMessageMetadata) => void)\n | undefined;\n sendPreparedEdit?:\n | ((sourceId: string, prepared: DeepAgentPreparedMessageMetadata) => void)\n | undefined;\n isPreparingSubmission?: boolean;\n /** The composed thread state — its `messages` are the raw wire messages of the loaded window. */\n state: { messages?: readonly { id?: unknown }[] } | null;\n /** The mounted documents (the interest window), absent on a wire without documents. */\n documents?: StatewireThread.Extras['documents'];\n invoke?: StatewireThread.Extras['invoke'];\n /** The live run, when one is in flight; `epoch` advances on each dispatch. */\n runs: { runId?: string | null; epoch?: number };\n /** The host's replicated run status; absent on a surface that predates it. */\n status?: StatewireThread.ThreadStatus;\n}\n\n/**\n * The statewire extras of the nearest aui thread, or `null` when the thread is\n * not a statewire thread (e.g. a read-only subagent transcript runtime).\n * Gated on {@link hasStatewireThreadExtras} for the same reason the approval\n * card is: the library's own hooks throw on a non-statewire thread.\n */\nexport function readDeepAgentStatewireExtras(extras: unknown): DeepAgentStatewireExtras | null {\n if (!hasStatewireThreadExtras(extras)) return null;\n return extras as DeepAgentStatewireExtras;\n}\n\n/**\n * The host's parent of `sourceId`: the raw wire message directly before it\n * (`null` when it is the first of the whole transcript). Returns `undefined`\n * when `sourceId` is not in the raw list at all — an optimistic bubble the\n * host has not settled yet, a message below the loaded window, or a surface\n * whose state this module cannot read — or when it is the first loaded\n * message while older ones exist (`hasOlder`), so the caller can load more or\n * fall back to the library's own path instead of asserting a wrong anchor.\n */\nexport function resolveWireAnchorMessageId({\n wireMessages,\n sourceId,\n hasOlder = false,\n}: {\n wireMessages: readonly { id?: unknown }[] | undefined;\n sourceId: string;\n hasOlder?: boolean;\n}): string | null | undefined {\n if (!wireMessages) return undefined;\n const index = wireMessages.findIndex((message) => message?.id === sourceId);\n if (index < 0) return undefined;\n if (index === 0) return hasOlder ? undefined : null;\n const parentId = wireMessages[index - 1]?.id;\n return typeof parentId === 'string' ? parentId : undefined;\n}\n\n/**\n * Whether `sourceId`'s parent lies below the loaded window: the message is\n * absent from the raw list, or its first entry, while older messages exist.\n * The caller loads older history before an edit can be anchored.\n */\nexport function isSourceBelowLoadedWindow({\n wireMessages,\n sourceId,\n window,\n}: {\n wireMessages: readonly { id?: unknown }[] | undefined;\n sourceId: string;\n window: DeepAgentMessageWindow | null;\n}): boolean {\n if (!wireMessages || window === null || !window.hasOlder) return false;\n const index = wireMessages.findIndex((message) => message?.id === sourceId);\n return index <= 0;\n}\n\nconst readWindow = (extras: DeepAgentStatewireExtras) =>\n readDeepAgentMessageWindow(extras.documents?.list());\n\n/**\n * A fresh command / message id (uniqueness, not secrecy). `crypto.randomUUID`\n * where the host runtime has it — every browser, Bun, Node and Hermes with\n * webcrypto — and a v4-shaped fallback elsewhere, so the shared path never\n * throws on a runtime without full webcrypto.\n */\nfunction mintCommandId(): string {\n const webcrypto = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto;\n if (typeof webcrypto?.randomUUID === 'function') return webcrypto.randomUUID();\n const hex = (): string => Math.floor(Math.random() * 0x10000).toString(16).padStart(4, '0');\n return `${hex()}${hex()}-${hex()}-4${hex().slice(1)}-${hex()}-${hex()}${hex()}${hex()}`;\n}\n\n/**\n * The `run/edit` command for resubmitting `sourceId` with `text`, anchored on\n * the host's own parent. `null` when the anchor cannot be resolved from the\n * replicated state.\n */\nexport function buildDeepAgentEditCommand({\n extras,\n sourceId,\n text,\n}: {\n extras: DeepAgentStatewireExtras;\n sourceId: string;\n text: string;\n}): StatewireThread.RunEditCommand | null {\n const runAnchorMessageId = resolveWireAnchorMessageId({\n wireMessages: extras.state?.messages,\n sourceId,\n hasOlder: readWindow(extras)?.hasOlder ?? false,\n });\n if (runAnchorMessageId === undefined) return null;\n return {\n type: 'run/edit',\n runId: extras.runs.runId ?? mintCommandId(),\n message: { id: mintCommandId(), role: 'user', parts: [{ type: 'text', text }] },\n sourceId,\n runAnchorMessageId,\n };\n}\n\n/**\n * Whether a windowed statewire thread has older history than it has loaded:\n * `null` while that is not known yet (the head interest has not resolved; a\n * remembered transcript can show from cache before it does), and `false` for\n * a thread that is not a statewire thread, so a reader looking for an older\n * message waits for the window, or stops.\n */\nexport function deepAgentHistoryHasOlder(extras: unknown): boolean | null {\n const typed = readDeepAgentStatewireExtras(extras);\n if (typed === null) return false;\n return readWindow(typed)?.hasOlder ?? null;\n}\n\n/**\n * State one more page of older history for a windowed thread: the next page\n * past the loaded window's oldest message. Resolves `true` once the host has\n * mounted it (it answers the statement after mounting), `false` when there is\n * nothing older, the thread is not a windowed statewire thread, or no page can\n * be stated. For a reader that needs a message below the loaded window — a\n * search result revealing an older turn of a long conversation — and pages\n * until it renders.\n */\nexport async function loadOlderDeepAgentHistoryPage({\n readExtras,\n pageSize,\n}: {\n readExtras: () => DeepAgentStatewireExtras | null;\n pageSize?: number;\n}): Promise<boolean> {\n const extras = readExtras();\n if (!extras?.invoke) return false;\n const window = readWindow(extras);\n if (window === null || !window.hasOlder) return false;\n const requests = pageInterestRequests(window, pageSize);\n if (requests === null) return false;\n await extras.invoke(DEEP_AGENT_INTEREST_PROTOCOL, 'set', [requests]);\n return true;\n}\n\n/**\n * Pages of older history stated while looking for an edited message's host\n * parent. Each page is up to a window's worth of messages, so an edit reaches\n * this many windows below what was loaded before it gives up.\n */\nexport const MAX_EDIT_ANCHOR_HISTORY_LOADS = 5;\n\n/**\n * The anchored `run/edit` for `sourceId`, stating older page interests one at\n * a time when the message's parent lies below the loaded window. Every page\n * is read back from the live documents (`readExtras` — the host mounts them\n * before it answers the statement), so the anchor is always the host's own\n * parent id.\n *\n * Resolves `null` — the caller's cue for the library's composer path, whose\n * failure it reports — when the thread is not a statewire thread, the host has\n * not settled the message, the history is exhausted without it, or the page\n * budget ({@link MAX_EDIT_ANCHOR_HISTORY_LOADS}) is spent. A synchronous\n * resolution never awaits: the first read either anchors at once or decides\n * that pages are needed.\n */\nexport async function resolveDeepAgentEditCommand({\n readExtras,\n sourceId,\n text,\n pageSize,\n maxHistoryLoads = MAX_EDIT_ANCHOR_HISTORY_LOADS,\n}: {\n /** The live thread extras — re-read per page so each anchor attempt sees the widened window. */\n readExtras: () => DeepAgentStatewireExtras | null;\n sourceId: string;\n text: string;\n pageSize?: number;\n maxHistoryLoads?: number;\n}): Promise<StatewireThread.RunEditCommand | null> {\n for (let page = 0; page <= maxHistoryLoads; page += 1) {\n const extras = readExtras();\n if (!extras) return null;\n const command = buildDeepAgentEditCommand({ extras, sourceId, text });\n if (command) return command;\n if (page === maxHistoryLoads || !extras.invoke) return null;\n const window = readWindow(extras);\n if (!isSourceBelowLoadedWindow({ wireMessages: extras.state?.messages, sourceId, window })) {\n return null;\n }\n const requests = window === null ? null : pageInterestRequests(window, pageSize);\n if (requests === null) return null;\n await extras.invoke(DEEP_AGENT_INTEREST_PROTOCOL, 'set', [requests]);\n }\n return null;\n}\n"],"names":["hasStatewireThreadExtras","readDeepAgentMessageWindow","pageInterestRequests","DEEP_AGENT_INTEREST_PROTOCOL"],"mappings":"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"}
1
+ {"version":3,"file":"edit-command.cjs","sources":["../../../../agent-runtime/src/edit-command.ts"],"sourcesContent":["import type { StatewireThread } from '@assistant-ui/react-statewire';\nimport { DEEP_AGENT_INTEREST_PROTOCOL } from './generated/runconfig-contract';\nimport {\n type DeepAgentMessageWindow,\n pageInterestRequests,\n readDeepAgentMessageWindow,\n} from './message-window';\nimport { hasStatewireThreadExtras } from './thread-extras';\n\n/**\n * Wire-accurate `run/edit` construction for deep-agent retry/edit, shared by\n * every surface that resubmits a user message.\n *\n * assistant-ui builds the command's `runAnchorMessageId` from the CONVERTED\n * thread messages (`resolveEditCommand`: `messages[index - 1].id`), but the\n * deep-agent host validates that anchor against the edited message's parent in\n * its RAW message list (`harness_sdk.linear_thread`: the entry before it in\n * `state[\"messages\"]`). Those two lists do not line up:\n *\n * - the converter chunks an assistant turn and its tool messages into ONE\n * thread message carrying only the FIRST wire id, so the anchor names the\n * head of the previous turn instead of its last tool message;\n * - `sanitizeLangChainMessages` drops hidden-from-frontend and unconvertible\n * entries, so a dropped tail message is invisible to the anchor too.\n *\n * Either way the host rejects the command with `wrong-anchor`\n * (`runAnchorMessageId … is not the source's parent`) AFTER the composer's\n * synchronous `send()` returned, so the retry/edit silently does nothing.\n *\n * Building the command here off the replicated raw state makes the anchor the\n * same value the host computes.\n *\n * The raw list is the loaded interest window, so the first loaded message's\n * parent is not in it while older messages exist — an edit there must not\n * anchor on `null` (the root, rejected `wrong-anchor`); a message below the\n * window has no parent on this client at all. {@link resolveDeepAgentEditCommand}\n * states older page interests until the parent is loaded.\n */\n\n/**\n * Host metadata frozen at submission, settling once the async capture does.\n * The message-metadata preparation surface — `prepareMessageMetadata`,\n * `discardPreparedMessageMetadata`, `sendPreparedEdit` and `sendCommand`'s\n * `preparedMetadata` option — is what the monorepo patches into\n * `@assistant-ui/react-statewire@0.31.0` (`patches/`). It is declared\n * structurally here rather than as `StatewireThread.Extras[...]` so that the\n * published sources also compile against the unpatched upstream typings, where\n * those members are absent and the edit path's optional calls never run.\n */\nexport type DeepAgentPreparedMessageMetadata = Promise<Record<string, unknown> | undefined>;\n\n/** The pieces of the statewire thread extras the edit path reads. */\nexport interface DeepAgentStatewireExtras {\n /** The library's dispatch; it resolves with the host's reply to the command. */\n sendCommand: (\n command: StatewireThread.Command,\n options?: { preparedMetadata?: DeepAgentPreparedMessageMetadata | undefined },\n ) => Promise<unknown> | void;\n /** Optional on older hosts; capture before loading an edit's history anchor. */\n prepareMessageMetadata?: (() => DeepAgentPreparedMessageMetadata) | undefined;\n discardPreparedMessageMetadata?:\n | ((prepared: DeepAgentPreparedMessageMetadata) => void)\n | undefined;\n sendPreparedEdit?:\n | ((sourceId: string, prepared: DeepAgentPreparedMessageMetadata) => void)\n | undefined;\n isPreparingSubmission?: boolean;\n /** The composed thread state — its `messages` are the raw wire messages of the loaded window. */\n state: { messages?: readonly { id?: unknown }[] } | null;\n /** The mounted documents (the interest window), absent on a wire without documents. */\n documents?: StatewireThread.Extras['documents'];\n invoke?: StatewireThread.Extras['invoke'];\n /** The live run, when one is in flight; `epoch` advances on each dispatch. */\n runs: { runId?: string | null; epoch?: number };\n /** The host's replicated run status; absent on a surface that predates it. */\n status?: StatewireThread.ThreadStatus;\n}\n\n/**\n * The statewire extras of the nearest aui thread, or `null` when the thread is\n * not a statewire thread (e.g. a read-only subagent transcript runtime).\n * Gated on {@link hasStatewireThreadExtras} for the same reason the approval\n * card is: the library's own hooks throw on a non-statewire thread.\n */\nexport function readDeepAgentStatewireExtras(extras: unknown): DeepAgentStatewireExtras | null {\n if (!hasStatewireThreadExtras(extras)) return null;\n return extras as DeepAgentStatewireExtras;\n}\n\n/**\n * The host's parent of `sourceId`: the raw wire message directly before it\n * (`null` when it is the first of the whole transcript). Returns `undefined`\n * when `sourceId` is not in the raw list at all — an optimistic bubble the\n * host has not settled yet, a message below the loaded window, or a surface\n * whose state this module cannot read — or when it is the first loaded\n * message while older ones exist (`hasOlder`), so the caller can load more or\n * fall back to the library's own path instead of asserting a wrong anchor.\n */\nexport function resolveWireAnchorMessageId({\n wireMessages,\n sourceId,\n hasOlder = false,\n}: {\n wireMessages: readonly { id?: unknown }[] | undefined;\n sourceId: string;\n hasOlder?: boolean;\n}): string | null | undefined {\n if (!wireMessages) return undefined;\n const index = wireMessages.findIndex((message) => message?.id === sourceId);\n if (index < 0) return undefined;\n if (index === 0) return hasOlder ? undefined : null;\n const parentId = wireMessages[index - 1]?.id;\n return typeof parentId === 'string' ? parentId : undefined;\n}\n\n/**\n * Whether `sourceId`'s parent lies below the loaded window: the message is\n * absent from the raw list, or its first entry, while older messages exist.\n * The caller loads older history before an edit can be anchored.\n */\nexport function isSourceBelowLoadedWindow({\n wireMessages,\n sourceId,\n window,\n}: {\n wireMessages: readonly { id?: unknown }[] | undefined;\n sourceId: string;\n window: DeepAgentMessageWindow | null;\n}): boolean {\n if (!wireMessages || window === null || !window.hasOlder) return false;\n const index = wireMessages.findIndex((message) => message?.id === sourceId);\n return index <= 0;\n}\n\nconst readWindow = (extras: DeepAgentStatewireExtras) =>\n readDeepAgentMessageWindow(extras.documents?.list());\n\n/**\n * A fresh command / message id (uniqueness, not secrecy). `crypto.randomUUID`\n * where the host runtime has it — every browser, Bun, Node and Hermes with\n * webcrypto — and a v4-shaped fallback elsewhere, so the shared path never\n * throws on a runtime without full webcrypto.\n */\nfunction mintCommandId(): string {\n const webcrypto = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto;\n if (typeof webcrypto?.randomUUID === 'function') return webcrypto.randomUUID();\n const hex = (): string => Math.floor(Math.random() * 0x10000).toString(16).padStart(4, '0');\n return `${hex()}${hex()}-${hex()}-4${hex().slice(1)}-${hex()}-${hex()}${hex()}${hex()}`;\n}\n\n/**\n * The `run/edit` command for resubmitting `sourceId` with `text`, anchored on\n * the host's own parent. `null` when the anchor cannot be resolved from the\n * replicated state.\n */\nexport function buildDeepAgentEditCommand({\n extras,\n sourceId,\n text,\n}: {\n extras: DeepAgentStatewireExtras;\n sourceId: string;\n text: string;\n}): StatewireThread.RunEditCommand | null {\n const runAnchorMessageId = resolveWireAnchorMessageId({\n wireMessages: extras.state?.messages,\n sourceId,\n hasOlder: readWindow(extras)?.hasOlder ?? false,\n });\n if (runAnchorMessageId === undefined) return null;\n return {\n type: 'run/edit',\n runId: extras.runs.runId ?? mintCommandId(),\n message: { id: mintCommandId(), role: 'user', parts: [{ type: 'text', text }] },\n sourceId,\n runAnchorMessageId,\n };\n}\n\n/**\n * Whether a windowed statewire thread has older history than it has loaded:\n * `null` while that is not known yet (the head interest has not resolved; a\n * remembered transcript can show from cache before it does), and `false` for\n * a thread that is not a statewire thread, so a reader looking for an older\n * message waits for the window, or stops.\n */\nexport function deepAgentHistoryHasOlder(extras: unknown): boolean | null {\n const typed = readDeepAgentStatewireExtras(extras);\n if (typed === null) return false;\n return readWindow(typed)?.hasOlder ?? null;\n}\n\n/**\n * State one more page of older history for a windowed thread: the next page\n * past the loaded window's oldest message. Resolves `true` once the host has\n * mounted it (it answers the statement after mounting), `false` when there is\n * nothing older, the thread is not a windowed statewire thread, or no page can\n * be stated. For a reader that needs a message below the loaded window — a\n * search result revealing an older turn of a long conversation — and pages\n * until it renders.\n */\nexport async function loadOlderDeepAgentHistoryPage({\n readExtras,\n pageSize,\n}: {\n readExtras: () => DeepAgentStatewireExtras | null;\n pageSize?: number;\n}): Promise<boolean> {\n const extras = readExtras();\n if (!extras?.invoke) return false;\n const window = readWindow(extras);\n if (window === null || !window.hasOlder) return false;\n const requests = pageInterestRequests(window, pageSize);\n if (requests === null) return false;\n await extras.invoke(DEEP_AGENT_INTEREST_PROTOCOL, 'set', [requests]);\n return true;\n}\n\n/**\n * Whether a {@link loadOlderDeepAgentHistoryPage} failure is the connection\n * dropping under the page (statewire settles an ephemeral statement in flight\n * at the drop `session-lost`), not the host refusing it. The re-attach carries\n * the view loaded so far, so a reader looking for a message pages again once\n * reconnected instead of deciding the history is exhausted.\n */\nexport function isHistoryPageLostToReconnect(error: unknown): boolean {\n if (typeof error !== 'object' || error === null || !('failure' in error)) return false;\n const { failure } = error;\n return (\n typeof failure === 'object' &&\n failure !== null &&\n 'cause' in failure &&\n failure.cause === 'session-lost'\n );\n}\n\n/**\n * Pages of older history stated while looking for an edited message's host\n * parent. Each page is up to a window's worth of messages, so an edit reaches\n * this many windows below what was loaded before it gives up.\n */\nexport const MAX_EDIT_ANCHOR_HISTORY_LOADS = 5;\n\n/**\n * The anchored `run/edit` for `sourceId`, stating older page interests one at\n * a time when the message's parent lies below the loaded window. Every page\n * is read back from the live documents (`readExtras` — the host mounts them\n * before it answers the statement), so the anchor is always the host's own\n * parent id.\n *\n * Resolves `null` — the caller's cue for the library's composer path, whose\n * failure it reports — when the thread is not a statewire thread, the host has\n * not settled the message, the history is exhausted without it, or the page\n * budget ({@link MAX_EDIT_ANCHOR_HISTORY_LOADS}) is spent. A synchronous\n * resolution never awaits: the first read either anchors at once or decides\n * that pages are needed.\n */\nexport async function resolveDeepAgentEditCommand({\n readExtras,\n sourceId,\n text,\n pageSize,\n maxHistoryLoads = MAX_EDIT_ANCHOR_HISTORY_LOADS,\n}: {\n /** The live thread extras — re-read per page so each anchor attempt sees the widened window. */\n readExtras: () => DeepAgentStatewireExtras | null;\n sourceId: string;\n text: string;\n pageSize?: number;\n maxHistoryLoads?: number;\n}): Promise<StatewireThread.RunEditCommand | null> {\n for (let page = 0; page <= maxHistoryLoads; page += 1) {\n const extras = readExtras();\n if (!extras) return null;\n const command = buildDeepAgentEditCommand({ extras, sourceId, text });\n if (command) return command;\n if (page === maxHistoryLoads || !extras.invoke) return null;\n const window = readWindow(extras);\n if (!isSourceBelowLoadedWindow({ wireMessages: extras.state?.messages, sourceId, window })) {\n return null;\n }\n const requests = window === null ? null : pageInterestRequests(window, pageSize);\n if (requests === null) return null;\n await extras.invoke(DEEP_AGENT_INTEREST_PROTOCOL, 'set', [requests]);\n }\n return null;\n}\n"],"names":["hasStatewireThreadExtras","readDeepAgentMessageWindow","pageInterestRequests","DEEP_AGENT_INTEREST_PROTOCOL"],"mappings":"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"}
@@ -134,6 +134,14 @@ export declare function loadOlderDeepAgentHistoryPage({ readExtras, pageSize, }:
134
134
  readExtras: () => DeepAgentStatewireExtras | null;
135
135
  pageSize?: number;
136
136
  }): Promise<boolean>;
137
+ /**
138
+ * Whether a {@link loadOlderDeepAgentHistoryPage} failure is the connection
139
+ * dropping under the page (statewire settles an ephemeral statement in flight
140
+ * at the drop `session-lost`), not the host refusing it. The re-attach carries
141
+ * the view loaded so far, so a reader looking for a message pages again once
142
+ * reconnected instead of deciding the history is exhausted.
143
+ */
144
+ export declare function isHistoryPageLostToReconnect(error: unknown): boolean;
137
145
  /**
138
146
  * Pages of older history stated while looking for an edited message's host
139
147
  * parent. Each page is up to a window's worth of messages, so an edit reaches
@@ -76,6 +76,11 @@ async function loadOlderDeepAgentHistoryPage({
76
76
  await extras.invoke(DEEP_AGENT_INTEREST_PROTOCOL, "set", [requests]);
77
77
  return true;
78
78
  }
79
+ function isHistoryPageLostToReconnect(error) {
80
+ if (typeof error !== "object" || error === null || !("failure" in error)) return false;
81
+ const { failure } = error;
82
+ return typeof failure === "object" && failure !== null && "cause" in failure && failure.cause === "session-lost";
83
+ }
79
84
  const MAX_EDIT_ANCHOR_HISTORY_LOADS = 5;
80
85
  async function resolveDeepAgentEditCommand({
81
86
  readExtras,
@@ -105,6 +110,7 @@ export {
105
110
  MAX_EDIT_ANCHOR_HISTORY_LOADS,
106
111
  buildDeepAgentEditCommand,
107
112
  deepAgentHistoryHasOlder,
113
+ isHistoryPageLostToReconnect,
108
114
  isSourceBelowLoadedWindow,
109
115
  loadOlderDeepAgentHistoryPage,
110
116
  readDeepAgentStatewireExtras,
@@ -1 +1 @@
1
- {"version":3,"file":"edit-command.js","sources":["../../../../agent-runtime/src/edit-command.ts"],"sourcesContent":["import type { StatewireThread } from '@assistant-ui/react-statewire';\nimport { DEEP_AGENT_INTEREST_PROTOCOL } from './generated/runconfig-contract';\nimport {\n type DeepAgentMessageWindow,\n pageInterestRequests,\n readDeepAgentMessageWindow,\n} from './message-window';\nimport { hasStatewireThreadExtras } from './thread-extras';\n\n/**\n * Wire-accurate `run/edit` construction for deep-agent retry/edit, shared by\n * every surface that resubmits a user message.\n *\n * assistant-ui builds the command's `runAnchorMessageId` from the CONVERTED\n * thread messages (`resolveEditCommand`: `messages[index - 1].id`), but the\n * deep-agent host validates that anchor against the edited message's parent in\n * its RAW message list (`harness_sdk.linear_thread`: the entry before it in\n * `state[\"messages\"]`). Those two lists do not line up:\n *\n * - the converter chunks an assistant turn and its tool messages into ONE\n * thread message carrying only the FIRST wire id, so the anchor names the\n * head of the previous turn instead of its last tool message;\n * - `sanitizeLangChainMessages` drops hidden-from-frontend and unconvertible\n * entries, so a dropped tail message is invisible to the anchor too.\n *\n * Either way the host rejects the command with `wrong-anchor`\n * (`runAnchorMessageId … is not the source's parent`) AFTER the composer's\n * synchronous `send()` returned, so the retry/edit silently does nothing.\n *\n * Building the command here off the replicated raw state makes the anchor the\n * same value the host computes.\n *\n * The raw list is the loaded interest window, so the first loaded message's\n * parent is not in it while older messages exist — an edit there must not\n * anchor on `null` (the root, rejected `wrong-anchor`); a message below the\n * window has no parent on this client at all. {@link resolveDeepAgentEditCommand}\n * states older page interests until the parent is loaded.\n */\n\n/**\n * Host metadata frozen at submission, settling once the async capture does.\n * The message-metadata preparation surface — `prepareMessageMetadata`,\n * `discardPreparedMessageMetadata`, `sendPreparedEdit` and `sendCommand`'s\n * `preparedMetadata` option — is what the monorepo patches into\n * `@assistant-ui/react-statewire@0.31.0` (`patches/`). It is declared\n * structurally here rather than as `StatewireThread.Extras[...]` so that the\n * published sources also compile against the unpatched upstream typings, where\n * those members are absent and the edit path's optional calls never run.\n */\nexport type DeepAgentPreparedMessageMetadata = Promise<Record<string, unknown> | undefined>;\n\n/** The pieces of the statewire thread extras the edit path reads. */\nexport interface DeepAgentStatewireExtras {\n /** The library's dispatch; it resolves with the host's reply to the command. */\n sendCommand: (\n command: StatewireThread.Command,\n options?: { preparedMetadata?: DeepAgentPreparedMessageMetadata | undefined },\n ) => Promise<unknown> | void;\n /** Optional on older hosts; capture before loading an edit's history anchor. */\n prepareMessageMetadata?: (() => DeepAgentPreparedMessageMetadata) | undefined;\n discardPreparedMessageMetadata?:\n | ((prepared: DeepAgentPreparedMessageMetadata) => void)\n | undefined;\n sendPreparedEdit?:\n | ((sourceId: string, prepared: DeepAgentPreparedMessageMetadata) => void)\n | undefined;\n isPreparingSubmission?: boolean;\n /** The composed thread state — its `messages` are the raw wire messages of the loaded window. */\n state: { messages?: readonly { id?: unknown }[] } | null;\n /** The mounted documents (the interest window), absent on a wire without documents. */\n documents?: StatewireThread.Extras['documents'];\n invoke?: StatewireThread.Extras['invoke'];\n /** The live run, when one is in flight; `epoch` advances on each dispatch. */\n runs: { runId?: string | null; epoch?: number };\n /** The host's replicated run status; absent on a surface that predates it. */\n status?: StatewireThread.ThreadStatus;\n}\n\n/**\n * The statewire extras of the nearest aui thread, or `null` when the thread is\n * not a statewire thread (e.g. a read-only subagent transcript runtime).\n * Gated on {@link hasStatewireThreadExtras} for the same reason the approval\n * card is: the library's own hooks throw on a non-statewire thread.\n */\nexport function readDeepAgentStatewireExtras(extras: unknown): DeepAgentStatewireExtras | null {\n if (!hasStatewireThreadExtras(extras)) return null;\n return extras as DeepAgentStatewireExtras;\n}\n\n/**\n * The host's parent of `sourceId`: the raw wire message directly before it\n * (`null` when it is the first of the whole transcript). Returns `undefined`\n * when `sourceId` is not in the raw list at all — an optimistic bubble the\n * host has not settled yet, a message below the loaded window, or a surface\n * whose state this module cannot read — or when it is the first loaded\n * message while older ones exist (`hasOlder`), so the caller can load more or\n * fall back to the library's own path instead of asserting a wrong anchor.\n */\nexport function resolveWireAnchorMessageId({\n wireMessages,\n sourceId,\n hasOlder = false,\n}: {\n wireMessages: readonly { id?: unknown }[] | undefined;\n sourceId: string;\n hasOlder?: boolean;\n}): string | null | undefined {\n if (!wireMessages) return undefined;\n const index = wireMessages.findIndex((message) => message?.id === sourceId);\n if (index < 0) return undefined;\n if (index === 0) return hasOlder ? undefined : null;\n const parentId = wireMessages[index - 1]?.id;\n return typeof parentId === 'string' ? parentId : undefined;\n}\n\n/**\n * Whether `sourceId`'s parent lies below the loaded window: the message is\n * absent from the raw list, or its first entry, while older messages exist.\n * The caller loads older history before an edit can be anchored.\n */\nexport function isSourceBelowLoadedWindow({\n wireMessages,\n sourceId,\n window,\n}: {\n wireMessages: readonly { id?: unknown }[] | undefined;\n sourceId: string;\n window: DeepAgentMessageWindow | null;\n}): boolean {\n if (!wireMessages || window === null || !window.hasOlder) return false;\n const index = wireMessages.findIndex((message) => message?.id === sourceId);\n return index <= 0;\n}\n\nconst readWindow = (extras: DeepAgentStatewireExtras) =>\n readDeepAgentMessageWindow(extras.documents?.list());\n\n/**\n * A fresh command / message id (uniqueness, not secrecy). `crypto.randomUUID`\n * where the host runtime has it — every browser, Bun, Node and Hermes with\n * webcrypto — and a v4-shaped fallback elsewhere, so the shared path never\n * throws on a runtime without full webcrypto.\n */\nfunction mintCommandId(): string {\n const webcrypto = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto;\n if (typeof webcrypto?.randomUUID === 'function') return webcrypto.randomUUID();\n const hex = (): string => Math.floor(Math.random() * 0x10000).toString(16).padStart(4, '0');\n return `${hex()}${hex()}-${hex()}-4${hex().slice(1)}-${hex()}-${hex()}${hex()}${hex()}`;\n}\n\n/**\n * The `run/edit` command for resubmitting `sourceId` with `text`, anchored on\n * the host's own parent. `null` when the anchor cannot be resolved from the\n * replicated state.\n */\nexport function buildDeepAgentEditCommand({\n extras,\n sourceId,\n text,\n}: {\n extras: DeepAgentStatewireExtras;\n sourceId: string;\n text: string;\n}): StatewireThread.RunEditCommand | null {\n const runAnchorMessageId = resolveWireAnchorMessageId({\n wireMessages: extras.state?.messages,\n sourceId,\n hasOlder: readWindow(extras)?.hasOlder ?? false,\n });\n if (runAnchorMessageId === undefined) return null;\n return {\n type: 'run/edit',\n runId: extras.runs.runId ?? mintCommandId(),\n message: { id: mintCommandId(), role: 'user', parts: [{ type: 'text', text }] },\n sourceId,\n runAnchorMessageId,\n };\n}\n\n/**\n * Whether a windowed statewire thread has older history than it has loaded:\n * `null` while that is not known yet (the head interest has not resolved; a\n * remembered transcript can show from cache before it does), and `false` for\n * a thread that is not a statewire thread, so a reader looking for an older\n * message waits for the window, or stops.\n */\nexport function deepAgentHistoryHasOlder(extras: unknown): boolean | null {\n const typed = readDeepAgentStatewireExtras(extras);\n if (typed === null) return false;\n return readWindow(typed)?.hasOlder ?? null;\n}\n\n/**\n * State one more page of older history for a windowed thread: the next page\n * past the loaded window's oldest message. Resolves `true` once the host has\n * mounted it (it answers the statement after mounting), `false` when there is\n * nothing older, the thread is not a windowed statewire thread, or no page can\n * be stated. For a reader that needs a message below the loaded window — a\n * search result revealing an older turn of a long conversation — and pages\n * until it renders.\n */\nexport async function loadOlderDeepAgentHistoryPage({\n readExtras,\n pageSize,\n}: {\n readExtras: () => DeepAgentStatewireExtras | null;\n pageSize?: number;\n}): Promise<boolean> {\n const extras = readExtras();\n if (!extras?.invoke) return false;\n const window = readWindow(extras);\n if (window === null || !window.hasOlder) return false;\n const requests = pageInterestRequests(window, pageSize);\n if (requests === null) return false;\n await extras.invoke(DEEP_AGENT_INTEREST_PROTOCOL, 'set', [requests]);\n return true;\n}\n\n/**\n * Pages of older history stated while looking for an edited message's host\n * parent. Each page is up to a window's worth of messages, so an edit reaches\n * this many windows below what was loaded before it gives up.\n */\nexport const MAX_EDIT_ANCHOR_HISTORY_LOADS = 5;\n\n/**\n * The anchored `run/edit` for `sourceId`, stating older page interests one at\n * a time when the message's parent lies below the loaded window. Every page\n * is read back from the live documents (`readExtras` — the host mounts them\n * before it answers the statement), so the anchor is always the host's own\n * parent id.\n *\n * Resolves `null` — the caller's cue for the library's composer path, whose\n * failure it reports — when the thread is not a statewire thread, the host has\n * not settled the message, the history is exhausted without it, or the page\n * budget ({@link MAX_EDIT_ANCHOR_HISTORY_LOADS}) is spent. A synchronous\n * resolution never awaits: the first read either anchors at once or decides\n * that pages are needed.\n */\nexport async function resolveDeepAgentEditCommand({\n readExtras,\n sourceId,\n text,\n pageSize,\n maxHistoryLoads = MAX_EDIT_ANCHOR_HISTORY_LOADS,\n}: {\n /** The live thread extras — re-read per page so each anchor attempt sees the widened window. */\n readExtras: () => DeepAgentStatewireExtras | null;\n sourceId: string;\n text: string;\n pageSize?: number;\n maxHistoryLoads?: number;\n}): Promise<StatewireThread.RunEditCommand | null> {\n for (let page = 0; page <= maxHistoryLoads; page += 1) {\n const extras = readExtras();\n if (!extras) return null;\n const command = buildDeepAgentEditCommand({ extras, sourceId, text });\n if (command) return command;\n if (page === maxHistoryLoads || !extras.invoke) return null;\n const window = readWindow(extras);\n if (!isSourceBelowLoadedWindow({ wireMessages: extras.state?.messages, sourceId, window })) {\n return null;\n }\n const requests = window === null ? null : pageInterestRequests(window, pageSize);\n if (requests === null) return null;\n await extras.invoke(DEEP_AGENT_INTEREST_PROTOCOL, 'set', [requests]);\n }\n return null;\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"edit-command.js","sources":["../../../../agent-runtime/src/edit-command.ts"],"sourcesContent":["import type { StatewireThread } from '@assistant-ui/react-statewire';\nimport { DEEP_AGENT_INTEREST_PROTOCOL } from './generated/runconfig-contract';\nimport {\n type DeepAgentMessageWindow,\n pageInterestRequests,\n readDeepAgentMessageWindow,\n} from './message-window';\nimport { hasStatewireThreadExtras } from './thread-extras';\n\n/**\n * Wire-accurate `run/edit` construction for deep-agent retry/edit, shared by\n * every surface that resubmits a user message.\n *\n * assistant-ui builds the command's `runAnchorMessageId` from the CONVERTED\n * thread messages (`resolveEditCommand`: `messages[index - 1].id`), but the\n * deep-agent host validates that anchor against the edited message's parent in\n * its RAW message list (`harness_sdk.linear_thread`: the entry before it in\n * `state[\"messages\"]`). Those two lists do not line up:\n *\n * - the converter chunks an assistant turn and its tool messages into ONE\n * thread message carrying only the FIRST wire id, so the anchor names the\n * head of the previous turn instead of its last tool message;\n * - `sanitizeLangChainMessages` drops hidden-from-frontend and unconvertible\n * entries, so a dropped tail message is invisible to the anchor too.\n *\n * Either way the host rejects the command with `wrong-anchor`\n * (`runAnchorMessageId … is not the source's parent`) AFTER the composer's\n * synchronous `send()` returned, so the retry/edit silently does nothing.\n *\n * Building the command here off the replicated raw state makes the anchor the\n * same value the host computes.\n *\n * The raw list is the loaded interest window, so the first loaded message's\n * parent is not in it while older messages exist — an edit there must not\n * anchor on `null` (the root, rejected `wrong-anchor`); a message below the\n * window has no parent on this client at all. {@link resolveDeepAgentEditCommand}\n * states older page interests until the parent is loaded.\n */\n\n/**\n * Host metadata frozen at submission, settling once the async capture does.\n * The message-metadata preparation surface — `prepareMessageMetadata`,\n * `discardPreparedMessageMetadata`, `sendPreparedEdit` and `sendCommand`'s\n * `preparedMetadata` option — is what the monorepo patches into\n * `@assistant-ui/react-statewire@0.31.0` (`patches/`). It is declared\n * structurally here rather than as `StatewireThread.Extras[...]` so that the\n * published sources also compile against the unpatched upstream typings, where\n * those members are absent and the edit path's optional calls never run.\n */\nexport type DeepAgentPreparedMessageMetadata = Promise<Record<string, unknown> | undefined>;\n\n/** The pieces of the statewire thread extras the edit path reads. */\nexport interface DeepAgentStatewireExtras {\n /** The library's dispatch; it resolves with the host's reply to the command. */\n sendCommand: (\n command: StatewireThread.Command,\n options?: { preparedMetadata?: DeepAgentPreparedMessageMetadata | undefined },\n ) => Promise<unknown> | void;\n /** Optional on older hosts; capture before loading an edit's history anchor. */\n prepareMessageMetadata?: (() => DeepAgentPreparedMessageMetadata) | undefined;\n discardPreparedMessageMetadata?:\n | ((prepared: DeepAgentPreparedMessageMetadata) => void)\n | undefined;\n sendPreparedEdit?:\n | ((sourceId: string, prepared: DeepAgentPreparedMessageMetadata) => void)\n | undefined;\n isPreparingSubmission?: boolean;\n /** The composed thread state — its `messages` are the raw wire messages of the loaded window. */\n state: { messages?: readonly { id?: unknown }[] } | null;\n /** The mounted documents (the interest window), absent on a wire without documents. */\n documents?: StatewireThread.Extras['documents'];\n invoke?: StatewireThread.Extras['invoke'];\n /** The live run, when one is in flight; `epoch` advances on each dispatch. */\n runs: { runId?: string | null; epoch?: number };\n /** The host's replicated run status; absent on a surface that predates it. */\n status?: StatewireThread.ThreadStatus;\n}\n\n/**\n * The statewire extras of the nearest aui thread, or `null` when the thread is\n * not a statewire thread (e.g. a read-only subagent transcript runtime).\n * Gated on {@link hasStatewireThreadExtras} for the same reason the approval\n * card is: the library's own hooks throw on a non-statewire thread.\n */\nexport function readDeepAgentStatewireExtras(extras: unknown): DeepAgentStatewireExtras | null {\n if (!hasStatewireThreadExtras(extras)) return null;\n return extras as DeepAgentStatewireExtras;\n}\n\n/**\n * The host's parent of `sourceId`: the raw wire message directly before it\n * (`null` when it is the first of the whole transcript). Returns `undefined`\n * when `sourceId` is not in the raw list at all — an optimistic bubble the\n * host has not settled yet, a message below the loaded window, or a surface\n * whose state this module cannot read — or when it is the first loaded\n * message while older ones exist (`hasOlder`), so the caller can load more or\n * fall back to the library's own path instead of asserting a wrong anchor.\n */\nexport function resolveWireAnchorMessageId({\n wireMessages,\n sourceId,\n hasOlder = false,\n}: {\n wireMessages: readonly { id?: unknown }[] | undefined;\n sourceId: string;\n hasOlder?: boolean;\n}): string | null | undefined {\n if (!wireMessages) return undefined;\n const index = wireMessages.findIndex((message) => message?.id === sourceId);\n if (index < 0) return undefined;\n if (index === 0) return hasOlder ? undefined : null;\n const parentId = wireMessages[index - 1]?.id;\n return typeof parentId === 'string' ? parentId : undefined;\n}\n\n/**\n * Whether `sourceId`'s parent lies below the loaded window: the message is\n * absent from the raw list, or its first entry, while older messages exist.\n * The caller loads older history before an edit can be anchored.\n */\nexport function isSourceBelowLoadedWindow({\n wireMessages,\n sourceId,\n window,\n}: {\n wireMessages: readonly { id?: unknown }[] | undefined;\n sourceId: string;\n window: DeepAgentMessageWindow | null;\n}): boolean {\n if (!wireMessages || window === null || !window.hasOlder) return false;\n const index = wireMessages.findIndex((message) => message?.id === sourceId);\n return index <= 0;\n}\n\nconst readWindow = (extras: DeepAgentStatewireExtras) =>\n readDeepAgentMessageWindow(extras.documents?.list());\n\n/**\n * A fresh command / message id (uniqueness, not secrecy). `crypto.randomUUID`\n * where the host runtime has it — every browser, Bun, Node and Hermes with\n * webcrypto — and a v4-shaped fallback elsewhere, so the shared path never\n * throws on a runtime without full webcrypto.\n */\nfunction mintCommandId(): string {\n const webcrypto = (globalThis as { crypto?: { randomUUID?: () => string } }).crypto;\n if (typeof webcrypto?.randomUUID === 'function') return webcrypto.randomUUID();\n const hex = (): string => Math.floor(Math.random() * 0x10000).toString(16).padStart(4, '0');\n return `${hex()}${hex()}-${hex()}-4${hex().slice(1)}-${hex()}-${hex()}${hex()}${hex()}`;\n}\n\n/**\n * The `run/edit` command for resubmitting `sourceId` with `text`, anchored on\n * the host's own parent. `null` when the anchor cannot be resolved from the\n * replicated state.\n */\nexport function buildDeepAgentEditCommand({\n extras,\n sourceId,\n text,\n}: {\n extras: DeepAgentStatewireExtras;\n sourceId: string;\n text: string;\n}): StatewireThread.RunEditCommand | null {\n const runAnchorMessageId = resolveWireAnchorMessageId({\n wireMessages: extras.state?.messages,\n sourceId,\n hasOlder: readWindow(extras)?.hasOlder ?? false,\n });\n if (runAnchorMessageId === undefined) return null;\n return {\n type: 'run/edit',\n runId: extras.runs.runId ?? mintCommandId(),\n message: { id: mintCommandId(), role: 'user', parts: [{ type: 'text', text }] },\n sourceId,\n runAnchorMessageId,\n };\n}\n\n/**\n * Whether a windowed statewire thread has older history than it has loaded:\n * `null` while that is not known yet (the head interest has not resolved; a\n * remembered transcript can show from cache before it does), and `false` for\n * a thread that is not a statewire thread, so a reader looking for an older\n * message waits for the window, or stops.\n */\nexport function deepAgentHistoryHasOlder(extras: unknown): boolean | null {\n const typed = readDeepAgentStatewireExtras(extras);\n if (typed === null) return false;\n return readWindow(typed)?.hasOlder ?? null;\n}\n\n/**\n * State one more page of older history for a windowed thread: the next page\n * past the loaded window's oldest message. Resolves `true` once the host has\n * mounted it (it answers the statement after mounting), `false` when there is\n * nothing older, the thread is not a windowed statewire thread, or no page can\n * be stated. For a reader that needs a message below the loaded window — a\n * search result revealing an older turn of a long conversation — and pages\n * until it renders.\n */\nexport async function loadOlderDeepAgentHistoryPage({\n readExtras,\n pageSize,\n}: {\n readExtras: () => DeepAgentStatewireExtras | null;\n pageSize?: number;\n}): Promise<boolean> {\n const extras = readExtras();\n if (!extras?.invoke) return false;\n const window = readWindow(extras);\n if (window === null || !window.hasOlder) return false;\n const requests = pageInterestRequests(window, pageSize);\n if (requests === null) return false;\n await extras.invoke(DEEP_AGENT_INTEREST_PROTOCOL, 'set', [requests]);\n return true;\n}\n\n/**\n * Whether a {@link loadOlderDeepAgentHistoryPage} failure is the connection\n * dropping under the page (statewire settles an ephemeral statement in flight\n * at the drop `session-lost`), not the host refusing it. The re-attach carries\n * the view loaded so far, so a reader looking for a message pages again once\n * reconnected instead of deciding the history is exhausted.\n */\nexport function isHistoryPageLostToReconnect(error: unknown): boolean {\n if (typeof error !== 'object' || error === null || !('failure' in error)) return false;\n const { failure } = error;\n return (\n typeof failure === 'object' &&\n failure !== null &&\n 'cause' in failure &&\n failure.cause === 'session-lost'\n );\n}\n\n/**\n * Pages of older history stated while looking for an edited message's host\n * parent. Each page is up to a window's worth of messages, so an edit reaches\n * this many windows below what was loaded before it gives up.\n */\nexport const MAX_EDIT_ANCHOR_HISTORY_LOADS = 5;\n\n/**\n * The anchored `run/edit` for `sourceId`, stating older page interests one at\n * a time when the message's parent lies below the loaded window. Every page\n * is read back from the live documents (`readExtras` — the host mounts them\n * before it answers the statement), so the anchor is always the host's own\n * parent id.\n *\n * Resolves `null` — the caller's cue for the library's composer path, whose\n * failure it reports — when the thread is not a statewire thread, the host has\n * not settled the message, the history is exhausted without it, or the page\n * budget ({@link MAX_EDIT_ANCHOR_HISTORY_LOADS}) is spent. A synchronous\n * resolution never awaits: the first read either anchors at once or decides\n * that pages are needed.\n */\nexport async function resolveDeepAgentEditCommand({\n readExtras,\n sourceId,\n text,\n pageSize,\n maxHistoryLoads = MAX_EDIT_ANCHOR_HISTORY_LOADS,\n}: {\n /** The live thread extras — re-read per page so each anchor attempt sees the widened window. */\n readExtras: () => DeepAgentStatewireExtras | null;\n sourceId: string;\n text: string;\n pageSize?: number;\n maxHistoryLoads?: number;\n}): Promise<StatewireThread.RunEditCommand | null> {\n for (let page = 0; page <= maxHistoryLoads; page += 1) {\n const extras = readExtras();\n if (!extras) return null;\n const command = buildDeepAgentEditCommand({ extras, sourceId, text });\n if (command) return command;\n if (page === maxHistoryLoads || !extras.invoke) return null;\n const window = readWindow(extras);\n if (!isSourceBelowLoadedWindow({ wireMessages: extras.state?.messages, sourceId, window })) {\n return null;\n }\n const requests = window === null ? null : pageInterestRequests(window, pageSize);\n if (requests === null) return null;\n await extras.invoke(DEEP_AGENT_INTEREST_PROTOCOL, 'set', [requests]);\n }\n return null;\n}\n"],"names":[],"mappings":"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"}
@@ -241,6 +241,8 @@ const CLIENT_TOOL_RESULT_STATUS_SUCCESS = "success";
241
241
  const CLIENT_TOOL_RESULT_STATUS_ERROR = "error";
242
242
  const DEEP_AGENT_PROTOCOL_VERSION_HEADER = "x-athena-deep-agent-protocol-version";
243
243
  const DEEP_AGENT_MESSAGE_WINDOW_HEADER = "x-athena-deep-agent-window";
244
+ const DEEP_AGENT_MESSAGE_INTERESTS_HEADER = "x-athena-deep-agent-interests";
245
+ const DEEP_AGENT_MAX_MESSAGE_INTERESTS_HEADER_BYTES = 8192;
244
246
  const DEEP_AGENT_PROTOCOL_STATE_KEY = "protocol";
245
247
  const DEEP_AGENT_INTEREST_PROTOCOL = "athena/interest";
246
248
  const DEEP_AGENT_MAIN_NS = "main";
@@ -248,6 +250,7 @@ const DEEP_AGENT_DEFAULT_MESSAGE_WINDOW = 40;
248
250
  const DEEP_AGENT_MIN_MESSAGE_WINDOW = 8;
249
251
  const DEEP_AGENT_MAX_MESSAGE_WINDOW = 200;
250
252
  const DEEP_AGENT_MAX_INTERESTS = 16;
253
+ const DEEP_AGENT_OVERSIZED_INTEREST_CODE = "oversized-interest";
251
254
  const DEEP_AGENT_HISTORY_TOOL_OUTPUT_COMMAND = "history/tool_output";
252
255
  const DEEP_AGENT_HISTORY_MESSAGE_COMMAND = "history/message";
253
256
  const DEEP_AGENT_TRUNCATED_CONTENT_KEY = "athena_content_truncated";
@@ -273,9 +276,12 @@ exports.DEEP_AGENT_LANE_USAGE_KEY = DEEP_AGENT_LANE_USAGE_KEY;
273
276
  exports.DEEP_AGENT_MAIN_NS = DEEP_AGENT_MAIN_NS;
274
277
  exports.DEEP_AGENT_MAX_INTERESTS = DEEP_AGENT_MAX_INTERESTS;
275
278
  exports.DEEP_AGENT_MAX_LANE_PAGE = DEEP_AGENT_MAX_LANE_PAGE;
279
+ exports.DEEP_AGENT_MAX_MESSAGE_INTERESTS_HEADER_BYTES = DEEP_AGENT_MAX_MESSAGE_INTERESTS_HEADER_BYTES;
276
280
  exports.DEEP_AGENT_MAX_MESSAGE_WINDOW = DEEP_AGENT_MAX_MESSAGE_WINDOW;
281
+ exports.DEEP_AGENT_MESSAGE_INTERESTS_HEADER = DEEP_AGENT_MESSAGE_INTERESTS_HEADER;
277
282
  exports.DEEP_AGENT_MESSAGE_WINDOW_HEADER = DEEP_AGENT_MESSAGE_WINDOW_HEADER;
278
283
  exports.DEEP_AGENT_MIN_MESSAGE_WINDOW = DEEP_AGENT_MIN_MESSAGE_WINDOW;
284
+ exports.DEEP_AGENT_OVERSIZED_INTEREST_CODE = DEEP_AGENT_OVERSIZED_INTEREST_CODE;
279
285
  exports.DEEP_AGENT_PROTOCOL_STATE_KEY = DEEP_AGENT_PROTOCOL_STATE_KEY;
280
286
  exports.DEEP_AGENT_PROTOCOL_VERSION_HEADER = DEEP_AGENT_PROTOCOL_VERSION_HEADER;
281
287
  exports.DEEP_AGENT_REPEATS_RESULT_KEY = DEEP_AGENT_REPEATS_RESULT_KEY;
@@ -1 +1 @@
1
- {"version":3,"file":"runconfig-contract.cjs","sources":["../../../../../agent-runtime/src/generated/runconfig-contract.ts"],"sourcesContent":["// GENERATED FILE — DO NOT EDIT BY HAND.\n//\n// Source of truth (agora):\n// agora/agora/graphs/athena_deep_agent/run_config.py (_PARSED_CUSTOM_KEYS / _COMPANION_CUSTOM_KEYS / PER_SEND_CUSTOM_KEYS)\n// agora/agora/graphs/athena_deep_agent/thread_config.py (server config lane + config/* command names)\n// agora/agora/graphs/athena_deep_agent/session_asset.py (KNOWN_START_CHANNELS / DEEP_AGENT_RUNTIME_MARKER)\n// agora/agora/graphs/athena_deep_agent/client_tools.py (client-tool interrupt + result-envelope literals)\n// agora/agora/graphs/athena_deep_agent/protocol_version.py (wire-contract version negotiation)\n// agora/agora/graphs/athena_deep_agent/message_window.py (interest windows + history commands)\n// agora/agora/type_definitions/collab_agent.py (CAPABILITIES ladder: absent mode + new-agent default)\n//\n// Regenerate:\n// cd agora && mise exec -- infisical run --command 'uv run python scripts/export_runconfig_contract.py'\n//\n// CI verifies this file matches the Python source (agora-check runs the\n// exporter with --check), so hand edits and un-regenerated key changes fail.\n\n/** `runConfig.custom` keys parsed by agora's `parse_deep_agent_run_config`. */\nexport const RUN_CONFIG_PARSED_CUSTOM_KEYS = [\n \"agent_catalog_asset_ids\",\n \"approve_changes\",\n \"catalog_asset_ids\",\n \"channel_reply_turn\",\n \"coding_worker_asset_id\",\n \"coding_workers\",\n \"compiled_subagents\",\n \"declined_toolkit_ids\",\n \"drive_mounts\",\n \"enable_interpreter\",\n \"enable_persistent_fs\",\n \"enable_sandbox\",\n \"enable_skills\",\n \"enabled_tools\",\n \"environment\",\n \"environment_id\",\n \"environment_name\",\n \"excluded_middleware\",\n \"excluded_tools\",\n \"extra_middleware\",\n \"include_citation_instructions\",\n \"interpreter_max_ptc_calls\",\n \"interpreter_mode\",\n \"interpreter_ptc\",\n \"interpreter_ptc_exclusive\",\n \"interpreter_runtime\",\n \"interpreter_subagents\",\n \"interpreter_timeout_seconds\",\n \"interrupt_on\",\n \"knowledge_base\",\n \"mcp_server_configs\",\n \"mcp_servers\",\n \"memory\",\n \"outbound_approval_allowlist\",\n \"permissions\",\n \"pre_approved_tools\",\n \"project_id\",\n \"read_only\",\n \"recursion_limit\",\n \"run_label\",\n \"sandbox_runtime\",\n \"secret_asset_ids\",\n \"session_computer\",\n \"session_machine\",\n \"session_vm_retention\",\n \"skill_asset_ids\",\n \"skills\",\n \"subagents\",\n \"system_prompt\",\n \"tool_description_overrides\",\n \"voice_update_handle\",\n \"workbench\",\n] as const;\n\n/** `runConfig.custom` keys consumed by the surrounding deep-agent request machinery rather than the capability parser. */\nexport const RUN_CONFIG_COMPANION_CUSTOM_KEYS = [\n \"addressed_agents\",\n \"agent\",\n \"agent_available_toolkits\",\n \"allowed_tab_ids\",\n \"app_id\",\n \"channel\",\n \"channel_router\",\n \"client_tools\",\n \"collab_agent_id\",\n \"collab_channel_id\",\n \"collab_entry_channel_id\",\n \"custom_tool_configs\",\n \"deterministic\",\n \"device_id\",\n \"device_toolkits\",\n \"dry_run\",\n \"enabled_toolkits\",\n \"entry_point\",\n \"from_stored_config\",\n \"frontend_available\",\n \"generative_frame_inline\",\n \"github_identity\",\n \"max_tokens\",\n \"middleware\",\n \"model\",\n \"muses_enabled\",\n \"muses_recall_enabled\",\n \"office_context\",\n \"panel_config\",\n \"posthog_session_id\",\n \"run_budget\",\n \"runtime\",\n \"session_id\",\n \"session_origin_kind\",\n \"session_tab_id\",\n \"skip_title_generation\",\n \"source_aop_id\",\n \"start_channel\",\n \"structured_output\",\n \"temperature\",\n \"tool_limit_override\",\n \"trigger_type\",\n \"workspace_id\",\n] as const;\n\n/** Every `runConfig.custom` key some deep-agent request consumer reads. A key outside this set is invisible to the run and trips agora's unknown-key telemetry. */\nexport const RUN_CONFIG_CUSTOM_KEYS = [\n \"addressed_agents\",\n \"agent\",\n \"agent_available_toolkits\",\n \"agent_catalog_asset_ids\",\n \"allowed_tab_ids\",\n \"app_id\",\n \"approve_changes\",\n \"catalog_asset_ids\",\n \"channel\",\n \"channel_reply_turn\",\n \"channel_router\",\n \"client_tools\",\n \"coding_worker_asset_id\",\n \"coding_workers\",\n \"collab_agent_id\",\n \"collab_channel_id\",\n \"collab_entry_channel_id\",\n \"compiled_subagents\",\n \"custom_tool_configs\",\n \"declined_toolkit_ids\",\n \"deterministic\",\n \"device_id\",\n \"device_toolkits\",\n \"drive_mounts\",\n \"dry_run\",\n \"enable_interpreter\",\n \"enable_persistent_fs\",\n \"enable_sandbox\",\n \"enable_skills\",\n \"enabled_toolkits\",\n \"enabled_tools\",\n \"entry_point\",\n \"environment\",\n \"environment_id\",\n \"environment_name\",\n \"excluded_middleware\",\n \"excluded_tools\",\n \"extra_middleware\",\n \"from_stored_config\",\n \"frontend_available\",\n \"generative_frame_inline\",\n \"github_identity\",\n \"include_citation_instructions\",\n \"interpreter_max_ptc_calls\",\n \"interpreter_mode\",\n \"interpreter_ptc\",\n \"interpreter_ptc_exclusive\",\n \"interpreter_runtime\",\n \"interpreter_subagents\",\n \"interpreter_timeout_seconds\",\n \"interrupt_on\",\n \"knowledge_base\",\n \"max_tokens\",\n \"mcp_server_configs\",\n \"mcp_servers\",\n \"memory\",\n \"middleware\",\n \"model\",\n \"muses_enabled\",\n \"muses_recall_enabled\",\n \"office_context\",\n \"outbound_approval_allowlist\",\n \"panel_config\",\n \"permissions\",\n \"posthog_session_id\",\n \"pre_approved_tools\",\n \"project_id\",\n \"read_only\",\n \"recursion_limit\",\n \"run_budget\",\n \"run_label\",\n \"runtime\",\n \"sandbox_runtime\",\n \"secret_asset_ids\",\n \"session_computer\",\n \"session_id\",\n \"session_machine\",\n \"session_origin_kind\",\n \"session_tab_id\",\n \"session_vm_retention\",\n \"skill_asset_ids\",\n \"skills\",\n \"skip_title_generation\",\n \"source_aop_id\",\n \"start_channel\",\n \"structured_output\",\n \"subagents\",\n \"system_prompt\",\n \"temperature\",\n \"tool_description_overrides\",\n \"tool_limit_override\",\n \"trigger_type\",\n \"voice_update_handle\",\n \"workbench\",\n \"workspace_id\",\n] as const;\n\nexport type RunConfigCustomKey = (typeof RUN_CONFIG_CUSTOM_KEYS)[number];\n\n/** Fast membership checks for builder/test assertions. */\nexport const RUN_CONFIG_CUSTOM_KEY_SET: ReadonlySet<string> = new Set(\n RUN_CONFIG_CUSTOM_KEYS,\n);\n\n/** `runConfig.custom` keys a client still carries per send on a thread with server config; every other key is dropped at dispatch. */\nexport const RUN_CONFIG_PER_SEND_CUSTOM_KEYS = [\n \"addressed_agents\",\n \"agent\",\n \"agent_available_toolkits\",\n \"allowed_tab_ids\",\n \"app_id\",\n \"channel\",\n \"channel_reply_turn\",\n \"channel_router\",\n \"client_tools\",\n \"collab_channel_id\",\n \"collab_entry_channel_id\",\n \"deterministic\",\n \"device_id\",\n \"device_toolkits\",\n \"dry_run\",\n \"entry_point\",\n \"from_stored_config\",\n \"frontend_available\",\n \"generative_frame_inline\",\n \"github_identity\",\n \"muses_enabled\",\n \"muses_recall_enabled\",\n \"office_context\",\n \"posthog_session_id\",\n \"project_id\",\n \"read_only\",\n \"run_budget\",\n \"runtime\",\n \"session_id\",\n \"session_origin_kind\",\n \"session_tab_id\",\n \"skip_title_generation\",\n \"source_aop_id\",\n \"start_channel\",\n \"structured_output\",\n \"tool_limit_override\",\n \"trigger_type\",\n \"voice_update_handle\",\n \"workspace_id\",\n] as const;\n\nexport type RunConfigPerSendCustomKey =\n (typeof RUN_CONFIG_PER_SEND_CUSTOM_KEYS)[number];\n\n/** Fast membership checks for builder/test assertions. */\nexport const RUN_CONFIG_PER_SEND_CUSTOM_KEY_SET: ReadonlySet<string> = new Set(\n RUN_CONFIG_PER_SEND_CUSTOM_KEYS,\n);\n\n/** Keys the thread's server config lane owns — changed only through the `config/*` commands, never per send. */\nexport const THREAD_CONFIG_CUSTOM_KEYS = [\n \"agent_catalog_asset_ids\",\n \"approve_changes\",\n \"catalog_asset_ids\",\n \"coding_worker_asset_id\",\n \"coding_workers\",\n \"collab_agent_id\",\n \"compiled_subagents\",\n \"custom_tool_configs\",\n \"declined_toolkit_ids\",\n \"drive_mounts\",\n \"enable_interpreter\",\n \"enable_persistent_fs\",\n \"enable_sandbox\",\n \"enable_skills\",\n \"enabled_toolkits\",\n \"enabled_tools\",\n \"environment\",\n \"environment_id\",\n \"environment_name\",\n \"excluded_middleware\",\n \"excluded_tools\",\n \"extra_middleware\",\n \"include_citation_instructions\",\n \"interpreter_max_ptc_calls\",\n \"interpreter_mode\",\n \"interpreter_ptc\",\n \"interpreter_ptc_exclusive\",\n \"interpreter_runtime\",\n \"interpreter_subagents\",\n \"interpreter_timeout_seconds\",\n \"interrupt_on\",\n \"knowledge_base\",\n \"max_tokens\",\n \"mcp_server_configs\",\n \"mcp_servers\",\n \"memory\",\n \"middleware\",\n \"model\",\n \"outbound_approval_allowlist\",\n \"permissions\",\n \"pre_approved_tools\",\n \"recursion_limit\",\n \"run_label\",\n \"sandbox_runtime\",\n \"secret_asset_ids\",\n \"session_computer\",\n \"session_machine\",\n \"session_vm_retention\",\n \"skill_asset_ids\",\n \"skills\",\n \"subagents\",\n \"system_prompt\",\n \"temperature\",\n \"tool_description_overrides\",\n \"workbench\",\n] as const;\n\nexport type ThreadConfigCustomKey = (typeof THREAD_CONFIG_CUSTOM_KEYS)[number];\n\n/** Fast membership checks for builder/test assertions. */\nexport const THREAD_CONFIG_CUSTOM_KEY_SET: ReadonlySet<string> = new Set(\n THREAD_CONFIG_CUSTOM_KEYS,\n);\n\n/** Replicated-state key of the server config lane (`{ version, custom }`). */\nexport const DEEP_AGENT_CONFIG_STATE_KEY = \"config\";\n\n/** The statewire commands that mutate the server config lane. */\nexport const DEEP_AGENT_CONFIG_COMMANDS = {\n patch: \"config/patch\",\n toolsEnable: \"config/tools/enable\",\n toolsDisable: \"config/tools/disable\",\n} as const;\n\n/** `start_channel` values the session substrate stamps as provenance; anything else clamps to \"web\". */\nexport const KNOWN_START_CHANNELS = [\n \"agent_orchestration\",\n \"api\",\n \"automation\",\n \"chrome_extension\",\n \"cli\",\n \"comment_agent\",\n \"default_voice\",\n \"desktop_app\",\n \"email\",\n \"meetings\",\n \"mobile_app\",\n \"mobile_app_voice\",\n \"office_addin\",\n \"orchestration\",\n \"programmatic\",\n \"slack\",\n \"sms\",\n \"task\",\n \"teams\",\n \"voice\",\n \"voice_memo\",\n \"web\",\n] as const;\n\nexport type KnownStartChannel = (typeof KNOWN_START_CHANNELS)[number];\n\n/** Fast membership checks for builder/test assertions. */\nexport const KNOWN_START_CHANNEL_SET: ReadonlySet<string> = new Set(\n KNOWN_START_CHANNELS,\n);\n\n/** `runConfig.custom.runtime` marker selecting the deep-agent runtime. */\nexport const DEEP_AGENT_RUNTIME_MARKER = \"athena_deep_agent\";\n\n/**\n * Collab-agent capability ladder (agent schema v3): per explicit\n * capability field, what an ABSENT value means and the value stamped on\n * a new agent. Resolved by agora's `capability_decoder` and the one agent\n * compiler on every run: `passthrough` — explicit only, absent means off;\n * `off` — absent means off under every `runtime` marker; `runtime` —\n * absent derives from the `runtime` marker (`athena_deep_agent` on, any\n * other or missing marker off).\n */\nexport const COLLAB_AGENT_CAPABILITIES = {\n deepAgentBuiltinsEnabled: { absent: \"runtime\", default: true },\n interpreterEnabled: { absent: \"off\", default: false },\n sandboxEnabled: { absent: \"passthrough\", default: false },\n skillsEnabled: { absent: \"runtime\", default: true },\n} as const;\n\nexport type CollabAgentCapabilityField = keyof typeof COLLAB_AGENT_CAPABILITIES;\n\nexport type CollabAgentCapabilityAbsentMode =\n (typeof COLLAB_AGENT_CAPABILITIES)[CollabAgentCapabilityField][\"absent\"];\n\n/** `source`/`type` stamped on client-tool interrupt payloads by agora. */\nexport const CLIENT_TOOL_INTERRUPT_SOURCE = \"client_tool\";\n\n/** `status` literals of the result envelope a client resumes a parked client-tool call with. */\nexport const CLIENT_TOOL_RESULT_STATUSES = [\"error\", \"success\"] as const;\n\nexport type ClientToolResultStatus =\n (typeof CLIENT_TOOL_RESULT_STATUSES)[number];\n\nexport const CLIENT_TOOL_RESULT_STATUS_SUCCESS = \"success\";\n\nexport const CLIENT_TOOL_RESULT_STATUS_ERROR = \"error\";\n\n/**\n * Result envelope a client resumes a parked client-tool call with,\n * keyed by interrupt id:\n * `{ client_tool_results: { <interrupt_id>: <envelope> } }`.\n * Agora relays the envelope to the model verbatim.\n */\nexport type ClientToolResultEnvelopeContract =\n | { status: typeof CLIENT_TOOL_RESULT_STATUS_SUCCESS; result: unknown }\n | { status: typeof CLIENT_TOOL_RESULT_STATUS_ERROR; error: string };\n\n/**\n * The deep-agent wire-contract version this client build speaks,\n * declared on every attach. The host records it for attach telemetry\n * and per-version behaviour; it has no minimum client version, so no\n * build is refused for the version it declares (the `protocol` state\n * lane's `minClientVersion` is the constant 1).\n */\nexport const DEEP_AGENT_PROTOCOL_VERSION = 2;\n\n/**\n * The first contract version whose host a client states `follow` to (a\n * subagent lane's steps, each its own document): a client follows a\n * lane only on a host whose `protocol` lane advertises at least this\n * version. A host that predates `follow` refuses it with\n * `invalid-interest`.\n */\nexport const DEEP_AGENT_LANE_FOLLOW_PROTOCOL_VERSION = 2;\n\n/** Attach header carrying the client's declared contract version. */\nexport const DEEP_AGENT_PROTOCOL_VERSION_HEADER =\n \"x-athena-deep-agent-protocol-version\";\n\n/** Attach header declaring the head window a fresh client wants in its hello (host-clamped). */\nexport const DEEP_AGENT_MESSAGE_WINDOW_HEADER = \"x-athena-deep-agent-window\";\n\n/** Replicated-state key of the server-advertised version lane. */\nexport const DEEP_AGENT_PROTOCOL_STATE_KEY = \"protocol\";\n\n/** Ephemeral subprotocol carrying a client's message-window interests. */\nexport const DEEP_AGENT_INTEREST_PROTOCOL = \"athena/interest\";\n\n/** Ephemeral subprotocol carrying a client's synced context document. */\nexport const DEEP_AGENT_CONTEXT_PROTOCOL = \"athena/context\";\n\n/** The only interest namespace the host resolves (the linear transcript). */\nexport const DEEP_AGENT_MAIN_NS = \"main\";\n\n/** Window size (interest `before`) a client asks for by default. */\nexport const DEEP_AGENT_DEFAULT_MESSAGE_WINDOW = 40;\n\n/** Bounds on a window size. */\nexport const DEEP_AGENT_MIN_MESSAGE_WINDOW = 8;\n\nexport const DEEP_AGENT_MAX_MESSAGE_WINDOW = 200;\n\n/** Interests one attach may hold at once (the head plus its pages). */\nexport const DEEP_AGENT_MAX_INTERESTS = 16;\n\n/** Command returning a truncated tool output whole. */\nexport const DEEP_AGENT_HISTORY_TOOL_OUTPUT_COMMAND = \"history/tool_output\";\n\n/** Command returning one stored message whole (provenance and full tool output included). */\nexport const DEEP_AGENT_HISTORY_MESSAGE_COMMAND = \"history/message\";\n\n/** Wire key marking a tool message whose content was truncated. */\nexport const DEEP_AGENT_TRUNCATED_CONTENT_KEY = \"athena_content_truncated\";\n\n/**\n * Wire key on a running `task` card whose nested transcript rides cut to its\n * newest steps: `{ messages, tool_calls }` over the whole stored transcript.\n */\nexport const DEEP_AGENT_TRUNCATED_LANE_KEY = \"athena_lane_truncated\";\n\n/**\n * Wire key on a `task` card, and on an in-eval lane's `ptc_subagents` entry,\n * carrying the whole lane's token use however much of the lane the wire\n * carries: `{ input_tokens, output_tokens, cache_read_input_tokens,\n * cache_creation_input_tokens }`, the input counting its cache reads and\n * writes. Absent while the lane's steps report no usage.\n */\nexport const DEEP_AGENT_LANE_USAGE_KEY = \"athena_lane_usage\";\n\n/**\n * The newest nested messages a cut card carries whole; the entries ahead\n * of them are the older assistant turns that requested results among\n * them, cut to those calls.\n */\nexport const DEEP_AGENT_RUNNING_LANE_WIRE_MESSAGES = 8;\n\n/**\n * Key of a followed lane's window (`follows[ns]` on a resolution whose\n * request added `follow: {before}`) naming the `task` call whose card\n * holds the lane.\n */\nexport const DEEP_AGENT_FOLLOW_TOOL_CALL_ID_KEY = \"toolCallId\";\n\n/** The most lane steps one attach follows, across every lane. */\nexport const DEEP_AGENT_MAX_FOLLOWED_STEPS = 200;\n\n/**\n * The first contract version a client declares to see a finished card cut\n * like a running one (and to follow lanes and page them through\n * `history/lane`). Below it, or declaring nothing, finished cards ride whole.\n */\nexport const DEEP_AGENT_LANE_CUT_PROTOCOL_VERSION = 2;\n\n/**\n * Last element of the key a cut finished card's document rides under:\n * `[threadId, \"main\", messageId, \"cut\"]`. A view holds that key or the\n * card's own, never both.\n */\nexport const DEEP_AGENT_CUT_LANE_DOCUMENT = \"cut\";\n\n/**\n * Command returning one page of a card's nested transcript, oldest first:\n * `{ messageId, before, at? }` answers\n * `{ messageId, toolCallId, ns, steps, more: { before }, total }`; the page\n * holds the newest `before` entries, or those strictly older than `at`.\n */\nexport const DEEP_AGENT_HISTORY_LANE_COMMAND = \"history/lane\";\n\n/** The most entries one `history/lane` page asks for. */\nexport const DEEP_AGENT_MAX_LANE_PAGE = 200;\n\n/** The most encoded characters one `history/lane` page carries (at least one entry). */\nexport const DEEP_AGENT_HISTORY_LANE_PAGE_CHARS = 1048576;\n\n/**\n * Set on the last step of a cut finished card whose text is the card's own\n * `content` (the subagent's report): the step rides with empty content, and\n * the card's `content` is its text.\n */\nexport const DEEP_AGENT_REPEATS_RESULT_KEY = \"athena_content_repeats_result\";\n\n/** Most inline-image payload characters one message carries whole on the wire. */\nexport const DEEP_AGENT_INLINE_IMAGE_WIRE_BUDGET = 4194304;\n\n/** Wire key on an image block left off the wire: `{ index, chars, mediaType }`. */\nexport const DEEP_AGENT_OMITTED_IMAGE_KEY = \"athena_image_omitted\";\n\n/** The image an omitted block carries instead of its own (a neutral PNG tile). */\nexport const DEEP_AGENT_OMITTED_IMAGE_PLACEHOLDER_URL =\n \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKAAAAB4AQMAAABPbGssAAAABlBMVEXi6PCUo7jao11HAAAA6ElEQVR42u2UyW3DMBBF3wxogEd2EJbCElKQDRCwC3MpSRc5eLuYokgNLEUxctK/CHyanQts2vRO3QdlALVsXsBvecqxxr1ob0A5GlDJU+hICxN54p/qXAx/+FpoeeE8hTerzfvByn7ifzpaBtWCOwv6bMVMBgzRgNGKmUL9McDs4XOSyEHuoKCI76AiqOugg+y0gx6SN+YQg3QwALGk19pQSKV/reOocyoww27oU5sxhAbKUNgIqrVxrvnovJ80MFgxYy23wtTss44tmL+bAuOE2p2o0fJa3iW/6iR/lEfx8kv3TZtW6AFk5Sf3k+GTswAAAABJRU5ErkJggg==\";\n\n/**\n * Command returning one inline image of a stored message in chunks:\n * `{ messageId, index, offset? }` answers\n * `{ messageId, index, mediaType, offset, total, chunk, next }`; the\n * chunks joined in order are the image's `data:` URL, and `next` is\n * the offset to ask for next (`null` after the last chunk).\n */\nexport const DEEP_AGENT_HISTORY_IMAGE_COMMAND = \"history/image\";\n\n/**\n * Command returning one inline image of a lane step in chunks, as\n * `history/image` does a stored message's: `{ messageId | lane, step,\n * index, offset? }` answers `{ messageId, lane, step, index, mediaType,\n * offset, total, chunk, next }`, with `messageId` null for an in-eval\n * lane and `lane` null for a card.\n */\nexport const DEEP_AGENT_HISTORY_LANE_IMAGE_COMMAND = \"history/lane_image\";\n"],"names":[],"mappings":";;AAyHO,MAAM,yBAAyB;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAK8D,IAAI;AAAA,EAChE;AACF;AAGO,MAAM,kCAAkC;AAAA,EAC7C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAMuE,IAAI;AAAA,EACzE;AACF;AAGO,MAAM,4BAA4B;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAKiE,IAAI;AAAA,EACnE;AACF;AAMO,MAAM,6BAA6B;AAAA,EACxC,OAAO;AAAA,EACP,aAAa;AAAA,EACb,cAAc;AAChB;AAGO,MAAM,uBAAuB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAK4D,IAAI;AAAA,EAC9D;AACF;AA2BO,MAAM,+BAA+B;AAQrC,MAAM,oCAAoC;AAE1C,MAAM,kCAAkC;AA+BxC,MAAM,qCACX;AAGK,MAAM,mCAAmC;AAGzC,MAAM,gCAAgC;AAGtC,MAAM,+BAA+B;AAMrC,MAAM,qBAAqB;AAG3B,MAAM,oCAAoC;AAG1C,MAAM,gCAAgC;AAEtC,MAAM,gCAAgC;AAGtC,MAAM,2BAA2B;AAGjC,MAAM,yCAAyC;AAG/C,MAAM,qCAAqC;AAG3C,MAAM,mCAAmC;AAMzC,MAAM,gCAAgC;AAStC,MAAM,4BAA4B;AAwBlC,MAAM,uCAAuC;AAO7C,MAAM,+BAA+B;AAQrC,MAAM,kCAAkC;AAGxC,MAAM,2BAA2B;AAUjC,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"runconfig-contract.cjs","sources":["../../../../../agent-runtime/src/generated/runconfig-contract.ts"],"sourcesContent":["// GENERATED FILE — DO NOT EDIT BY HAND.\n//\n// Source of truth (agora):\n// agora/agora/graphs/athena_deep_agent/run_config.py (_PARSED_CUSTOM_KEYS / _COMPANION_CUSTOM_KEYS / PER_SEND_CUSTOM_KEYS)\n// agora/agora/graphs/athena_deep_agent/thread_config.py (server config lane + config/* command names)\n// agora/agora/graphs/athena_deep_agent/session_asset.py (KNOWN_START_CHANNELS / DEEP_AGENT_RUNTIME_MARKER)\n// agora/agora/graphs/athena_deep_agent/client_tools.py (client-tool interrupt + result-envelope literals)\n// agora/agora/graphs/athena_deep_agent/protocol_version.py (wire-contract version negotiation)\n// agora/agora/graphs/athena_deep_agent/message_window.py (interest windows + history commands)\n// agora/agora/type_definitions/collab_agent.py (CAPABILITIES ladder: absent mode + new-agent default)\n//\n// Regenerate:\n// cd agora && mise exec -- infisical run --command 'uv run python scripts/export_runconfig_contract.py'\n//\n// CI verifies this file matches the Python source (agora-check runs the\n// exporter with --check), so hand edits and un-regenerated key changes fail.\n\n/** `runConfig.custom` keys parsed by agora's `parse_deep_agent_run_config`. */\nexport const RUN_CONFIG_PARSED_CUSTOM_KEYS = [\n \"agent_catalog_asset_ids\",\n \"approve_changes\",\n \"catalog_asset_ids\",\n \"channel_reply_turn\",\n \"coding_worker_asset_id\",\n \"coding_workers\",\n \"compiled_subagents\",\n \"declined_toolkit_ids\",\n \"drive_mounts\",\n \"enable_interpreter\",\n \"enable_persistent_fs\",\n \"enable_sandbox\",\n \"enable_skills\",\n \"enabled_tools\",\n \"environment\",\n \"environment_id\",\n \"environment_name\",\n \"excluded_middleware\",\n \"excluded_tools\",\n \"extra_middleware\",\n \"include_citation_instructions\",\n \"interpreter_max_ptc_calls\",\n \"interpreter_mode\",\n \"interpreter_ptc\",\n \"interpreter_ptc_exclusive\",\n \"interpreter_runtime\",\n \"interpreter_subagents\",\n \"interpreter_timeout_seconds\",\n \"interrupt_on\",\n \"knowledge_base\",\n \"mcp_server_configs\",\n \"mcp_servers\",\n \"memory\",\n \"outbound_approval_allowlist\",\n \"permissions\",\n \"pre_approved_tools\",\n \"project_id\",\n \"read_only\",\n \"recursion_limit\",\n \"run_label\",\n \"sandbox_runtime\",\n \"secret_asset_ids\",\n \"session_computer\",\n \"session_machine\",\n \"session_vm_retention\",\n \"skill_asset_ids\",\n \"skills\",\n \"subagents\",\n \"system_prompt\",\n \"tool_description_overrides\",\n \"voice_update_handle\",\n \"workbench\",\n] as const;\n\n/** `runConfig.custom` keys consumed by the surrounding deep-agent request machinery rather than the capability parser. */\nexport const RUN_CONFIG_COMPANION_CUSTOM_KEYS = [\n \"addressed_agents\",\n \"agent\",\n \"agent_available_toolkits\",\n \"allowed_tab_ids\",\n \"app_id\",\n \"channel\",\n \"channel_router\",\n \"client_tools\",\n \"collab_agent_id\",\n \"collab_channel_id\",\n \"collab_entry_channel_id\",\n \"custom_tool_configs\",\n \"deterministic\",\n \"device_id\",\n \"device_toolkits\",\n \"dry_run\",\n \"enabled_toolkits\",\n \"entry_point\",\n \"from_stored_config\",\n \"frontend_available\",\n \"generative_frame_inline\",\n \"github_identity\",\n \"max_tokens\",\n \"middleware\",\n \"model\",\n \"muses_enabled\",\n \"muses_recall_enabled\",\n \"office_context\",\n \"panel_config\",\n \"posthog_session_id\",\n \"run_budget\",\n \"runtime\",\n \"session_id\",\n \"session_origin_kind\",\n \"session_tab_id\",\n \"skip_title_generation\",\n \"source_aop_id\",\n \"start_channel\",\n \"structured_output\",\n \"temperature\",\n \"tool_limit_override\",\n \"trigger_type\",\n \"workspace_id\",\n] as const;\n\n/** Every `runConfig.custom` key some deep-agent request consumer reads. A key outside this set is invisible to the run and trips agora's unknown-key telemetry. */\nexport const RUN_CONFIG_CUSTOM_KEYS = [\n \"addressed_agents\",\n \"agent\",\n \"agent_available_toolkits\",\n \"agent_catalog_asset_ids\",\n \"allowed_tab_ids\",\n \"app_id\",\n \"approve_changes\",\n \"catalog_asset_ids\",\n \"channel\",\n \"channel_reply_turn\",\n \"channel_router\",\n \"client_tools\",\n \"coding_worker_asset_id\",\n \"coding_workers\",\n \"collab_agent_id\",\n \"collab_channel_id\",\n \"collab_entry_channel_id\",\n \"compiled_subagents\",\n \"custom_tool_configs\",\n \"declined_toolkit_ids\",\n \"deterministic\",\n \"device_id\",\n \"device_toolkits\",\n \"drive_mounts\",\n \"dry_run\",\n \"enable_interpreter\",\n \"enable_persistent_fs\",\n \"enable_sandbox\",\n \"enable_skills\",\n \"enabled_toolkits\",\n \"enabled_tools\",\n \"entry_point\",\n \"environment\",\n \"environment_id\",\n \"environment_name\",\n \"excluded_middleware\",\n \"excluded_tools\",\n \"extra_middleware\",\n \"from_stored_config\",\n \"frontend_available\",\n \"generative_frame_inline\",\n \"github_identity\",\n \"include_citation_instructions\",\n \"interpreter_max_ptc_calls\",\n \"interpreter_mode\",\n \"interpreter_ptc\",\n \"interpreter_ptc_exclusive\",\n \"interpreter_runtime\",\n \"interpreter_subagents\",\n \"interpreter_timeout_seconds\",\n \"interrupt_on\",\n \"knowledge_base\",\n \"max_tokens\",\n \"mcp_server_configs\",\n \"mcp_servers\",\n \"memory\",\n \"middleware\",\n \"model\",\n \"muses_enabled\",\n \"muses_recall_enabled\",\n \"office_context\",\n \"outbound_approval_allowlist\",\n \"panel_config\",\n \"permissions\",\n \"posthog_session_id\",\n \"pre_approved_tools\",\n \"project_id\",\n \"read_only\",\n \"recursion_limit\",\n \"run_budget\",\n \"run_label\",\n \"runtime\",\n \"sandbox_runtime\",\n \"secret_asset_ids\",\n \"session_computer\",\n \"session_id\",\n \"session_machine\",\n \"session_origin_kind\",\n \"session_tab_id\",\n \"session_vm_retention\",\n \"skill_asset_ids\",\n \"skills\",\n \"skip_title_generation\",\n \"source_aop_id\",\n \"start_channel\",\n \"structured_output\",\n \"subagents\",\n \"system_prompt\",\n \"temperature\",\n \"tool_description_overrides\",\n \"tool_limit_override\",\n \"trigger_type\",\n \"voice_update_handle\",\n \"workbench\",\n \"workspace_id\",\n] as const;\n\nexport type RunConfigCustomKey = (typeof RUN_CONFIG_CUSTOM_KEYS)[number];\n\n/** Fast membership checks for builder/test assertions. */\nexport const RUN_CONFIG_CUSTOM_KEY_SET: ReadonlySet<string> = new Set(\n RUN_CONFIG_CUSTOM_KEYS,\n);\n\n/** `runConfig.custom` keys a client still carries per send on a thread with server config; every other key is dropped at dispatch. */\nexport const RUN_CONFIG_PER_SEND_CUSTOM_KEYS = [\n \"addressed_agents\",\n \"agent\",\n \"agent_available_toolkits\",\n \"allowed_tab_ids\",\n \"app_id\",\n \"channel\",\n \"channel_reply_turn\",\n \"channel_router\",\n \"client_tools\",\n \"collab_channel_id\",\n \"collab_entry_channel_id\",\n \"deterministic\",\n \"device_id\",\n \"device_toolkits\",\n \"dry_run\",\n \"entry_point\",\n \"from_stored_config\",\n \"frontend_available\",\n \"generative_frame_inline\",\n \"github_identity\",\n \"muses_enabled\",\n \"muses_recall_enabled\",\n \"office_context\",\n \"posthog_session_id\",\n \"project_id\",\n \"read_only\",\n \"run_budget\",\n \"runtime\",\n \"session_id\",\n \"session_origin_kind\",\n \"session_tab_id\",\n \"skip_title_generation\",\n \"source_aop_id\",\n \"start_channel\",\n \"structured_output\",\n \"tool_limit_override\",\n \"trigger_type\",\n \"voice_update_handle\",\n \"workspace_id\",\n] as const;\n\nexport type RunConfigPerSendCustomKey =\n (typeof RUN_CONFIG_PER_SEND_CUSTOM_KEYS)[number];\n\n/** Fast membership checks for builder/test assertions. */\nexport const RUN_CONFIG_PER_SEND_CUSTOM_KEY_SET: ReadonlySet<string> = new Set(\n RUN_CONFIG_PER_SEND_CUSTOM_KEYS,\n);\n\n/** Keys the thread's server config lane owns — changed only through the `config/*` commands, never per send. */\nexport const THREAD_CONFIG_CUSTOM_KEYS = [\n \"agent_catalog_asset_ids\",\n \"approve_changes\",\n \"catalog_asset_ids\",\n \"coding_worker_asset_id\",\n \"coding_workers\",\n \"collab_agent_id\",\n \"compiled_subagents\",\n \"custom_tool_configs\",\n \"declined_toolkit_ids\",\n \"drive_mounts\",\n \"enable_interpreter\",\n \"enable_persistent_fs\",\n \"enable_sandbox\",\n \"enable_skills\",\n \"enabled_toolkits\",\n \"enabled_tools\",\n \"environment\",\n \"environment_id\",\n \"environment_name\",\n \"excluded_middleware\",\n \"excluded_tools\",\n \"extra_middleware\",\n \"include_citation_instructions\",\n \"interpreter_max_ptc_calls\",\n \"interpreter_mode\",\n \"interpreter_ptc\",\n \"interpreter_ptc_exclusive\",\n \"interpreter_runtime\",\n \"interpreter_subagents\",\n \"interpreter_timeout_seconds\",\n \"interrupt_on\",\n \"knowledge_base\",\n \"max_tokens\",\n \"mcp_server_configs\",\n \"mcp_servers\",\n \"memory\",\n \"middleware\",\n \"model\",\n \"outbound_approval_allowlist\",\n \"permissions\",\n \"pre_approved_tools\",\n \"recursion_limit\",\n \"run_label\",\n \"sandbox_runtime\",\n \"secret_asset_ids\",\n \"session_computer\",\n \"session_machine\",\n \"session_vm_retention\",\n \"skill_asset_ids\",\n \"skills\",\n \"subagents\",\n \"system_prompt\",\n \"temperature\",\n \"tool_description_overrides\",\n \"workbench\",\n] as const;\n\nexport type ThreadConfigCustomKey = (typeof THREAD_CONFIG_CUSTOM_KEYS)[number];\n\n/** Fast membership checks for builder/test assertions. */\nexport const THREAD_CONFIG_CUSTOM_KEY_SET: ReadonlySet<string> = new Set(\n THREAD_CONFIG_CUSTOM_KEYS,\n);\n\n/** Replicated-state key of the server config lane (`{ version, custom }`). */\nexport const DEEP_AGENT_CONFIG_STATE_KEY = \"config\";\n\n/** The statewire commands that mutate the server config lane. */\nexport const DEEP_AGENT_CONFIG_COMMANDS = {\n patch: \"config/patch\",\n toolsEnable: \"config/tools/enable\",\n toolsDisable: \"config/tools/disable\",\n} as const;\n\n/** `start_channel` values the session substrate stamps as provenance; anything else clamps to \"web\". */\nexport const KNOWN_START_CHANNELS = [\n \"agent_orchestration\",\n \"api\",\n \"automation\",\n \"chrome_extension\",\n \"cli\",\n \"comment_agent\",\n \"default_voice\",\n \"desktop_app\",\n \"email\",\n \"meetings\",\n \"mobile_app\",\n \"mobile_app_voice\",\n \"office_addin\",\n \"orchestration\",\n \"programmatic\",\n \"slack\",\n \"sms\",\n \"task\",\n \"teams\",\n \"voice\",\n \"voice_memo\",\n \"web\",\n] as const;\n\nexport type KnownStartChannel = (typeof KNOWN_START_CHANNELS)[number];\n\n/** Fast membership checks for builder/test assertions. */\nexport const KNOWN_START_CHANNEL_SET: ReadonlySet<string> = new Set(\n KNOWN_START_CHANNELS,\n);\n\n/** `runConfig.custom.runtime` marker selecting the deep-agent runtime. */\nexport const DEEP_AGENT_RUNTIME_MARKER = \"athena_deep_agent\";\n\n/**\n * Collab-agent capability ladder (agent schema v3): per explicit\n * capability field, what an ABSENT value means and the value stamped on\n * a new agent. Resolved by agora's `capability_decoder` and the one agent\n * compiler on every run: `passthrough` — explicit only, absent means off;\n * `off` — absent means off under every `runtime` marker; `runtime` —\n * absent derives from the `runtime` marker (`athena_deep_agent` on, any\n * other or missing marker off).\n */\nexport const COLLAB_AGENT_CAPABILITIES = {\n deepAgentBuiltinsEnabled: { absent: \"runtime\", default: true },\n interpreterEnabled: { absent: \"off\", default: false },\n sandboxEnabled: { absent: \"passthrough\", default: false },\n skillsEnabled: { absent: \"runtime\", default: true },\n} as const;\n\nexport type CollabAgentCapabilityField = keyof typeof COLLAB_AGENT_CAPABILITIES;\n\nexport type CollabAgentCapabilityAbsentMode =\n (typeof COLLAB_AGENT_CAPABILITIES)[CollabAgentCapabilityField][\"absent\"];\n\n/** `source`/`type` stamped on client-tool interrupt payloads by agora. */\nexport const CLIENT_TOOL_INTERRUPT_SOURCE = \"client_tool\";\n\n/** `status` literals of the result envelope a client resumes a parked client-tool call with. */\nexport const CLIENT_TOOL_RESULT_STATUSES = [\"error\", \"success\"] as const;\n\nexport type ClientToolResultStatus =\n (typeof CLIENT_TOOL_RESULT_STATUSES)[number];\n\nexport const CLIENT_TOOL_RESULT_STATUS_SUCCESS = \"success\";\n\nexport const CLIENT_TOOL_RESULT_STATUS_ERROR = \"error\";\n\n/**\n * Result envelope a client resumes a parked client-tool call with,\n * keyed by interrupt id:\n * `{ client_tool_results: { <interrupt_id>: <envelope> } }`.\n * Agora relays the envelope to the model verbatim.\n */\nexport type ClientToolResultEnvelopeContract =\n | { status: typeof CLIENT_TOOL_RESULT_STATUS_SUCCESS; result: unknown }\n | { status: typeof CLIENT_TOOL_RESULT_STATUS_ERROR; error: string };\n\n/**\n * The deep-agent wire-contract version this client build speaks,\n * declared on every attach. The host records it for attach telemetry\n * and per-version behaviour; it has no minimum client version, so no\n * build is refused for the version it declares (the `protocol` state\n * lane's `minClientVersion` is the constant 1).\n */\nexport const DEEP_AGENT_PROTOCOL_VERSION = 2;\n\n/**\n * The first contract version whose host a client states `follow` to (a\n * subagent lane's steps, each its own document): a client follows a\n * lane only on a host whose `protocol` lane advertises at least this\n * version. A host that predates `follow` refuses it with\n * `invalid-interest`.\n */\nexport const DEEP_AGENT_LANE_FOLLOW_PROTOCOL_VERSION = 2;\n\n/** Attach header carrying the client's declared contract version. */\nexport const DEEP_AGENT_PROTOCOL_VERSION_HEADER =\n \"x-athena-deep-agent-protocol-version\";\n\n/** Attach header declaring the head window a fresh client wants in its hello (host-clamped). */\nexport const DEEP_AGENT_MESSAGE_WINDOW_HEADER = \"x-athena-deep-agent-window\";\n\n/**\n * Attach header carrying the view a re-attaching client holds (JSON:\n * requests, head floor, lane floors): its hello carries that view on\n * any host instance.\n */\nexport const DEEP_AGENT_MESSAGE_INTERESTS_HEADER =\n \"x-athena-deep-agent-interests\";\n\n/** The largest interests header the host reads; larger is undeclared. */\nexport const DEEP_AGENT_MAX_MESSAGE_INTERESTS_HEADER_BYTES = 8192;\n\n/** Replicated-state key of the server-advertised version lane. */\nexport const DEEP_AGENT_PROTOCOL_STATE_KEY = \"protocol\";\n\n/** Ephemeral subprotocol carrying a client's message-window interests. */\nexport const DEEP_AGENT_INTEREST_PROTOCOL = \"athena/interest\";\n\n/** Ephemeral subprotocol carrying a client's synced context document. */\nexport const DEEP_AGENT_CONTEXT_PROTOCOL = \"athena/context\";\n\n/** The only interest namespace the host resolves (the linear transcript). */\nexport const DEEP_AGENT_MAIN_NS = \"main\";\n\n/** Window size (interest `before`) a client asks for by default. */\nexport const DEEP_AGENT_DEFAULT_MESSAGE_WINDOW = 40;\n\n/** Bounds on a window size. */\nexport const DEEP_AGENT_MIN_MESSAGE_WINDOW = 8;\n\nexport const DEEP_AGENT_MAX_MESSAGE_WINDOW = 200;\n\n/** Interests one attach may hold at once (the head plus its pages). */\nexport const DEEP_AGENT_MAX_INTERESTS = 16;\n\n/**\n * Rejection code of an interest `set` whose windows resolve past the\n * attach's interest document budget: the view is as deep as one attach holds.\n */\nexport const DEEP_AGENT_OVERSIZED_INTEREST_CODE = \"oversized-interest\";\n\n/** Command returning a truncated tool output whole. */\nexport const DEEP_AGENT_HISTORY_TOOL_OUTPUT_COMMAND = \"history/tool_output\";\n\n/** Command returning one stored message whole (provenance and full tool output included). */\nexport const DEEP_AGENT_HISTORY_MESSAGE_COMMAND = \"history/message\";\n\n/** Wire key marking a tool message whose content was truncated. */\nexport const DEEP_AGENT_TRUNCATED_CONTENT_KEY = \"athena_content_truncated\";\n\n/**\n * Wire key on a running `task` card whose nested transcript rides cut to its\n * newest steps: `{ messages, tool_calls }` over the whole stored transcript.\n */\nexport const DEEP_AGENT_TRUNCATED_LANE_KEY = \"athena_lane_truncated\";\n\n/**\n * Wire key on a `task` card, and on an in-eval lane's `ptc_subagents` entry,\n * carrying the whole lane's token use however much of the lane the wire\n * carries: `{ input_tokens, output_tokens, cache_read_input_tokens,\n * cache_creation_input_tokens }`, the input counting its cache reads and\n * writes. Absent while the lane's steps report no usage.\n */\nexport const DEEP_AGENT_LANE_USAGE_KEY = \"athena_lane_usage\";\n\n/**\n * The newest nested messages a cut card carries whole; the entries ahead\n * of them are the older assistant turns that requested results among\n * them, cut to those calls.\n */\nexport const DEEP_AGENT_RUNNING_LANE_WIRE_MESSAGES = 8;\n\n/**\n * Key of a followed lane's window (`follows[ns]` on a resolution whose\n * request added `follow: {before}`) naming the `task` call whose card\n * holds the lane.\n */\nexport const DEEP_AGENT_FOLLOW_TOOL_CALL_ID_KEY = \"toolCallId\";\n\n/** The most lane steps one attach follows, across every lane. */\nexport const DEEP_AGENT_MAX_FOLLOWED_STEPS = 200;\n\n/**\n * The first contract version a client declares to see a finished card cut\n * like a running one (and to follow lanes and page them through\n * `history/lane`). Below it, or declaring nothing, finished cards ride whole.\n */\nexport const DEEP_AGENT_LANE_CUT_PROTOCOL_VERSION = 2;\n\n/**\n * Last element of the key a cut finished card's document rides under:\n * `[threadId, \"main\", messageId, \"cut\"]`. A view holds that key or the\n * card's own, never both.\n */\nexport const DEEP_AGENT_CUT_LANE_DOCUMENT = \"cut\";\n\n/**\n * Command returning one page of a card's nested transcript, oldest first:\n * `{ messageId, before, at? }` answers\n * `{ messageId, toolCallId, ns, steps, more: { before }, total }`; the page\n * holds the newest `before` entries, or those strictly older than `at`.\n */\nexport const DEEP_AGENT_HISTORY_LANE_COMMAND = \"history/lane\";\n\n/** The most entries one `history/lane` page asks for. */\nexport const DEEP_AGENT_MAX_LANE_PAGE = 200;\n\n/** The most encoded characters one `history/lane` page carries (at least one entry). */\nexport const DEEP_AGENT_HISTORY_LANE_PAGE_CHARS = 1048576;\n\n/**\n * Set on the last step of a cut finished card whose text is the card's own\n * `content` (the subagent's report): the step rides with empty content, and\n * the card's `content` is its text.\n */\nexport const DEEP_AGENT_REPEATS_RESULT_KEY = \"athena_content_repeats_result\";\n\n/** Most inline-image payload characters one message carries whole on the wire. */\nexport const DEEP_AGENT_INLINE_IMAGE_WIRE_BUDGET = 4194304;\n\n/** Wire key on an image block left off the wire: `{ index, chars, mediaType }`. */\nexport const DEEP_AGENT_OMITTED_IMAGE_KEY = \"athena_image_omitted\";\n\n/** The image an omitted block carries instead of its own (a neutral PNG tile). */\nexport const DEEP_AGENT_OMITTED_IMAGE_PLACEHOLDER_URL =\n \"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKAAAAB4AQMAAABPbGssAAAABlBMVEXi6PCUo7jao11HAAAA6ElEQVR42u2UyW3DMBBF3wxogEd2EJbCElKQDRCwC3MpSRc5eLuYokgNLEUxctK/CHyanQts2vRO3QdlALVsXsBvecqxxr1ob0A5GlDJU+hICxN54p/qXAx/+FpoeeE8hTerzfvByn7ifzpaBtWCOwv6bMVMBgzRgNGKmUL9McDs4XOSyEHuoKCI76AiqOugg+y0gx6SN+YQg3QwALGk19pQSKV/reOocyoww27oU5sxhAbKUNgIqrVxrvnovJ80MFgxYy23wtTss44tmL+bAuOE2p2o0fJa3iW/6iR/lEfx8kv3TZtW6AFk5Sf3k+GTswAAAABJRU5ErkJggg==\";\n\n/**\n * Command returning one inline image of a stored message in chunks:\n * `{ messageId, index, offset? }` answers\n * `{ messageId, index, mediaType, offset, total, chunk, next }`; the\n * chunks joined in order are the image's `data:` URL, and `next` is\n * the offset to ask for next (`null` after the last chunk).\n */\nexport const DEEP_AGENT_HISTORY_IMAGE_COMMAND = \"history/image\";\n\n/**\n * Command returning one inline image of a lane step in chunks, as\n * `history/image` does a stored message's: `{ messageId | lane, step,\n * index, offset? }` answers `{ messageId, lane, step, index, mediaType,\n * offset, total, chunk, next }`, with `messageId` null for an in-eval\n * lane and `lane` null for a card.\n */\nexport const DEEP_AGENT_HISTORY_LANE_IMAGE_COMMAND = \"history/lane_image\";\n"],"names":[],"mappings":";;AAyHO,MAAM,yBAAyB;AAAA,EACpC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAK8D,IAAI;AAAA,EAChE;AACF;AAGO,MAAM,kCAAkC;AAAA,EAC7C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAMuE,IAAI;AAAA,EACzE;AACF;AAGO,MAAM,4BAA4B;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAKiE,IAAI;AAAA,EACnE;AACF;AAMO,MAAM,6BAA6B;AAAA,EACxC,OAAO;AAAA,EACP,aAAa;AAAA,EACb,cAAc;AAChB;AAGO,MAAM,uBAAuB;AAAA,EAClC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAK4D,IAAI;AAAA,EAC9D;AACF;AA2BO,MAAM,+BAA+B;AAQrC,MAAM,oCAAoC;AAE1C,MAAM,kCAAkC;AA+BxC,MAAM,qCACX;AAGK,MAAM,mCAAmC;AAOzC,MAAM,sCACX;AAGK,MAAM,gDAAgD;AAGtD,MAAM,gCAAgC;AAGtC,MAAM,+BAA+B;AAMrC,MAAM,qBAAqB;AAG3B,MAAM,oCAAoC;AAG1C,MAAM,gCAAgC;AAEtC,MAAM,gCAAgC;AAGtC,MAAM,2BAA2B;AAMjC,MAAM,qCAAqC;AAG3C,MAAM,yCAAyC;AAG/C,MAAM,qCAAqC;AAG3C,MAAM,mCAAmC;AAMzC,MAAM,gCAAgC;AAStC,MAAM,4BAA4B;AAwBlC,MAAM,uCAAuC;AAO7C,MAAM,+BAA+B;AAQrC,MAAM,kCAAkC;AAGxC,MAAM,2BAA2B;AAUjC,MAAM,gCAAgC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}