@athenaintel/react 0.55.0 → 0.56.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 (90) hide show
  1. package/README.md +13 -0
  2. package/dist/agent-runtime/src/answer-label.cjs +8 -2
  3. package/dist/agent-runtime/src/answer-label.cjs.map +1 -1
  4. package/dist/agent-runtime/src/answer-label.d.ts +10 -4
  5. package/dist/agent-runtime/src/answer-label.js +8 -2
  6. package/dist/agent-runtime/src/answer-label.js.map +1 -1
  7. package/dist/agent-runtime/src/deep-agent-transport-recipe.cjs +6 -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.js +6 -3
  10. package/dist/agent-runtime/src/deep-agent-transport-recipe.js.map +1 -1
  11. package/dist/agent-runtime/src/edit-command.cjs +40 -19
  12. package/dist/agent-runtime/src/edit-command.cjs.map +1 -1
  13. package/dist/agent-runtime/src/edit-command.d.ts +2 -0
  14. package/dist/agent-runtime/src/edit-command.js +41 -20
  15. package/dist/agent-runtime/src/edit-command.js.map +1 -1
  16. package/dist/agent-runtime/src/generated/runconfig-contract.cjs +8 -0
  17. package/dist/agent-runtime/src/generated/runconfig-contract.cjs.map +1 -1
  18. package/dist/agent-runtime/src/generated/runconfig-contract.d.ts +9 -0
  19. package/dist/agent-runtime/src/generated/runconfig-contract.js +8 -0
  20. package/dist/agent-runtime/src/generated/runconfig-contract.js.map +1 -1
  21. package/dist/agent-runtime/src/history-store.cjs +426 -0
  22. package/dist/agent-runtime/src/history-store.cjs.map +1 -0
  23. package/dist/agent-runtime/src/history-store.d.ts +282 -0
  24. package/dist/agent-runtime/src/history-store.js +426 -0
  25. package/dist/agent-runtime/src/history-store.js.map +1 -0
  26. package/dist/agent-runtime/src/index.d.ts +4 -4
  27. package/dist/agent-runtime/src/message-window.cjs +43 -5
  28. package/dist/agent-runtime/src/message-window.cjs.map +1 -1
  29. package/dist/agent-runtime/src/message-window.d.ts +26 -2
  30. package/dist/agent-runtime/src/message-window.js +44 -6
  31. package/dist/agent-runtime/src/message-window.js.map +1 -1
  32. package/dist/agent-runtime/src/offline-status.cjs.map +1 -1
  33. package/dist/agent-runtime/src/offline-status.d.ts +85 -4
  34. package/dist/agent-runtime/src/offline-status.js.map +1 -1
  35. package/dist/agent-runtime/src/runtime.d.ts +1 -0
  36. package/dist/agent-runtime/src/tool-metadata.cjs +8 -0
  37. package/dist/agent-runtime/src/tool-metadata.cjs.map +1 -1
  38. package/dist/agent-runtime/src/tool-metadata.js +8 -0
  39. package/dist/agent-runtime/src/tool-metadata.js.map +1 -1
  40. package/dist/agent-runtime/src/use-deep-agent-thread.cjs +8 -16
  41. package/dist/agent-runtime/src/use-deep-agent-thread.cjs.map +1 -1
  42. package/dist/agent-runtime/src/use-deep-agent-thread.d.ts +1 -9
  43. package/dist/agent-runtime/src/use-deep-agent-thread.js +9 -17
  44. package/dist/agent-runtime/src/use-deep-agent-thread.js.map +1 -1
  45. package/dist/agent-runtime/src/use-deep-agent-window-sync.cjs +86 -79
  46. package/dist/agent-runtime/src/use-deep-agent-window-sync.cjs.map +1 -1
  47. package/dist/agent-runtime/src/use-deep-agent-window-sync.d.ts +2 -27
  48. package/dist/agent-runtime/src/use-deep-agent-window-sync.js +89 -82
  49. package/dist/agent-runtime/src/use-deep-agent-window-sync.js.map +1 -1
  50. package/dist/chat/super-grouping/CollapsibleGroup.cjs +1 -1
  51. package/dist/chat/super-grouping/CollapsibleGroup.cjs.map +1 -1
  52. package/dist/chat/super-grouping/CollapsibleGroup.d.ts +6 -5
  53. package/dist/chat/super-grouping/CollapsibleGroup.js +1 -1
  54. package/dist/chat/super-grouping/CollapsibleGroup.js.map +1 -1
  55. package/dist/chat/super-grouping/earlier-steps-button.cjs +5 -6
  56. package/dist/chat/super-grouping/earlier-steps-button.cjs.map +1 -1
  57. package/dist/chat/super-grouping/earlier-steps-button.d.ts +6 -6
  58. package/dist/chat/super-grouping/earlier-steps-button.js +5 -6
  59. package/dist/chat/super-grouping/earlier-steps-button.js.map +1 -1
  60. package/dist/chat/super-grouping/toolkit-map.cjs +1 -0
  61. package/dist/chat/super-grouping/toolkit-map.cjs.map +1 -1
  62. package/dist/chat/super-grouping/toolkit-map.js +1 -0
  63. package/dist/chat/super-grouping/toolkit-map.js.map +1 -1
  64. package/dist/chat/super-grouping/use-turn-steps.cjs +3 -3
  65. package/dist/chat/super-grouping/use-turn-steps.js +1 -1
  66. package/dist/chat-ui/thread/statewire-history-edge.cjs +0 -4
  67. package/dist/chat-ui/thread/statewire-history-edge.cjs.map +1 -1
  68. package/dist/chat-ui/thread/statewire-history-edge.d.ts +5 -7
  69. package/dist/chat-ui/thread/statewire-history-edge.js +1 -5
  70. package/dist/chat-ui/thread/statewire-history-edge.js.map +1 -1
  71. package/dist/provider/AthenaProvider.cjs +12 -11
  72. package/dist/provider/AthenaProvider.cjs.map +1 -1
  73. package/dist/provider/AthenaProvider.js +11 -10
  74. package/dist/provider/AthenaProvider.js.map +1 -1
  75. package/dist/provider/statewire-window-context.cjs.map +1 -1
  76. package/dist/provider/statewire-window-context.d.ts +8 -8
  77. package/dist/provider/statewire-window-context.js.map +1 -1
  78. package/dist/react/package.json.cjs +1 -1
  79. package/dist/react/package.json.js +1 -1
  80. package/dist/runtime/useAthenaStatewireRuntime.cjs +0 -2
  81. package/dist/runtime/useAthenaStatewireRuntime.cjs.map +1 -1
  82. package/dist/runtime/useAthenaStatewireRuntime.d.ts +5 -5
  83. package/dist/runtime/useAthenaStatewireRuntime.js +0 -2
  84. package/dist/runtime/useAthenaStatewireRuntime.js.map +1 -1
  85. package/package.json +1 -1
  86. package/dist/agent-runtime/src/history-pages.cjs +0 -279
  87. package/dist/agent-runtime/src/history-pages.cjs.map +0 -1
  88. package/dist/agent-runtime/src/history-pages.d.ts +0 -252
  89. package/dist/agent-runtime/src/history-pages.js +0 -279
  90. package/dist/agent-runtime/src/history-pages.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"useAthenaStatewireRuntime.cjs","sources":["../../src/runtime/useAthenaStatewireRuntime.ts"],"sourcesContent":["import type { AssistantClient, Toolkit } from '@assistant-ui/react';\nimport { Tools, useAui } from '@assistant-ui/react';\nimport {\n createSubagentTranscriptConversionCache,\n DEEP_AGENT_DEFAULT_MESSAGE_WINDOW,\n type DeepAgentHistoryStore,\n type DeepAgentMessageWindowDeclaration,\n type DeepAgentStreamValues,\n type DeepAgentThreadElement,\n type DeepAgentThreadSnapshotCache,\n type DeepAgentToolOutputStore,\n isDeepAgentHostState,\n isStatewireChannelTeardown,\n logUnhandledStatewireError,\n type RegisteredClientTool,\n useDeepAgentRuntime,\n type UseDeepAgentThreadOptions,\n withStagedComposerMarkdown,\n} from '@athenaintel/agent-runtime';\nimport { useContext, useMemo, useRef } from 'react';\nimport { AthenaAuthContext } from '../auth/AthenaAuthContext';\nimport {\n collectStatewireClientTools,\n statewireClientToolWireEntries,\n} from '../chat/statewire-client-tools';\nimport { athenaDiagnostics } from '../diagnostics/athena-diagnostics';\nimport {\n type AthenaStatewireTokenGetter,\n resolveStatewireAuthHeaders,\n} from './statewire-auth-headers';\nimport { statewireSessionKey, statewireSessionPrincipal } from './statewire-session-key';\n\ntype AthenaDiagnosticsSpanStarter = typeof athenaDiagnostics.span;\nimport {\n buildStatewireRunConfig,\n DEFAULT_STATEWIRE_MODEL,\n resolveAgentProp,\n} from './statewire-run-config';\n\nexport { DEFAULT_STATEWIRE_MODEL };\n\n/**\n * The head interest every SDK attach states (`athena/interest`): the host\n * mounts the transcript's tail as message documents instead of every message\n * — megabytes on long threads, over the 1 MiB frame limit of stock websocket\n * clients. Older pages load from the `StatewireHistoryEdge` row the chat UI\n * mounts above the messages, and cut tool outputs are fetched back for the\n * cards that show them.\n */\nexport const ATHENA_SDK_MESSAGE_WINDOW: DeepAgentMessageWindowDeclaration = {\n size: DEEP_AGENT_DEFAULT_MESSAGE_WINDOW,\n};\n\nexport interface AthenaStatewireRuntimeConfig {\n /** Base URL of the statewire sync host (the `…/v2/threads` mount). */\n syncUrl: string;\n /** Thread ID the statewire session attaches to. */\n threadId: string;\n /** True only for a never-started local chat. Existing (or pre-assigned)\n * threads load until their server snapshot arrives. */\n isNewChat?: boolean;\n /** API key for authentication. Used when no auth token is provided. */\n apiKey?: string;\n /** Auth token. Takes priority over apiKey. */\n token?: string | null;\n /** Resolve the latest token immediately before a request (for expiring\n * clients). Called with `{ force: true }` right after the host refused the\n * previous credential (the transport's `staleAuth`), so a caching getter\n * mints a fresh token instead of returning the refused one. */\n getToken?: AthenaStatewireTokenGetter;\n /**\n * Per-provider LRU of each thread's last wire state. A switch back to a\n * remembered thread mounts with that snapshot and projects ready on the\n * first frame instead of a loading treatment; the attach snapshot then\n * replaces it. Owned above the per-thread mount so it survives switches.\n */\n snapshotCache?: DeepAgentThreadSnapshotCache;\n /** The head interest stated on the attach (see {@link ATHENA_SDK_MESSAGE_WINDOW}, the default). */\n messageWindow?: DeepAgentMessageWindowDeclaration;\n /**\n * Whether the chat this runtime serves loads a subagent lane's earlier steps\n * on request, as `AthenaChat`'s subagent card does (\"Load earlier steps\").\n * When true, its attaches declare the deep-agent lane-cut contract\n * (protocol 2): the host sends a finished subagent's card cut to its newest\n * steps, as it sends a running one, and the card reads the rest. Default\n * `false`, so a chat that does not page lanes declares the default contract\n * and finished lanes arrive whole; a host whose `AthenaChat` renders every\n * `task` call in the subagent card turns it on through `AthenaProvider`'s\n * `subagentLaneHistory`. Read once per attach.\n */\n subagentLaneHistory?: boolean;\n /**\n * Full tool outputs fetched back for a windowed wire's cut tool messages;\n * the thread re-converts when one lands. `AthenaProvider` owns one per\n * provider and hands the same store to `StatewireHistoryEdge`.\n */\n toolOutputs?: DeepAgentToolOutputStore;\n /**\n * Older turns paged by command (`history/page`, protocol 3), joined in front\n * of the live window; `AthenaProvider` owns one and hands the same store to\n * `StatewireHistoryEdge`, which pages into it.\n */\n historyPages?: DeepAgentHistoryStore;\n /** LLM model identifier. Defaults to the deep-agent default model. */\n model?: string;\n /** Agent selector: only `collab_agent:<asset_id>` refs are accepted (the run\n * executes AS that published collab agent). Any other non-empty value\n * throws — see `resolveAgentProp`. */\n agent?: string;\n /** Collab-agent channel id selecting that channel's overrides. */\n channel?: string;\n /** The agent's mode picked for this thread (`AthenaProvider` `modes`). */\n mode?: string;\n /** Backend toolkit IDs to enable. */\n tools?: string[];\n /** Frontend tool IDs to include in enabled_tools. */\n frontendToolIds?: string[];\n /** Frontend tools registered on the assistant client. Tools with a local\n * `execute` are also declared as `client_tools` and executed through the\n * statewire client-tool bridge. */\n frontendToolkit?: Toolkit;\n /** Asset IDs to include in the workbench. */\n workbench?: string[];\n /** Knowledge base IDs for RAG context. */\n knowledgeBase?: string[];\n /** System prompt override. */\n systemPrompt?: string;\n /** Client app identifier for session filtering. Sent as app_id in runConfig.custom. */\n appId?: string;\n /** Additional fields merged into runConfig.custom. */\n extraRunConfig?: Record<string, unknown>;\n /** Called on statewire transport errors (send rejections, stream failures). */\n onError?: (error: Error) => void;\n /** Projected connection status changes (deduped; null on unmount). */\n onConnectionChange?: UseDeepAgentThreadOptions['onConnectionChange'];\n /** Raw connection observer — carries the transport's reconnect handle. */\n onRawConnectionChange?: UseDeepAgentThreadOptions['onRawConnectionChange'];\n /** Notified when a run starts/stops. */\n onRunningChange?: UseDeepAgentThreadOptions['onRunningChange'];\n /** Core's paired session-asset existence verdict, including remembered/unknown state. */\n onSessionPersistedChange?: UseDeepAgentThreadOptions['onSessionPersistedChange'];\n /** Every statewire command-lifecycle update (the chat outbox lets a handed-over message go on it). */\n onCommandChange?: UseDeepAgentThreadOptions['onCommandChange'];\n /**\n * Observes the host's own state: called with the attach snapshot and then on\n * every later frame (`isDeepAgentHostState`) — never with the placeholder or\n * remembered snapshot a thread renders before its snapshot applies, which\n * can be after the connection reports `connected`. Called per streamed\n * token, so keep it cheap.\n */\n onServerState?: (state: DeepAgentStreamValues) => void;\n}\n\nconst EMPTY_TOOLKIT: Toolkit = {};\nconst EMPTY_TOOL_IDS: string[] = [];\n\n/** The client tools derived from the runtime's frontend toolkit — exposed so\n * the provider can mount the client-tool bridge with the same set. */\nexport function useStatewireClientTools(\n frontendToolkit: Toolkit | undefined,\n): RegisteredClientTool[] {\n return useMemo(\n () => collectStatewireClientTools(frontendToolkit ?? EMPTY_TOOLKIT),\n [frontendToolkit],\n );\n}\n\n/**\n * Statewire runtime for the Athena SDK — a thin shim over the shared\n * `@athenaintel/agent-runtime` `useDeepAgentRuntime`: it attaches to the\n * agora-hosted deep-agent thread at `${syncUrl}/${threadId}` and returns the\n * `AssistantClient` to mount via `AuiProvider` — the same integration shape as\n * the Olympus, Chrome extension, Office, and mobile statewire hosts.\n *\n * Auth: a token (resolved live through `getToken` when provided) rides\n * `Authorization: Bearer`, and an API key falls back to `X-API-KEY` — both\n * accepted by the statewire host.\n */\nexport function useAthenaStatewireRuntime(\n config: AthenaStatewireRuntimeConfig,\n): AssistantClient {\n const {\n syncUrl,\n threadId,\n isNewChat = false,\n apiKey,\n token,\n getToken,\n model,\n agent,\n channel,\n mode,\n tools = EMPTY_TOOL_IDS,\n frontendToolIds = EMPTY_TOOL_IDS,\n frontendToolkit = EMPTY_TOOLKIT,\n workbench,\n knowledgeBase,\n systemPrompt,\n appId,\n extraRunConfig,\n snapshotCache,\n messageWindow = ATHENA_SDK_MESSAGE_WINDOW,\n subagentLaneHistory = false,\n toolOutputs,\n historyPages,\n onError,\n onConnectionChange,\n onRawConnectionChange,\n onRunningChange,\n onSessionPersistedChange,\n onCommandChange,\n onServerState,\n } = config;\n\n // Fail loud at mount, not at first send: the statewire host always runs the\n // Athena deep agent, so an `agent` outside the collab_agent namespace can\n // never apply. Throwing here (render time) is what makes a misconfigured\n // integration visible instead of quietly answering as the wrong agent.\n resolveAgentProp({ agent });\n\n const clientTools = useStatewireClientTools(frontendToolkit);\n\n // The persisted command lane is keyed by WHO is signed in as well as by host\n // and thread (see `statewireSessionKey`); `null` while the sign-in provider\n // above is still resolving who that is.\n const principal = statewireSessionPrincipal(useContext(AthenaAuthContext));\n\n // Attach → first server snapshot span, keyed per thread attach.\n const attachSpanRef = useRef<ReturnType<AthenaDiagnosticsSpanStarter> | null>(null);\n const attachThreadRef = useRef<string | null>(null);\n if (attachThreadRef.current !== threadId) {\n attachThreadRef.current = threadId;\n attachSpanRef.current = athenaDiagnostics.span(\n `statewire.attach:${threadId}`,\n 'statewire.attach.start',\n { thread_id: threadId, is_new_chat: isNewChat },\n );\n }\n\n // Built every render so its JSON signature can key the model-context\n // registration below: consumers commonly pass fresh array literals per\n // render, which must not thrash registration, while a changed value (a new\n // `model`, channel, tool list, system prompt, …) must re-sync the context\n // before the next send. The core pulls this value only on model-context\n // notifications, which a key change triggers.\n const runConfigValue = buildStatewireRunConfig({\n model,\n agent,\n channel,\n mode,\n tools,\n frontendToolIds,\n workbench,\n knowledgeBase,\n systemPrompt,\n appId,\n extraRunConfig,\n clientTools: statewireClientToolWireEntries(clientTools),\n });\n const runConfigKey = JSON.stringify(runConfigValue);\n\n const auiTools = useMemo(() => Tools({ toolkit: frontendToolkit }), [frontendToolkit]);\n // Web client for the shared runtime core (a `use*` name so the\n // rules-of-hooks lint sees the `useAui` call inside a custom hook; the core\n // invokes it unconditionally every render).\n const useSdkClient = (thread: DeepAgentThreadElement) => useAui({ thread, tools: auiTools });\n\n return useDeepAgentRuntime({\n surface: 'AthenaSDK',\n threadId,\n baseUrl: syncUrl,\n // Option closures are re-read per render by the core, so credential\n // rotation (new `token`/`getToken`/`apiKey` props) reaches the next\n // request without remounting the thread. The transport's `staleAuth`\n // (true right after a refused credential) is forwarded as `force`.\n headers: (ctx) => resolveStatewireAuthHeaders({ apiKey, token, getToken }, ctx),\n isNewChat,\n // Queued entries render in the SDK's queue panel, so only the steer lane\n // projects into the message tail.\n laneProjection: 'steer-only',\n // Durable session: a reload resumes the lane and resends whatever the\n // server has not marked durable. Scoped by host AND principal — a thread\n // id is only meaningful against the backend that minted it, and a stored\n // lane must never resend against another signed-in user. (Consumers\n // server-render this SDK; the core's availability probe keeps those\n // sessions process-local, as before the seam existed.) Until the sign-in\n // provider knows who is signed in, the lane is pending: the transport\n // stays parked and nothing is mounted on a stand-in key\n // (`statewireSessionPrincipal`). A change to another principal remounts\n // the conversation on that principal's lane instead of moving this one\n // there (the runtime's lane epoch), so the previous principal's\n // undelivered commands are never sent as the new one.\n session:\n principal === null\n ? { kind: 'pending' }\n : {\n kind: 'local-storage',\n key: (id) => statewireSessionKey({ syncUrl, principal, threadId: id }),\n },\n snapshotCache,\n // Head interest (see `ATHENA_SDK_MESSAGE_WINDOW`): the tail of the\n // transcript instead of every message; the chat UI's history edge pages\n // older ranges in and fetches cut tool outputs into `toolOutputs`.\n messageWindow,\n toolOutputs,\n historyStore: historyPages,\n // Each `task` card's nested transcript becomes its tool-call part's\n // `messages` (assistant-ui's nested-thread channel), which the subagent\n // card (`SubagentTaskToolUI`) shows.\n createConversionCache: createSubagentTranscriptConversionCache,\n // The lane-cut contract only where the chat pages lanes (see `subagentLaneHistory`).\n laneHistory: subagentLaneHistory,\n capabilities: { edit: true, reload: true, continue: true },\n // The composer stages the draft each send came from right before it\n // sends; the message carries it as its composer markdown, so its bubble\n // shows the text exactly as typed (`UserMessageText`).\n getMessageMetadata: withStagedComposerMarkdown({ threadId }),\n useClient: useSdkClient,\n onStateChange: (state) => {\n // Statewire publishes what the thread renders before its attach snapshot\n // through here too (the placeholder, a remembered snapshot, and a replay\n // boundary's pre-stream default), and on a thread mid-run it reports\n // `connected` before the snapshot applies: only a state the host sent\n // counts, whatever the connection says.\n if (!isDeepAgentHostState(state)) return;\n // The attach's first one ends the attach span (time-to-history).\n const endSpan = attachSpanRef.current;\n if (endSpan) {\n attachSpanRef.current = null;\n endSpan('statewire.snapshot', { data: { thread_id: threadId } });\n }\n onServerState?.(state);\n },\n onConnectionChange: (connection) => {\n athenaDiagnostics.gauge('statewire.connection', connection?.status ?? null);\n if (connection?.status === 'stopped') {\n athenaDiagnostics.emit('statewire.connection', {\n level: 'warn',\n data: {\n status: connection.status,\n reason: connection.reason,\n message: connection.message,\n },\n });\n }\n onConnectionChange?.(connection);\n },\n onRawConnectionChange,\n onRunningChange,\n onSessionPersistedChange,\n ...(onCommandChange && { onCommandChange }),\n // Each model-context notification pulls the latest getter through the\n // core's per-render ref; the value-stable key re-registers (and so\n // notifies) only when the built runConfig actually changed. On a thread\n // with a server config lane, agora keeps only the per-send keys of what\n // this carries; `StatewireThreadConfigLaneSync` writes a changed model,\n // system prompt, tool list, workbench or knowledge base to the lane itself.\n runConfig: {\n get: () => runConfigValue,\n key: runConfigKey,\n },\n onError: (error) => {\n if (!isStatewireChannelTeardown(error)) {\n athenaDiagnostics.error(\n 'statewire.error',\n error,\n {\n code: 'statewire_rejected',\n message: 'The statewire host rejected a command',\n hint: 'Inspect error.detail — agora rejections carry a structured {code, message}.',\n },\n { thread_id: threadId },\n );\n }\n if (onError) {\n onError(error);\n return;\n }\n logUnhandledStatewireError('AthenaSDK', error);\n },\n });\n}\n"],"names":["DEEP_AGENT_DEFAULT_MESSAGE_WINDOW","useMemo","collectStatewireClientTools","resolveAgentProp","statewireSessionPrincipal","useContext","AthenaAuthContext","useRef","athenaDiagnostics","buildStatewireRunConfig","statewireClientToolWireEntries","Tools","useAui","useDeepAgentRuntime","resolveStatewireAuthHeaders","statewireSessionKey","createSubagentTranscriptConversionCache","withStagedComposerMarkdown","isDeepAgentHostState","isStatewireChannelTeardown","logUnhandledStatewireError"],"mappings":"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"}
1
+ {"version":3,"file":"useAthenaStatewireRuntime.cjs","sources":["../../src/runtime/useAthenaStatewireRuntime.ts"],"sourcesContent":["import type { AssistantClient, Toolkit } from '@assistant-ui/react';\nimport { Tools, useAui } from '@assistant-ui/react';\nimport {\n createSubagentTranscriptConversionCache,\n DEEP_AGENT_DEFAULT_MESSAGE_WINDOW,\n type DeepAgentMessageWindowDeclaration,\n type DeepAgentStreamValues,\n type DeepAgentThreadElement,\n type DeepAgentThreadSnapshotCache,\n type DeepAgentToolOutputStore,\n isDeepAgentHostState,\n isStatewireChannelTeardown,\n logUnhandledStatewireError,\n type RegisteredClientTool,\n useDeepAgentRuntime,\n type UseDeepAgentThreadOptions,\n withStagedComposerMarkdown,\n} from '@athenaintel/agent-runtime';\nimport { useContext, useMemo, useRef } from 'react';\nimport { AthenaAuthContext } from '../auth/AthenaAuthContext';\nimport {\n collectStatewireClientTools,\n statewireClientToolWireEntries,\n} from '../chat/statewire-client-tools';\nimport { athenaDiagnostics } from '../diagnostics/athena-diagnostics';\nimport {\n type AthenaStatewireTokenGetter,\n resolveStatewireAuthHeaders,\n} from './statewire-auth-headers';\nimport { statewireSessionKey, statewireSessionPrincipal } from './statewire-session-key';\n\ntype AthenaDiagnosticsSpanStarter = typeof athenaDiagnostics.span;\nimport {\n buildStatewireRunConfig,\n DEFAULT_STATEWIRE_MODEL,\n resolveAgentProp,\n} from './statewire-run-config';\n\nexport { DEFAULT_STATEWIRE_MODEL };\n\n/**\n * The head interest every SDK attach states (`athena/interest`): the host\n * mounts the transcript's tail as message documents instead of every message\n * — megabytes on long threads, over the 1 MiB frame limit of stock websocket\n * clients. Older pages load from the `StatewireHistoryEdge` row the chat UI\n * mounts above the messages, and cut tool outputs are fetched back for the\n * cards that show them.\n */\nexport const ATHENA_SDK_MESSAGE_WINDOW: DeepAgentMessageWindowDeclaration = {\n size: DEEP_AGENT_DEFAULT_MESSAGE_WINDOW,\n};\n\nexport interface AthenaStatewireRuntimeConfig {\n /** Base URL of the statewire sync host (the `…/v2/threads` mount). */\n syncUrl: string;\n /** Thread ID the statewire session attaches to. */\n threadId: string;\n /** True only for a never-started local chat. Existing (or pre-assigned)\n * threads load until their server snapshot arrives. */\n isNewChat?: boolean;\n /** API key for authentication. Used when no auth token is provided. */\n apiKey?: string;\n /** Auth token. Takes priority over apiKey. */\n token?: string | null;\n /** Resolve the latest token immediately before a request (for expiring\n * clients). Called with `{ force: true }` right after the host refused the\n * previous credential (the transport's `staleAuth`), so a caching getter\n * mints a fresh token instead of returning the refused one. */\n getToken?: AthenaStatewireTokenGetter;\n /**\n * Per-provider LRU of each thread's last wire state. A switch back to a\n * remembered thread mounts with that snapshot and projects ready on the\n * first frame instead of a loading treatment; the attach snapshot then\n * replaces it. Owned above the per-thread mount so it survives switches.\n */\n snapshotCache?: DeepAgentThreadSnapshotCache;\n /** The head interest stated on the attach (see {@link ATHENA_SDK_MESSAGE_WINDOW}, the default). */\n messageWindow?: DeepAgentMessageWindowDeclaration;\n /**\n * Whether the chat this runtime serves loads a subagent lane's earlier steps\n * on request, as `AthenaChat`'s subagent card does (\"Load earlier steps\").\n * When true, its attaches declare the deep-agent lane-cut contract\n * (protocol 2): the host sends a finished subagent's card cut to its newest\n * steps, as it sends a running one, and the card reads the rest. Default\n * `false`, so a chat that does not page lanes declares the default contract\n * and finished lanes arrive whole; a host whose `AthenaChat` renders every\n * `task` call in the subagent card turns it on through `AthenaProvider`'s\n * `subagentLaneHistory`. Read once per attach.\n */\n subagentLaneHistory?: boolean;\n /**\n * Full tool outputs fetched back for a windowed wire's cut tool messages;\n * the thread re-converts when one lands. `AthenaProvider` owns one per\n * provider and hands the same store to `StatewireHistoryEdge`.\n */\n toolOutputs?: DeepAgentToolOutputStore;\n /**\n * @deprecated Ignored. Older history pages by command (`history/page`) on\n * every host that serves it, into the conversation's own store, which every\n * reader of the thread joins; there is nothing to pass.\n */\n historyPages?: unknown;\n /** LLM model identifier. Defaults to the deep-agent default model. */\n model?: string;\n /** Agent selector: only `collab_agent:<asset_id>` refs are accepted (the run\n * executes AS that published collab agent). Any other non-empty value\n * throws — see `resolveAgentProp`. */\n agent?: string;\n /** Collab-agent channel id selecting that channel's overrides. */\n channel?: string;\n /** The agent's mode picked for this thread (`AthenaProvider` `modes`). */\n mode?: string;\n /** Backend toolkit IDs to enable. */\n tools?: string[];\n /** Frontend tool IDs to include in enabled_tools. */\n frontendToolIds?: string[];\n /** Frontend tools registered on the assistant client. Tools with a local\n * `execute` are also declared as `client_tools` and executed through the\n * statewire client-tool bridge. */\n frontendToolkit?: Toolkit;\n /** Asset IDs to include in the workbench. */\n workbench?: string[];\n /** Knowledge base IDs for RAG context. */\n knowledgeBase?: string[];\n /** System prompt override. */\n systemPrompt?: string;\n /** Client app identifier for session filtering. Sent as app_id in runConfig.custom. */\n appId?: string;\n /** Additional fields merged into runConfig.custom. */\n extraRunConfig?: Record<string, unknown>;\n /** Called on statewire transport errors (send rejections, stream failures). */\n onError?: (error: Error) => void;\n /** Projected connection status changes (deduped; null on unmount). */\n onConnectionChange?: UseDeepAgentThreadOptions['onConnectionChange'];\n /** Raw connection observer — carries the transport's reconnect handle. */\n onRawConnectionChange?: UseDeepAgentThreadOptions['onRawConnectionChange'];\n /** Notified when a run starts/stops. */\n onRunningChange?: UseDeepAgentThreadOptions['onRunningChange'];\n /** Core's paired session-asset existence verdict, including remembered/unknown state. */\n onSessionPersistedChange?: UseDeepAgentThreadOptions['onSessionPersistedChange'];\n /** Every statewire command-lifecycle update (the chat outbox lets a handed-over message go on it). */\n onCommandChange?: UseDeepAgentThreadOptions['onCommandChange'];\n /**\n * Observes the host's own state: called with the attach snapshot and then on\n * every later frame (`isDeepAgentHostState`) — never with the placeholder or\n * remembered snapshot a thread renders before its snapshot applies, which\n * can be after the connection reports `connected`. Called per streamed\n * token, so keep it cheap.\n */\n onServerState?: (state: DeepAgentStreamValues) => void;\n}\n\nconst EMPTY_TOOLKIT: Toolkit = {};\nconst EMPTY_TOOL_IDS: string[] = [];\n\n/** The client tools derived from the runtime's frontend toolkit — exposed so\n * the provider can mount the client-tool bridge with the same set. */\nexport function useStatewireClientTools(\n frontendToolkit: Toolkit | undefined,\n): RegisteredClientTool[] {\n return useMemo(\n () => collectStatewireClientTools(frontendToolkit ?? EMPTY_TOOLKIT),\n [frontendToolkit],\n );\n}\n\n/**\n * Statewire runtime for the Athena SDK — a thin shim over the shared\n * `@athenaintel/agent-runtime` `useDeepAgentRuntime`: it attaches to the\n * agora-hosted deep-agent thread at `${syncUrl}/${threadId}` and returns the\n * `AssistantClient` to mount via `AuiProvider` — the same integration shape as\n * the Olympus, Chrome extension, Office, and mobile statewire hosts.\n *\n * Auth: a token (resolved live through `getToken` when provided) rides\n * `Authorization: Bearer`, and an API key falls back to `X-API-KEY` — both\n * accepted by the statewire host.\n */\nexport function useAthenaStatewireRuntime(\n config: AthenaStatewireRuntimeConfig,\n): AssistantClient {\n const {\n syncUrl,\n threadId,\n isNewChat = false,\n apiKey,\n token,\n getToken,\n model,\n agent,\n channel,\n mode,\n tools = EMPTY_TOOL_IDS,\n frontendToolIds = EMPTY_TOOL_IDS,\n frontendToolkit = EMPTY_TOOLKIT,\n workbench,\n knowledgeBase,\n systemPrompt,\n appId,\n extraRunConfig,\n snapshotCache,\n messageWindow = ATHENA_SDK_MESSAGE_WINDOW,\n subagentLaneHistory = false,\n toolOutputs,\n onError,\n onConnectionChange,\n onRawConnectionChange,\n onRunningChange,\n onSessionPersistedChange,\n onCommandChange,\n onServerState,\n } = config;\n\n // Fail loud at mount, not at first send: the statewire host always runs the\n // Athena deep agent, so an `agent` outside the collab_agent namespace can\n // never apply. Throwing here (render time) is what makes a misconfigured\n // integration visible instead of quietly answering as the wrong agent.\n resolveAgentProp({ agent });\n\n const clientTools = useStatewireClientTools(frontendToolkit);\n\n // The persisted command lane is keyed by WHO is signed in as well as by host\n // and thread (see `statewireSessionKey`); `null` while the sign-in provider\n // above is still resolving who that is.\n const principal = statewireSessionPrincipal(useContext(AthenaAuthContext));\n\n // Attach → first server snapshot span, keyed per thread attach.\n const attachSpanRef = useRef<ReturnType<AthenaDiagnosticsSpanStarter> | null>(null);\n const attachThreadRef = useRef<string | null>(null);\n if (attachThreadRef.current !== threadId) {\n attachThreadRef.current = threadId;\n attachSpanRef.current = athenaDiagnostics.span(\n `statewire.attach:${threadId}`,\n 'statewire.attach.start',\n { thread_id: threadId, is_new_chat: isNewChat },\n );\n }\n\n // Built every render so its JSON signature can key the model-context\n // registration below: consumers commonly pass fresh array literals per\n // render, which must not thrash registration, while a changed value (a new\n // `model`, channel, tool list, system prompt, …) must re-sync the context\n // before the next send. The core pulls this value only on model-context\n // notifications, which a key change triggers.\n const runConfigValue = buildStatewireRunConfig({\n model,\n agent,\n channel,\n mode,\n tools,\n frontendToolIds,\n workbench,\n knowledgeBase,\n systemPrompt,\n appId,\n extraRunConfig,\n clientTools: statewireClientToolWireEntries(clientTools),\n });\n const runConfigKey = JSON.stringify(runConfigValue);\n\n const auiTools = useMemo(() => Tools({ toolkit: frontendToolkit }), [frontendToolkit]);\n // Web client for the shared runtime core (a `use*` name so the\n // rules-of-hooks lint sees the `useAui` call inside a custom hook; the core\n // invokes it unconditionally every render).\n const useSdkClient = (thread: DeepAgentThreadElement) => useAui({ thread, tools: auiTools });\n\n return useDeepAgentRuntime({\n surface: 'AthenaSDK',\n threadId,\n baseUrl: syncUrl,\n // Option closures are re-read per render by the core, so credential\n // rotation (new `token`/`getToken`/`apiKey` props) reaches the next\n // request without remounting the thread. The transport's `staleAuth`\n // (true right after a refused credential) is forwarded as `force`.\n headers: (ctx) => resolveStatewireAuthHeaders({ apiKey, token, getToken }, ctx),\n isNewChat,\n // Queued entries render in the SDK's queue panel, so only the steer lane\n // projects into the message tail.\n laneProjection: 'steer-only',\n // Durable session: a reload resumes the lane and resends whatever the\n // server has not marked durable. Scoped by host AND principal — a thread\n // id is only meaningful against the backend that minted it, and a stored\n // lane must never resend against another signed-in user. (Consumers\n // server-render this SDK; the core's availability probe keeps those\n // sessions process-local, as before the seam existed.) Until the sign-in\n // provider knows who is signed in, the lane is pending: the transport\n // stays parked and nothing is mounted on a stand-in key\n // (`statewireSessionPrincipal`). A change to another principal remounts\n // the conversation on that principal's lane instead of moving this one\n // there (the runtime's lane epoch), so the previous principal's\n // undelivered commands are never sent as the new one.\n session:\n principal === null\n ? { kind: 'pending' }\n : {\n kind: 'local-storage',\n key: (id) => statewireSessionKey({ syncUrl, principal, threadId: id }),\n },\n snapshotCache,\n // Head interest (see `ATHENA_SDK_MESSAGE_WINDOW`): the tail of the\n // transcript instead of every message; the chat UI's history edge pages\n // older ranges in and fetches cut tool outputs into `toolOutputs`.\n messageWindow,\n toolOutputs,\n // Each `task` card's nested transcript becomes its tool-call part's\n // `messages` (assistant-ui's nested-thread channel), which the subagent\n // card (`SubagentTaskToolUI`) shows.\n createConversionCache: createSubagentTranscriptConversionCache,\n // The lane-cut contract only where the chat pages lanes (see `subagentLaneHistory`).\n laneHistory: subagentLaneHistory,\n capabilities: { edit: true, reload: true, continue: true },\n // The composer stages the draft each send came from right before it\n // sends; the message carries it as its composer markdown, so its bubble\n // shows the text exactly as typed (`UserMessageText`).\n getMessageMetadata: withStagedComposerMarkdown({ threadId }),\n useClient: useSdkClient,\n onStateChange: (state) => {\n // Statewire publishes what the thread renders before its attach snapshot\n // through here too (the placeholder, a remembered snapshot, and a replay\n // boundary's pre-stream default), and on a thread mid-run it reports\n // `connected` before the snapshot applies: only a state the host sent\n // counts, whatever the connection says.\n if (!isDeepAgentHostState(state)) return;\n // The attach's first one ends the attach span (time-to-history).\n const endSpan = attachSpanRef.current;\n if (endSpan) {\n attachSpanRef.current = null;\n endSpan('statewire.snapshot', { data: { thread_id: threadId } });\n }\n onServerState?.(state);\n },\n onConnectionChange: (connection) => {\n athenaDiagnostics.gauge('statewire.connection', connection?.status ?? null);\n if (connection?.status === 'stopped') {\n athenaDiagnostics.emit('statewire.connection', {\n level: 'warn',\n data: {\n status: connection.status,\n reason: connection.reason,\n message: connection.message,\n },\n });\n }\n onConnectionChange?.(connection);\n },\n onRawConnectionChange,\n onRunningChange,\n onSessionPersistedChange,\n ...(onCommandChange && { onCommandChange }),\n // Each model-context notification pulls the latest getter through the\n // core's per-render ref; the value-stable key re-registers (and so\n // notifies) only when the built runConfig actually changed. On a thread\n // with a server config lane, agora keeps only the per-send keys of what\n // this carries; `StatewireThreadConfigLaneSync` writes a changed model,\n // system prompt, tool list, workbench or knowledge base to the lane itself.\n runConfig: {\n get: () => runConfigValue,\n key: runConfigKey,\n },\n onError: (error) => {\n if (!isStatewireChannelTeardown(error)) {\n athenaDiagnostics.error(\n 'statewire.error',\n error,\n {\n code: 'statewire_rejected',\n message: 'The statewire host rejected a command',\n hint: 'Inspect error.detail — agora rejections carry a structured {code, message}.',\n },\n { thread_id: threadId },\n );\n }\n if (onError) {\n onError(error);\n return;\n }\n logUnhandledStatewireError('AthenaSDK', error);\n },\n });\n}\n"],"names":["DEEP_AGENT_DEFAULT_MESSAGE_WINDOW","useMemo","collectStatewireClientTools","resolveAgentProp","statewireSessionPrincipal","useContext","AthenaAuthContext","useRef","athenaDiagnostics","buildStatewireRunConfig","statewireClientToolWireEntries","Tools","useAui","useDeepAgentRuntime","resolveStatewireAuthHeaders","statewireSessionKey","createSubagentTranscriptConversionCache","withStagedComposerMarkdown","isDeepAgentHostState","isStatewireChannelTeardown","logUnhandledStatewireError"],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import type { AssistantClient, Toolkit } from '@assistant-ui/react';
2
- import { type DeepAgentHistoryStore, type DeepAgentMessageWindowDeclaration, type DeepAgentStreamValues, type DeepAgentThreadSnapshotCache, type DeepAgentToolOutputStore, type RegisteredClientTool, type UseDeepAgentThreadOptions } from '../agent-runtime/src/index';
2
+ import { type DeepAgentMessageWindowDeclaration, type DeepAgentStreamValues, type DeepAgentThreadSnapshotCache, type DeepAgentToolOutputStore, type RegisteredClientTool, type UseDeepAgentThreadOptions } from '../agent-runtime/src/index';
3
3
  import { type AthenaStatewireTokenGetter } from './statewire-auth-headers';
4
4
  import { DEFAULT_STATEWIRE_MODEL } from './statewire-run-config';
5
5
  export { DEFAULT_STATEWIRE_MODEL };
@@ -57,11 +57,11 @@ export interface AthenaStatewireRuntimeConfig {
57
57
  */
58
58
  toolOutputs?: DeepAgentToolOutputStore;
59
59
  /**
60
- * Older turns paged by command (`history/page`, protocol 3), joined in front
61
- * of the live window; `AthenaProvider` owns one and hands the same store to
62
- * `StatewireHistoryEdge`, which pages into it.
60
+ * @deprecated Ignored. Older history pages by command (`history/page`) on
61
+ * every host that serves it, into the conversation's own store, which every
62
+ * reader of the thread joins; there is nothing to pass.
63
63
  */
64
- historyPages?: DeepAgentHistoryStore;
64
+ historyPages?: unknown;
65
65
  /** LLM model identifier. Defaults to the deep-agent default model. */
66
66
  model?: string;
67
67
  /** Agent selector: only `collab_agent:<asset_id>` refs are accepted (the run
@@ -48,7 +48,6 @@ function useAthenaStatewireRuntime(config) {
48
48
  messageWindow = ATHENA_SDK_MESSAGE_WINDOW,
49
49
  subagentLaneHistory = false,
50
50
  toolOutputs,
51
- historyPages,
52
51
  onError,
53
52
  onConnectionChange,
54
53
  onRawConnectionChange,
@@ -122,7 +121,6 @@ function useAthenaStatewireRuntime(config) {
122
121
  // older ranges in and fetches cut tool outputs into `toolOutputs`.
123
122
  messageWindow,
124
123
  toolOutputs,
125
- historyStore: historyPages,
126
124
  // Each `task` card's nested transcript becomes its tool-call part's
127
125
  // `messages` (assistant-ui's nested-thread channel), which the subagent
128
126
  // card (`SubagentTaskToolUI`) shows.
@@ -1 +1 @@
1
- {"version":3,"file":"useAthenaStatewireRuntime.js","sources":["../../src/runtime/useAthenaStatewireRuntime.ts"],"sourcesContent":["import type { AssistantClient, Toolkit } from '@assistant-ui/react';\nimport { Tools, useAui } from '@assistant-ui/react';\nimport {\n createSubagentTranscriptConversionCache,\n DEEP_AGENT_DEFAULT_MESSAGE_WINDOW,\n type DeepAgentHistoryStore,\n type DeepAgentMessageWindowDeclaration,\n type DeepAgentStreamValues,\n type DeepAgentThreadElement,\n type DeepAgentThreadSnapshotCache,\n type DeepAgentToolOutputStore,\n isDeepAgentHostState,\n isStatewireChannelTeardown,\n logUnhandledStatewireError,\n type RegisteredClientTool,\n useDeepAgentRuntime,\n type UseDeepAgentThreadOptions,\n withStagedComposerMarkdown,\n} from '@athenaintel/agent-runtime';\nimport { useContext, useMemo, useRef } from 'react';\nimport { AthenaAuthContext } from '../auth/AthenaAuthContext';\nimport {\n collectStatewireClientTools,\n statewireClientToolWireEntries,\n} from '../chat/statewire-client-tools';\nimport { athenaDiagnostics } from '../diagnostics/athena-diagnostics';\nimport {\n type AthenaStatewireTokenGetter,\n resolveStatewireAuthHeaders,\n} from './statewire-auth-headers';\nimport { statewireSessionKey, statewireSessionPrincipal } from './statewire-session-key';\n\ntype AthenaDiagnosticsSpanStarter = typeof athenaDiagnostics.span;\nimport {\n buildStatewireRunConfig,\n DEFAULT_STATEWIRE_MODEL,\n resolveAgentProp,\n} from './statewire-run-config';\n\nexport { DEFAULT_STATEWIRE_MODEL };\n\n/**\n * The head interest every SDK attach states (`athena/interest`): the host\n * mounts the transcript's tail as message documents instead of every message\n * — megabytes on long threads, over the 1 MiB frame limit of stock websocket\n * clients. Older pages load from the `StatewireHistoryEdge` row the chat UI\n * mounts above the messages, and cut tool outputs are fetched back for the\n * cards that show them.\n */\nexport const ATHENA_SDK_MESSAGE_WINDOW: DeepAgentMessageWindowDeclaration = {\n size: DEEP_AGENT_DEFAULT_MESSAGE_WINDOW,\n};\n\nexport interface AthenaStatewireRuntimeConfig {\n /** Base URL of the statewire sync host (the `…/v2/threads` mount). */\n syncUrl: string;\n /** Thread ID the statewire session attaches to. */\n threadId: string;\n /** True only for a never-started local chat. Existing (or pre-assigned)\n * threads load until their server snapshot arrives. */\n isNewChat?: boolean;\n /** API key for authentication. Used when no auth token is provided. */\n apiKey?: string;\n /** Auth token. Takes priority over apiKey. */\n token?: string | null;\n /** Resolve the latest token immediately before a request (for expiring\n * clients). Called with `{ force: true }` right after the host refused the\n * previous credential (the transport's `staleAuth`), so a caching getter\n * mints a fresh token instead of returning the refused one. */\n getToken?: AthenaStatewireTokenGetter;\n /**\n * Per-provider LRU of each thread's last wire state. A switch back to a\n * remembered thread mounts with that snapshot and projects ready on the\n * first frame instead of a loading treatment; the attach snapshot then\n * replaces it. Owned above the per-thread mount so it survives switches.\n */\n snapshotCache?: DeepAgentThreadSnapshotCache;\n /** The head interest stated on the attach (see {@link ATHENA_SDK_MESSAGE_WINDOW}, the default). */\n messageWindow?: DeepAgentMessageWindowDeclaration;\n /**\n * Whether the chat this runtime serves loads a subagent lane's earlier steps\n * on request, as `AthenaChat`'s subagent card does (\"Load earlier steps\").\n * When true, its attaches declare the deep-agent lane-cut contract\n * (protocol 2): the host sends a finished subagent's card cut to its newest\n * steps, as it sends a running one, and the card reads the rest. Default\n * `false`, so a chat that does not page lanes declares the default contract\n * and finished lanes arrive whole; a host whose `AthenaChat` renders every\n * `task` call in the subagent card turns it on through `AthenaProvider`'s\n * `subagentLaneHistory`. Read once per attach.\n */\n subagentLaneHistory?: boolean;\n /**\n * Full tool outputs fetched back for a windowed wire's cut tool messages;\n * the thread re-converts when one lands. `AthenaProvider` owns one per\n * provider and hands the same store to `StatewireHistoryEdge`.\n */\n toolOutputs?: DeepAgentToolOutputStore;\n /**\n * Older turns paged by command (`history/page`, protocol 3), joined in front\n * of the live window; `AthenaProvider` owns one and hands the same store to\n * `StatewireHistoryEdge`, which pages into it.\n */\n historyPages?: DeepAgentHistoryStore;\n /** LLM model identifier. Defaults to the deep-agent default model. */\n model?: string;\n /** Agent selector: only `collab_agent:<asset_id>` refs are accepted (the run\n * executes AS that published collab agent). Any other non-empty value\n * throws — see `resolveAgentProp`. */\n agent?: string;\n /** Collab-agent channel id selecting that channel's overrides. */\n channel?: string;\n /** The agent's mode picked for this thread (`AthenaProvider` `modes`). */\n mode?: string;\n /** Backend toolkit IDs to enable. */\n tools?: string[];\n /** Frontend tool IDs to include in enabled_tools. */\n frontendToolIds?: string[];\n /** Frontend tools registered on the assistant client. Tools with a local\n * `execute` are also declared as `client_tools` and executed through the\n * statewire client-tool bridge. */\n frontendToolkit?: Toolkit;\n /** Asset IDs to include in the workbench. */\n workbench?: string[];\n /** Knowledge base IDs for RAG context. */\n knowledgeBase?: string[];\n /** System prompt override. */\n systemPrompt?: string;\n /** Client app identifier for session filtering. Sent as app_id in runConfig.custom. */\n appId?: string;\n /** Additional fields merged into runConfig.custom. */\n extraRunConfig?: Record<string, unknown>;\n /** Called on statewire transport errors (send rejections, stream failures). */\n onError?: (error: Error) => void;\n /** Projected connection status changes (deduped; null on unmount). */\n onConnectionChange?: UseDeepAgentThreadOptions['onConnectionChange'];\n /** Raw connection observer — carries the transport's reconnect handle. */\n onRawConnectionChange?: UseDeepAgentThreadOptions['onRawConnectionChange'];\n /** Notified when a run starts/stops. */\n onRunningChange?: UseDeepAgentThreadOptions['onRunningChange'];\n /** Core's paired session-asset existence verdict, including remembered/unknown state. */\n onSessionPersistedChange?: UseDeepAgentThreadOptions['onSessionPersistedChange'];\n /** Every statewire command-lifecycle update (the chat outbox lets a handed-over message go on it). */\n onCommandChange?: UseDeepAgentThreadOptions['onCommandChange'];\n /**\n * Observes the host's own state: called with the attach snapshot and then on\n * every later frame (`isDeepAgentHostState`) — never with the placeholder or\n * remembered snapshot a thread renders before its snapshot applies, which\n * can be after the connection reports `connected`. Called per streamed\n * token, so keep it cheap.\n */\n onServerState?: (state: DeepAgentStreamValues) => void;\n}\n\nconst EMPTY_TOOLKIT: Toolkit = {};\nconst EMPTY_TOOL_IDS: string[] = [];\n\n/** The client tools derived from the runtime's frontend toolkit — exposed so\n * the provider can mount the client-tool bridge with the same set. */\nexport function useStatewireClientTools(\n frontendToolkit: Toolkit | undefined,\n): RegisteredClientTool[] {\n return useMemo(\n () => collectStatewireClientTools(frontendToolkit ?? EMPTY_TOOLKIT),\n [frontendToolkit],\n );\n}\n\n/**\n * Statewire runtime for the Athena SDK — a thin shim over the shared\n * `@athenaintel/agent-runtime` `useDeepAgentRuntime`: it attaches to the\n * agora-hosted deep-agent thread at `${syncUrl}/${threadId}` and returns the\n * `AssistantClient` to mount via `AuiProvider` — the same integration shape as\n * the Olympus, Chrome extension, Office, and mobile statewire hosts.\n *\n * Auth: a token (resolved live through `getToken` when provided) rides\n * `Authorization: Bearer`, and an API key falls back to `X-API-KEY` — both\n * accepted by the statewire host.\n */\nexport function useAthenaStatewireRuntime(\n config: AthenaStatewireRuntimeConfig,\n): AssistantClient {\n const {\n syncUrl,\n threadId,\n isNewChat = false,\n apiKey,\n token,\n getToken,\n model,\n agent,\n channel,\n mode,\n tools = EMPTY_TOOL_IDS,\n frontendToolIds = EMPTY_TOOL_IDS,\n frontendToolkit = EMPTY_TOOLKIT,\n workbench,\n knowledgeBase,\n systemPrompt,\n appId,\n extraRunConfig,\n snapshotCache,\n messageWindow = ATHENA_SDK_MESSAGE_WINDOW,\n subagentLaneHistory = false,\n toolOutputs,\n historyPages,\n onError,\n onConnectionChange,\n onRawConnectionChange,\n onRunningChange,\n onSessionPersistedChange,\n onCommandChange,\n onServerState,\n } = config;\n\n // Fail loud at mount, not at first send: the statewire host always runs the\n // Athena deep agent, so an `agent` outside the collab_agent namespace can\n // never apply. Throwing here (render time) is what makes a misconfigured\n // integration visible instead of quietly answering as the wrong agent.\n resolveAgentProp({ agent });\n\n const clientTools = useStatewireClientTools(frontendToolkit);\n\n // The persisted command lane is keyed by WHO is signed in as well as by host\n // and thread (see `statewireSessionKey`); `null` while the sign-in provider\n // above is still resolving who that is.\n const principal = statewireSessionPrincipal(useContext(AthenaAuthContext));\n\n // Attach → first server snapshot span, keyed per thread attach.\n const attachSpanRef = useRef<ReturnType<AthenaDiagnosticsSpanStarter> | null>(null);\n const attachThreadRef = useRef<string | null>(null);\n if (attachThreadRef.current !== threadId) {\n attachThreadRef.current = threadId;\n attachSpanRef.current = athenaDiagnostics.span(\n `statewire.attach:${threadId}`,\n 'statewire.attach.start',\n { thread_id: threadId, is_new_chat: isNewChat },\n );\n }\n\n // Built every render so its JSON signature can key the model-context\n // registration below: consumers commonly pass fresh array literals per\n // render, which must not thrash registration, while a changed value (a new\n // `model`, channel, tool list, system prompt, …) must re-sync the context\n // before the next send. The core pulls this value only on model-context\n // notifications, which a key change triggers.\n const runConfigValue = buildStatewireRunConfig({\n model,\n agent,\n channel,\n mode,\n tools,\n frontendToolIds,\n workbench,\n knowledgeBase,\n systemPrompt,\n appId,\n extraRunConfig,\n clientTools: statewireClientToolWireEntries(clientTools),\n });\n const runConfigKey = JSON.stringify(runConfigValue);\n\n const auiTools = useMemo(() => Tools({ toolkit: frontendToolkit }), [frontendToolkit]);\n // Web client for the shared runtime core (a `use*` name so the\n // rules-of-hooks lint sees the `useAui` call inside a custom hook; the core\n // invokes it unconditionally every render).\n const useSdkClient = (thread: DeepAgentThreadElement) => useAui({ thread, tools: auiTools });\n\n return useDeepAgentRuntime({\n surface: 'AthenaSDK',\n threadId,\n baseUrl: syncUrl,\n // Option closures are re-read per render by the core, so credential\n // rotation (new `token`/`getToken`/`apiKey` props) reaches the next\n // request without remounting the thread. The transport's `staleAuth`\n // (true right after a refused credential) is forwarded as `force`.\n headers: (ctx) => resolveStatewireAuthHeaders({ apiKey, token, getToken }, ctx),\n isNewChat,\n // Queued entries render in the SDK's queue panel, so only the steer lane\n // projects into the message tail.\n laneProjection: 'steer-only',\n // Durable session: a reload resumes the lane and resends whatever the\n // server has not marked durable. Scoped by host AND principal — a thread\n // id is only meaningful against the backend that minted it, and a stored\n // lane must never resend against another signed-in user. (Consumers\n // server-render this SDK; the core's availability probe keeps those\n // sessions process-local, as before the seam existed.) Until the sign-in\n // provider knows who is signed in, the lane is pending: the transport\n // stays parked and nothing is mounted on a stand-in key\n // (`statewireSessionPrincipal`). A change to another principal remounts\n // the conversation on that principal's lane instead of moving this one\n // there (the runtime's lane epoch), so the previous principal's\n // undelivered commands are never sent as the new one.\n session:\n principal === null\n ? { kind: 'pending' }\n : {\n kind: 'local-storage',\n key: (id) => statewireSessionKey({ syncUrl, principal, threadId: id }),\n },\n snapshotCache,\n // Head interest (see `ATHENA_SDK_MESSAGE_WINDOW`): the tail of the\n // transcript instead of every message; the chat UI's history edge pages\n // older ranges in and fetches cut tool outputs into `toolOutputs`.\n messageWindow,\n toolOutputs,\n historyStore: historyPages,\n // Each `task` card's nested transcript becomes its tool-call part's\n // `messages` (assistant-ui's nested-thread channel), which the subagent\n // card (`SubagentTaskToolUI`) shows.\n createConversionCache: createSubagentTranscriptConversionCache,\n // The lane-cut contract only where the chat pages lanes (see `subagentLaneHistory`).\n laneHistory: subagentLaneHistory,\n capabilities: { edit: true, reload: true, continue: true },\n // The composer stages the draft each send came from right before it\n // sends; the message carries it as its composer markdown, so its bubble\n // shows the text exactly as typed (`UserMessageText`).\n getMessageMetadata: withStagedComposerMarkdown({ threadId }),\n useClient: useSdkClient,\n onStateChange: (state) => {\n // Statewire publishes what the thread renders before its attach snapshot\n // through here too (the placeholder, a remembered snapshot, and a replay\n // boundary's pre-stream default), and on a thread mid-run it reports\n // `connected` before the snapshot applies: only a state the host sent\n // counts, whatever the connection says.\n if (!isDeepAgentHostState(state)) return;\n // The attach's first one ends the attach span (time-to-history).\n const endSpan = attachSpanRef.current;\n if (endSpan) {\n attachSpanRef.current = null;\n endSpan('statewire.snapshot', { data: { thread_id: threadId } });\n }\n onServerState?.(state);\n },\n onConnectionChange: (connection) => {\n athenaDiagnostics.gauge('statewire.connection', connection?.status ?? null);\n if (connection?.status === 'stopped') {\n athenaDiagnostics.emit('statewire.connection', {\n level: 'warn',\n data: {\n status: connection.status,\n reason: connection.reason,\n message: connection.message,\n },\n });\n }\n onConnectionChange?.(connection);\n },\n onRawConnectionChange,\n onRunningChange,\n onSessionPersistedChange,\n ...(onCommandChange && { onCommandChange }),\n // Each model-context notification pulls the latest getter through the\n // core's per-render ref; the value-stable key re-registers (and so\n // notifies) only when the built runConfig actually changed. On a thread\n // with a server config lane, agora keeps only the per-send keys of what\n // this carries; `StatewireThreadConfigLaneSync` writes a changed model,\n // system prompt, tool list, workbench or knowledge base to the lane itself.\n runConfig: {\n get: () => runConfigValue,\n key: runConfigKey,\n },\n onError: (error) => {\n if (!isStatewireChannelTeardown(error)) {\n athenaDiagnostics.error(\n 'statewire.error',\n error,\n {\n code: 'statewire_rejected',\n message: 'The statewire host rejected a command',\n hint: 'Inspect error.detail — agora rejections carry a structured {code, message}.',\n },\n { thread_id: threadId },\n );\n }\n if (onError) {\n onError(error);\n return;\n }\n logUnhandledStatewireError('AthenaSDK', error);\n },\n });\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useAthenaStatewireRuntime.js","sources":["../../src/runtime/useAthenaStatewireRuntime.ts"],"sourcesContent":["import type { AssistantClient, Toolkit } from '@assistant-ui/react';\nimport { Tools, useAui } from '@assistant-ui/react';\nimport {\n createSubagentTranscriptConversionCache,\n DEEP_AGENT_DEFAULT_MESSAGE_WINDOW,\n type DeepAgentMessageWindowDeclaration,\n type DeepAgentStreamValues,\n type DeepAgentThreadElement,\n type DeepAgentThreadSnapshotCache,\n type DeepAgentToolOutputStore,\n isDeepAgentHostState,\n isStatewireChannelTeardown,\n logUnhandledStatewireError,\n type RegisteredClientTool,\n useDeepAgentRuntime,\n type UseDeepAgentThreadOptions,\n withStagedComposerMarkdown,\n} from '@athenaintel/agent-runtime';\nimport { useContext, useMemo, useRef } from 'react';\nimport { AthenaAuthContext } from '../auth/AthenaAuthContext';\nimport {\n collectStatewireClientTools,\n statewireClientToolWireEntries,\n} from '../chat/statewire-client-tools';\nimport { athenaDiagnostics } from '../diagnostics/athena-diagnostics';\nimport {\n type AthenaStatewireTokenGetter,\n resolveStatewireAuthHeaders,\n} from './statewire-auth-headers';\nimport { statewireSessionKey, statewireSessionPrincipal } from './statewire-session-key';\n\ntype AthenaDiagnosticsSpanStarter = typeof athenaDiagnostics.span;\nimport {\n buildStatewireRunConfig,\n DEFAULT_STATEWIRE_MODEL,\n resolveAgentProp,\n} from './statewire-run-config';\n\nexport { DEFAULT_STATEWIRE_MODEL };\n\n/**\n * The head interest every SDK attach states (`athena/interest`): the host\n * mounts the transcript's tail as message documents instead of every message\n * — megabytes on long threads, over the 1 MiB frame limit of stock websocket\n * clients. Older pages load from the `StatewireHistoryEdge` row the chat UI\n * mounts above the messages, and cut tool outputs are fetched back for the\n * cards that show them.\n */\nexport const ATHENA_SDK_MESSAGE_WINDOW: DeepAgentMessageWindowDeclaration = {\n size: DEEP_AGENT_DEFAULT_MESSAGE_WINDOW,\n};\n\nexport interface AthenaStatewireRuntimeConfig {\n /** Base URL of the statewire sync host (the `…/v2/threads` mount). */\n syncUrl: string;\n /** Thread ID the statewire session attaches to. */\n threadId: string;\n /** True only for a never-started local chat. Existing (or pre-assigned)\n * threads load until their server snapshot arrives. */\n isNewChat?: boolean;\n /** API key for authentication. Used when no auth token is provided. */\n apiKey?: string;\n /** Auth token. Takes priority over apiKey. */\n token?: string | null;\n /** Resolve the latest token immediately before a request (for expiring\n * clients). Called with `{ force: true }` right after the host refused the\n * previous credential (the transport's `staleAuth`), so a caching getter\n * mints a fresh token instead of returning the refused one. */\n getToken?: AthenaStatewireTokenGetter;\n /**\n * Per-provider LRU of each thread's last wire state. A switch back to a\n * remembered thread mounts with that snapshot and projects ready on the\n * first frame instead of a loading treatment; the attach snapshot then\n * replaces it. Owned above the per-thread mount so it survives switches.\n */\n snapshotCache?: DeepAgentThreadSnapshotCache;\n /** The head interest stated on the attach (see {@link ATHENA_SDK_MESSAGE_WINDOW}, the default). */\n messageWindow?: DeepAgentMessageWindowDeclaration;\n /**\n * Whether the chat this runtime serves loads a subagent lane's earlier steps\n * on request, as `AthenaChat`'s subagent card does (\"Load earlier steps\").\n * When true, its attaches declare the deep-agent lane-cut contract\n * (protocol 2): the host sends a finished subagent's card cut to its newest\n * steps, as it sends a running one, and the card reads the rest. Default\n * `false`, so a chat that does not page lanes declares the default contract\n * and finished lanes arrive whole; a host whose `AthenaChat` renders every\n * `task` call in the subagent card turns it on through `AthenaProvider`'s\n * `subagentLaneHistory`. Read once per attach.\n */\n subagentLaneHistory?: boolean;\n /**\n * Full tool outputs fetched back for a windowed wire's cut tool messages;\n * the thread re-converts when one lands. `AthenaProvider` owns one per\n * provider and hands the same store to `StatewireHistoryEdge`.\n */\n toolOutputs?: DeepAgentToolOutputStore;\n /**\n * @deprecated Ignored. Older history pages by command (`history/page`) on\n * every host that serves it, into the conversation's own store, which every\n * reader of the thread joins; there is nothing to pass.\n */\n historyPages?: unknown;\n /** LLM model identifier. Defaults to the deep-agent default model. */\n model?: string;\n /** Agent selector: only `collab_agent:<asset_id>` refs are accepted (the run\n * executes AS that published collab agent). Any other non-empty value\n * throws — see `resolveAgentProp`. */\n agent?: string;\n /** Collab-agent channel id selecting that channel's overrides. */\n channel?: string;\n /** The agent's mode picked for this thread (`AthenaProvider` `modes`). */\n mode?: string;\n /** Backend toolkit IDs to enable. */\n tools?: string[];\n /** Frontend tool IDs to include in enabled_tools. */\n frontendToolIds?: string[];\n /** Frontend tools registered on the assistant client. Tools with a local\n * `execute` are also declared as `client_tools` and executed through the\n * statewire client-tool bridge. */\n frontendToolkit?: Toolkit;\n /** Asset IDs to include in the workbench. */\n workbench?: string[];\n /** Knowledge base IDs for RAG context. */\n knowledgeBase?: string[];\n /** System prompt override. */\n systemPrompt?: string;\n /** Client app identifier for session filtering. Sent as app_id in runConfig.custom. */\n appId?: string;\n /** Additional fields merged into runConfig.custom. */\n extraRunConfig?: Record<string, unknown>;\n /** Called on statewire transport errors (send rejections, stream failures). */\n onError?: (error: Error) => void;\n /** Projected connection status changes (deduped; null on unmount). */\n onConnectionChange?: UseDeepAgentThreadOptions['onConnectionChange'];\n /** Raw connection observer — carries the transport's reconnect handle. */\n onRawConnectionChange?: UseDeepAgentThreadOptions['onRawConnectionChange'];\n /** Notified when a run starts/stops. */\n onRunningChange?: UseDeepAgentThreadOptions['onRunningChange'];\n /** Core's paired session-asset existence verdict, including remembered/unknown state. */\n onSessionPersistedChange?: UseDeepAgentThreadOptions['onSessionPersistedChange'];\n /** Every statewire command-lifecycle update (the chat outbox lets a handed-over message go on it). */\n onCommandChange?: UseDeepAgentThreadOptions['onCommandChange'];\n /**\n * Observes the host's own state: called with the attach snapshot and then on\n * every later frame (`isDeepAgentHostState`) — never with the placeholder or\n * remembered snapshot a thread renders before its snapshot applies, which\n * can be after the connection reports `connected`. Called per streamed\n * token, so keep it cheap.\n */\n onServerState?: (state: DeepAgentStreamValues) => void;\n}\n\nconst EMPTY_TOOLKIT: Toolkit = {};\nconst EMPTY_TOOL_IDS: string[] = [];\n\n/** The client tools derived from the runtime's frontend toolkit — exposed so\n * the provider can mount the client-tool bridge with the same set. */\nexport function useStatewireClientTools(\n frontendToolkit: Toolkit | undefined,\n): RegisteredClientTool[] {\n return useMemo(\n () => collectStatewireClientTools(frontendToolkit ?? EMPTY_TOOLKIT),\n [frontendToolkit],\n );\n}\n\n/**\n * Statewire runtime for the Athena SDK — a thin shim over the shared\n * `@athenaintel/agent-runtime` `useDeepAgentRuntime`: it attaches to the\n * agora-hosted deep-agent thread at `${syncUrl}/${threadId}` and returns the\n * `AssistantClient` to mount via `AuiProvider` — the same integration shape as\n * the Olympus, Chrome extension, Office, and mobile statewire hosts.\n *\n * Auth: a token (resolved live through `getToken` when provided) rides\n * `Authorization: Bearer`, and an API key falls back to `X-API-KEY` — both\n * accepted by the statewire host.\n */\nexport function useAthenaStatewireRuntime(\n config: AthenaStatewireRuntimeConfig,\n): AssistantClient {\n const {\n syncUrl,\n threadId,\n isNewChat = false,\n apiKey,\n token,\n getToken,\n model,\n agent,\n channel,\n mode,\n tools = EMPTY_TOOL_IDS,\n frontendToolIds = EMPTY_TOOL_IDS,\n frontendToolkit = EMPTY_TOOLKIT,\n workbench,\n knowledgeBase,\n systemPrompt,\n appId,\n extraRunConfig,\n snapshotCache,\n messageWindow = ATHENA_SDK_MESSAGE_WINDOW,\n subagentLaneHistory = false,\n toolOutputs,\n onError,\n onConnectionChange,\n onRawConnectionChange,\n onRunningChange,\n onSessionPersistedChange,\n onCommandChange,\n onServerState,\n } = config;\n\n // Fail loud at mount, not at first send: the statewire host always runs the\n // Athena deep agent, so an `agent` outside the collab_agent namespace can\n // never apply. Throwing here (render time) is what makes a misconfigured\n // integration visible instead of quietly answering as the wrong agent.\n resolveAgentProp({ agent });\n\n const clientTools = useStatewireClientTools(frontendToolkit);\n\n // The persisted command lane is keyed by WHO is signed in as well as by host\n // and thread (see `statewireSessionKey`); `null` while the sign-in provider\n // above is still resolving who that is.\n const principal = statewireSessionPrincipal(useContext(AthenaAuthContext));\n\n // Attach → first server snapshot span, keyed per thread attach.\n const attachSpanRef = useRef<ReturnType<AthenaDiagnosticsSpanStarter> | null>(null);\n const attachThreadRef = useRef<string | null>(null);\n if (attachThreadRef.current !== threadId) {\n attachThreadRef.current = threadId;\n attachSpanRef.current = athenaDiagnostics.span(\n `statewire.attach:${threadId}`,\n 'statewire.attach.start',\n { thread_id: threadId, is_new_chat: isNewChat },\n );\n }\n\n // Built every render so its JSON signature can key the model-context\n // registration below: consumers commonly pass fresh array literals per\n // render, which must not thrash registration, while a changed value (a new\n // `model`, channel, tool list, system prompt, …) must re-sync the context\n // before the next send. The core pulls this value only on model-context\n // notifications, which a key change triggers.\n const runConfigValue = buildStatewireRunConfig({\n model,\n agent,\n channel,\n mode,\n tools,\n frontendToolIds,\n workbench,\n knowledgeBase,\n systemPrompt,\n appId,\n extraRunConfig,\n clientTools: statewireClientToolWireEntries(clientTools),\n });\n const runConfigKey = JSON.stringify(runConfigValue);\n\n const auiTools = useMemo(() => Tools({ toolkit: frontendToolkit }), [frontendToolkit]);\n // Web client for the shared runtime core (a `use*` name so the\n // rules-of-hooks lint sees the `useAui` call inside a custom hook; the core\n // invokes it unconditionally every render).\n const useSdkClient = (thread: DeepAgentThreadElement) => useAui({ thread, tools: auiTools });\n\n return useDeepAgentRuntime({\n surface: 'AthenaSDK',\n threadId,\n baseUrl: syncUrl,\n // Option closures are re-read per render by the core, so credential\n // rotation (new `token`/`getToken`/`apiKey` props) reaches the next\n // request without remounting the thread. The transport's `staleAuth`\n // (true right after a refused credential) is forwarded as `force`.\n headers: (ctx) => resolveStatewireAuthHeaders({ apiKey, token, getToken }, ctx),\n isNewChat,\n // Queued entries render in the SDK's queue panel, so only the steer lane\n // projects into the message tail.\n laneProjection: 'steer-only',\n // Durable session: a reload resumes the lane and resends whatever the\n // server has not marked durable. Scoped by host AND principal — a thread\n // id is only meaningful against the backend that minted it, and a stored\n // lane must never resend against another signed-in user. (Consumers\n // server-render this SDK; the core's availability probe keeps those\n // sessions process-local, as before the seam existed.) Until the sign-in\n // provider knows who is signed in, the lane is pending: the transport\n // stays parked and nothing is mounted on a stand-in key\n // (`statewireSessionPrincipal`). A change to another principal remounts\n // the conversation on that principal's lane instead of moving this one\n // there (the runtime's lane epoch), so the previous principal's\n // undelivered commands are never sent as the new one.\n session:\n principal === null\n ? { kind: 'pending' }\n : {\n kind: 'local-storage',\n key: (id) => statewireSessionKey({ syncUrl, principal, threadId: id }),\n },\n snapshotCache,\n // Head interest (see `ATHENA_SDK_MESSAGE_WINDOW`): the tail of the\n // transcript instead of every message; the chat UI's history edge pages\n // older ranges in and fetches cut tool outputs into `toolOutputs`.\n messageWindow,\n toolOutputs,\n // Each `task` card's nested transcript becomes its tool-call part's\n // `messages` (assistant-ui's nested-thread channel), which the subagent\n // card (`SubagentTaskToolUI`) shows.\n createConversionCache: createSubagentTranscriptConversionCache,\n // The lane-cut contract only where the chat pages lanes (see `subagentLaneHistory`).\n laneHistory: subagentLaneHistory,\n capabilities: { edit: true, reload: true, continue: true },\n // The composer stages the draft each send came from right before it\n // sends; the message carries it as its composer markdown, so its bubble\n // shows the text exactly as typed (`UserMessageText`).\n getMessageMetadata: withStagedComposerMarkdown({ threadId }),\n useClient: useSdkClient,\n onStateChange: (state) => {\n // Statewire publishes what the thread renders before its attach snapshot\n // through here too (the placeholder, a remembered snapshot, and a replay\n // boundary's pre-stream default), and on a thread mid-run it reports\n // `connected` before the snapshot applies: only a state the host sent\n // counts, whatever the connection says.\n if (!isDeepAgentHostState(state)) return;\n // The attach's first one ends the attach span (time-to-history).\n const endSpan = attachSpanRef.current;\n if (endSpan) {\n attachSpanRef.current = null;\n endSpan('statewire.snapshot', { data: { thread_id: threadId } });\n }\n onServerState?.(state);\n },\n onConnectionChange: (connection) => {\n athenaDiagnostics.gauge('statewire.connection', connection?.status ?? null);\n if (connection?.status === 'stopped') {\n athenaDiagnostics.emit('statewire.connection', {\n level: 'warn',\n data: {\n status: connection.status,\n reason: connection.reason,\n message: connection.message,\n },\n });\n }\n onConnectionChange?.(connection);\n },\n onRawConnectionChange,\n onRunningChange,\n onSessionPersistedChange,\n ...(onCommandChange && { onCommandChange }),\n // Each model-context notification pulls the latest getter through the\n // core's per-render ref; the value-stable key re-registers (and so\n // notifies) only when the built runConfig actually changed. On a thread\n // with a server config lane, agora keeps only the per-send keys of what\n // this carries; `StatewireThreadConfigLaneSync` writes a changed model,\n // system prompt, tool list, workbench or knowledge base to the lane itself.\n runConfig: {\n get: () => runConfigValue,\n key: runConfigKey,\n },\n onError: (error) => {\n if (!isStatewireChannelTeardown(error)) {\n athenaDiagnostics.error(\n 'statewire.error',\n error,\n {\n code: 'statewire_rejected',\n message: 'The statewire host rejected a command',\n hint: 'Inspect error.detail — agora rejections carry a structured {code, message}.',\n },\n { thread_id: threadId },\n );\n }\n if (onError) {\n onError(error);\n return;\n }\n logUnhandledStatewireError('AthenaSDK', error);\n },\n });\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@athenaintel/react",
3
- "version": "0.55.0",
3
+ "version": "0.56.0",
4
4
  "description": "Athena React SDK — Build AI-powered chat applications with the Athena platform",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -1,279 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const runconfigContract = require("./generated/runconfig-contract.cjs");
4
- const toolNames = require("./tool-names.cjs");
5
- const DEEP_AGENT_HISTORY_PAGE_TURNS = 10;
6
- const DEEP_AGENT_TURN_STEPS_PAGE = 100;
7
- const DEEP_AGENT_TURN_STEPS_KEY = "athena_turn_steps";
8
- const DEEP_AGENT_HISTORY_START_KEY = "athenaHistoryStart";
9
- function isDeepAgentHistoryAtStart(state) {
10
- return isRecord(state) && state[DEEP_AGENT_HISTORY_START_KEY] === true;
11
- }
12
- function buildHistoryPageCommand({
13
- before,
14
- turns = DEEP_AGENT_HISTORY_PAGE_TURNS
15
- }) {
16
- return { type: runconfigContract.DEEP_AGENT_HISTORY_PAGE_COMMAND, before, turns };
17
- }
18
- function buildTurnStepsCommand({
19
- turn,
20
- before,
21
- steps = DEEP_AGENT_TURN_STEPS_PAGE
22
- }) {
23
- return {
24
- type: runconfigContract.DEEP_AGENT_HISTORY_PAGE_COMMAND,
25
- turn,
26
- ...before !== void 0 && { before },
27
- steps
28
- };
29
- }
30
- const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
31
- const isCount = (value) => typeof value === "number" && Number.isInteger(value) && value >= 0;
32
- const isId = (value) => typeof value === "string" && value.length > 0;
33
- function readMessages(value) {
34
- if (!Array.isArray(value)) return null;
35
- for (const message of value) {
36
- if (!isRecord(message) || !isId(message.id) || typeof message.type !== "string") return null;
37
- }
38
- return value;
39
- }
40
- function readMore(value) {
41
- return isRecord(value) && typeof value.before === "boolean" ? { before: value.before } : null;
42
- }
43
- function readSteps(value) {
44
- if (value === null) return null;
45
- if (!isRecord(value)) return void 0;
46
- const { count, tools, delegations, first, last } = value;
47
- if (!isCount(count) || !isCount(tools) || !isCount(delegations)) return void 0;
48
- if (first !== null && !isId(first) || last !== null && !isId(last)) return void 0;
49
- return { count, tools, delegations, first, last };
50
- }
51
- function readHistoryPageAnswer(payload) {
52
- if (!isRecord(payload) || !Array.isArray(payload.turns)) return null;
53
- const more = readMore(payload.more);
54
- if (more === null) return null;
55
- const turns = [];
56
- for (const turn of payload.turns) {
57
- if (!isRecord(turn) || !isId(turn.id)) return null;
58
- const messages = readMessages(turn.messages);
59
- const steps = readSteps(turn.steps);
60
- if (messages === null || steps === void 0) return null;
61
- turns.push({ id: turn.id, messages, steps });
62
- }
63
- return { turns, more };
64
- }
65
- function readTurnStepsAnswer(payload) {
66
- if (!isRecord(payload) || !isId(payload.turn)) return null;
67
- const messages = readMessages(payload.messages);
68
- const more = readMore(payload.more);
69
- if (messages === null || more === null) return null;
70
- return { turn: payload.turn, messages, more };
71
- }
72
- function createDeepAgentHistoryStore() {
73
- let snapshot = null;
74
- const loadingSteps = /* @__PURE__ */ new Set();
75
- const listeners = /* @__PURE__ */ new Set();
76
- const publish = (next) => {
77
- snapshot = next;
78
- for (const listener of listeners) listener();
79
- };
80
- const store = {
81
- getSnapshot: () => snapshot,
82
- subscribe(listener) {
83
- listeners.add(listener);
84
- return () => {
85
- listeners.delete(listener);
86
- };
87
- },
88
- addPage({ threadId, before, beforeIsPrompt, answer }) {
89
- var _a;
90
- const current = snapshot;
91
- const continues = current !== null && current.threadId === threadId && ((_a = current.turns[0]) == null ? void 0 : _a.id) === before;
92
- if (!continues) {
93
- loadingSteps.clear();
94
- publish({
95
- threadId,
96
- anchor: before,
97
- anchorInsideTurn: !beforeIsPrompt,
98
- turns: answer.turns,
99
- more: answer.more.before,
100
- steps: /* @__PURE__ */ new Map()
101
- });
102
- return;
103
- }
104
- const held = new Set(current.turns.map((turn) => turn.id));
105
- publish({
106
- ...current,
107
- turns: [...answer.turns.filter((turn) => !held.has(turn.id)), ...current.turns],
108
- more: answer.more.before
109
- });
110
- },
111
- addSteps({ threadId, answer }) {
112
- const current = snapshot;
113
- if (current === null || current.threadId !== threadId) return;
114
- if (!current.turns.some((turn) => turn.id === answer.turn)) return;
115
- const loaded = current.steps.get(answer.turn);
116
- const held = new Set(loaded == null ? void 0 : loaded.messages.map((message) => message.id));
117
- const steps = new Map(current.steps);
118
- steps.set(answer.turn, {
119
- messages: [
120
- ...answer.messages.filter((message) => !held.has(message.id)),
121
- ...(loaded == null ? void 0 : loaded.messages) ?? []
122
- ],
123
- more: answer.more.before
124
- });
125
- publish({ ...current, steps });
126
- },
127
- isLoadingSteps: (turn) => loadingSteps.has(turn),
128
- setLoadingSteps(turn, loading) {
129
- if (loading) loadingSteps.add(turn);
130
- else loadingSteps.delete(turn);
131
- },
132
- clear() {
133
- loadingSteps.clear();
134
- if (snapshot !== null) publish(null);
135
- },
136
- join({ threadId, live, liveIds }) {
137
- const history = snapshot;
138
- if (history === null || history.turns.length === 0 || isDeepAgentHistoryDetached({ history, threadId, liveIds })) {
139
- return { messages: live, atStart: false };
140
- }
141
- return { messages: joinDeepAgentHistory({ history, threadId, live, liveIds }), atStart: !history.more };
142
- },
143
- isDetached: ({ threadId, liveIds }) => snapshot !== null && isDeepAgentHistoryDetached({ history: snapshot, threadId, liveIds }),
144
- async requestOlder({ send, threadId, before, beforeIsPrompt, turns }) {
145
- const answer = readHistoryPageAnswer(await send(buildHistoryPageCommand({ before, turns })));
146
- if (answer === null) throw new Error("history/page answered in a shape this client cannot read");
147
- store.addPage({ threadId, before, beforeIsPrompt, answer });
148
- return answer.turns.length;
149
- },
150
- async loadSteps({ send, marker }) {
151
- var _a;
152
- const current = snapshot;
153
- if (current === null || marker.hiddenSteps === 0 || loadingSteps.has(marker.turn)) return;
154
- const newestInsideTurn = current.anchorInsideTurn && ((_a = current.turns.at(-1)) == null ? void 0 : _a.id) === marker.turn;
155
- const before = marker.before ?? (newestInsideTurn ? current.anchor : void 0);
156
- loadingSteps.add(marker.turn);
157
- try {
158
- const answer = readTurnStepsAnswer(await send(buildTurnStepsCommand({ turn: marker.turn, before })));
159
- if (answer === null) {
160
- throw new Error("history/page answered steps in a shape this client cannot read");
161
- }
162
- store.addSteps({ threadId: current.threadId, answer });
163
- } finally {
164
- loadingSteps.delete(marker.turn);
165
- }
166
- }
167
- };
168
- return store;
169
- }
170
- function toolCalls(messages) {
171
- let tools = 0;
172
- let delegations = 0;
173
- for (const message of messages) {
174
- if (message.type !== "ai") continue;
175
- for (const call of message.tool_calls ?? []) {
176
- if (toolNames.QUIET_TOOL_NAMES.has(call.name)) continue;
177
- tools += 1;
178
- if (call.name === "task") delegations += 1;
179
- }
180
- }
181
- return { tools, delegations };
182
- }
183
- function readTurnStepsMarker(message) {
184
- if (!isRecord(message) || !isRecord(message.additional_kwargs)) return void 0;
185
- const marker = message.additional_kwargs[DEEP_AGENT_TURN_STEPS_KEY];
186
- if (!isRecord(marker) || !isId(marker.turn)) return void 0;
187
- const { hiddenSteps, hiddenTools, hiddenDelegations, before } = marker;
188
- if (!isCount(hiddenSteps) || !isCount(hiddenTools) || !isCount(hiddenDelegations)) return void 0;
189
- return {
190
- turn: marker.turn,
191
- hiddenSteps,
192
- hiddenTools,
193
- hiddenDelegations,
194
- before: isId(before) ? before : void 0
195
- };
196
- }
197
- const markedCopies = /* @__PURE__ */ new WeakMap();
198
- function withMarker(message, marker) {
199
- const key = JSON.stringify(marker);
200
- const cached = markedCopies.get(message);
201
- if ((cached == null ? void 0 : cached.key) === key) return cached.message;
202
- const kwargs = message.additional_kwargs;
203
- const marked = {
204
- ...message,
205
- additional_kwargs: { ...kwargs ?? {}, [DEEP_AGENT_TURN_STEPS_KEY]: marker }
206
- };
207
- markedCopies.set(message, { key, message: marked });
208
- return marked;
209
- }
210
- function joinDeepAgentHistory({
211
- history,
212
- threadId,
213
- live,
214
- liveIds
215
- }) {
216
- var _a, _b;
217
- if (history === null || history.turns.length === 0 || isDeepAgentHistoryDetached({ history, threadId, liveIds })) {
218
- return live;
219
- }
220
- const joined = [];
221
- let pendingMarker = null;
222
- const markNext = (message) => {
223
- if (pendingMarker === null || message.type !== "ai") return message;
224
- const marked = withMarker(message, pendingMarker);
225
- pendingMarker = null;
226
- return marked;
227
- };
228
- for (const turn of history.turns) {
229
- if (turn.steps === null) {
230
- for (const message of turn.messages) {
231
- if (!liveIds.has(message.id ?? "")) joined.push(message);
232
- }
233
- continue;
234
- }
235
- const loaded = ((_a = history.steps.get(turn.id)) == null ? void 0 : _a.messages) ?? [];
236
- const [first, ...rest] = turn.messages;
237
- const prompt = (first == null ? void 0 : first.type) === "human" ? first : void 0;
238
- const answer = prompt === void 0 ? turn.messages : rest;
239
- const paged = toolCalls(loaded);
240
- pendingMarker = {
241
- turn: turn.id,
242
- hiddenSteps: Math.max(0, turn.steps.count - loaded.length),
243
- hiddenTools: Math.max(0, turn.steps.tools - paged.tools),
244
- hiddenDelegations: Math.max(0, turn.steps.delegations - paged.delegations),
245
- before: (_b = loaded[0]) == null ? void 0 : _b.id
246
- };
247
- for (const message of [...prompt ? [prompt] : [], ...loaded, ...answer]) {
248
- if (liveIds.has(message.id ?? "")) continue;
249
- joined.push(markNext(message));
250
- }
251
- if (pendingMarker !== null && (turn !== history.turns.at(-1) || !history.anchorInsideTurn)) {
252
- pendingMarker = null;
253
- }
254
- }
255
- for (const message of live) joined.push(markNext(message));
256
- return joined;
257
- }
258
- function isDeepAgentHistoryDetached({
259
- history,
260
- threadId,
261
- liveIds
262
- }) {
263
- if (threadId !== void 0 && history.threadId !== threadId) return true;
264
- return liveIds.size > 0 && !liveIds.has(history.anchor);
265
- }
266
- exports.DEEP_AGENT_HISTORY_PAGE_TURNS = DEEP_AGENT_HISTORY_PAGE_TURNS;
267
- exports.DEEP_AGENT_HISTORY_START_KEY = DEEP_AGENT_HISTORY_START_KEY;
268
- exports.DEEP_AGENT_TURN_STEPS_KEY = DEEP_AGENT_TURN_STEPS_KEY;
269
- exports.DEEP_AGENT_TURN_STEPS_PAGE = DEEP_AGENT_TURN_STEPS_PAGE;
270
- exports.buildHistoryPageCommand = buildHistoryPageCommand;
271
- exports.buildTurnStepsCommand = buildTurnStepsCommand;
272
- exports.createDeepAgentHistoryStore = createDeepAgentHistoryStore;
273
- exports.isDeepAgentHistoryAtStart = isDeepAgentHistoryAtStart;
274
- exports.isDeepAgentHistoryDetached = isDeepAgentHistoryDetached;
275
- exports.joinDeepAgentHistory = joinDeepAgentHistory;
276
- exports.readHistoryPageAnswer = readHistoryPageAnswer;
277
- exports.readTurnStepsAnswer = readTurnStepsAnswer;
278
- exports.readTurnStepsMarker = readTurnStepsMarker;
279
- //# sourceMappingURL=history-pages.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"history-pages.cjs","sources":["../../../../agent-runtime/src/history-pages.ts"],"sourcesContent":["import type { LangChainMessage } from '@assistant-ui/react-langgraph';\nimport { DEEP_AGENT_HISTORY_PAGE_COMMAND } from './generated/runconfig-contract';\nimport { QUIET_TOOL_NAMES } from './tool-names';\n\n/**\n * Older history by command, a turn at a time — the client half of agora's\n * `history_page.py` (protocol 3, `docs/plans/2026-11-03-history-by-command-plan.md`).\n *\n * A host advertising `DEEP_AGENT_HISTORY_PAGE_PROTOCOL_VERSION` answers\n * `history/page` with whole turns older than a message the client holds, as a\n * command result: nothing is mounted in the attach's view, so no interest\n * document grows with how far back a reader goes, and a re-attach restates\n * nothing it paged. The client keeps the answers in a\n * {@link DeepAgentHistoryStore} and joins them in front of the live window\n * ({@link joinDeepAgentHistory}).\n *\n * A turn longer than the host's whole-turn limit rides as its prompt and its\n * answer, with `steps` counting what it left out; `history/page` with a\n * `turn` pages those steps newest first. The join marks each summarized turn\n * on a source message ({@link DEEP_AGENT_TURN_STEPS_KEY}) so a renderer reads\n * the turn's exact counts, and inserts the steps fetched so far between the\n * prompt and the answer.\n */\n\n/** Turns one `history/page` asks for. */\nexport const DEEP_AGENT_HISTORY_PAGE_TURNS = 10;\n/** Steps of one turn one `history/page` asks for. */\nexport const DEEP_AGENT_TURN_STEPS_PAGE = 100;\n/** `additional_kwargs` key the join marks a summarized turn's first reply message with. */\nexport const DEEP_AGENT_TURN_STEPS_KEY = 'athena_turn_steps';\n/**\n * Key on the composed thread state (`useDeepAgentThread`'s converter) set when\n * the paged turns joined in front of the window reach the transcript's start:\n * the live window's own `hasOlder` still says older messages exist, so an\n * edit's anchor search reads this to know the first message has no parent.\n */\nexport const DEEP_AGENT_HISTORY_START_KEY = 'athenaHistoryStart';\n\n/** Whether a composed thread state says its messages start at the transcript's start. */\nexport function isDeepAgentHistoryAtStart(state: unknown): boolean {\n return isRecord(state) && state[DEEP_AGENT_HISTORY_START_KEY] === true;\n}\n\n/** What a summarized turn's page left out (the host's `steps`). */\nexport interface DeepAgentHistoryTurnSteps {\n /** Messages left out. */\n count: number;\n /** Tool calls among the messages left out (a renderer adds the ones it holds). */\n tools: number;\n /** Of which `task` delegations. */\n delegations: number;\n first: string | null;\n last: string | null;\n}\n\n/** One turn of a `history/page` answer. */\nexport interface DeepAgentHistoryTurn {\n /** The turn's first message (its prompt), the id its steps are paged by. */\n id: string;\n /** What the page shows of it, oldest first: the prompt and the answer, or the whole turn. */\n messages: LangChainMessage[];\n /** What it left out, or `null` when the turn rides whole. */\n steps: DeepAgentHistoryTurnSteps | null;\n}\n\nexport interface DeepAgentHistoryPageAnswer {\n turns: DeepAgentHistoryTurn[];\n more: { before: boolean };\n}\n\nexport interface DeepAgentTurnStepsAnswer {\n turn: string;\n /** Steps, oldest first. */\n messages: LangChainMessage[];\n more: { before: boolean };\n}\n\n/** The `history/page` command asking for turns older than `before`. */\nexport interface HistoryPageCommand {\n readonly type: typeof DEEP_AGENT_HISTORY_PAGE_COMMAND;\n readonly before: string;\n readonly turns: number;\n}\n\n/** The `history/page` command asking for one turn's steps older than `before`. */\nexport interface TurnStepsCommand {\n readonly type: typeof DEEP_AGENT_HISTORY_PAGE_COMMAND;\n readonly turn: string;\n readonly before?: string;\n readonly steps: number;\n}\n\ndeclare module '@assistant-ui/core' {\n namespace Assistant {\n interface Commands {\n /** Older turns, outside the attach's view. */\n historyPage: HistoryPageCommand;\n /** One summarized turn's steps. */\n historyTurnSteps: TurnStepsCommand;\n }\n }\n}\n\nexport function buildHistoryPageCommand({\n before,\n turns = DEEP_AGENT_HISTORY_PAGE_TURNS,\n}: {\n before: string;\n turns?: number;\n}): HistoryPageCommand {\n return { type: DEEP_AGENT_HISTORY_PAGE_COMMAND, before, turns };\n}\n\nexport function buildTurnStepsCommand({\n turn,\n before,\n steps = DEEP_AGENT_TURN_STEPS_PAGE,\n}: {\n turn: string;\n before?: string | undefined;\n steps?: number;\n}): TurnStepsCommand {\n return {\n type: DEEP_AGENT_HISTORY_PAGE_COMMAND,\n turn,\n ...(before !== undefined && { before }),\n steps,\n };\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\nconst isCount = (value: unknown): value is number =>\n typeof value === 'number' && Number.isInteger(value) && value >= 0;\nconst isId = (value: unknown): value is string => typeof value === 'string' && value.length > 0;\n\nfunction readMessages(value: unknown): LangChainMessage[] | null {\n if (!Array.isArray(value)) return null;\n for (const message of value) {\n if (!isRecord(message) || !isId(message.id) || typeof message.type !== 'string') return null;\n }\n return value as LangChainMessage[];\n}\n\nfunction readMore(value: unknown): { before: boolean } | null {\n return isRecord(value) && typeof value.before === 'boolean' ? { before: value.before } : null;\n}\n\nfunction readSteps(value: unknown): DeepAgentHistoryTurnSteps | null | undefined {\n if (value === null) return null;\n if (!isRecord(value)) return undefined;\n const { count, tools, delegations, first, last } = value;\n if (!isCount(count) || !isCount(tools) || !isCount(delegations)) return undefined;\n if ((first !== null && !isId(first)) || (last !== null && !isId(last))) return undefined;\n return { count, tools, delegations, first, last };\n}\n\n/** A `history/page` answer to `{before, turns}`, or `null` when it is malformed. */\nexport function readHistoryPageAnswer(payload: unknown): DeepAgentHistoryPageAnswer | null {\n if (!isRecord(payload) || !Array.isArray(payload.turns)) return null;\n const more = readMore(payload.more);\n if (more === null) return null;\n const turns: DeepAgentHistoryTurn[] = [];\n for (const turn of payload.turns) {\n if (!isRecord(turn) || !isId(turn.id)) return null;\n const messages = readMessages(turn.messages);\n const steps = readSteps(turn.steps);\n if (messages === null || steps === undefined) return null;\n turns.push({ id: turn.id, messages, steps });\n }\n return { turns, more };\n}\n\n/** A `history/page` answer to `{turn, before?, steps}`, or `null` when it is malformed. */\nexport function readTurnStepsAnswer(payload: unknown): DeepAgentTurnStepsAnswer | null {\n if (!isRecord(payload) || !isId(payload.turn)) return null;\n const messages = readMessages(payload.messages);\n const more = readMore(payload.more);\n if (messages === null || more === null) return null;\n return { turn: payload.turn, messages, more };\n}\n\n/** The steps of one summarized turn fetched so far, oldest first. */\nexport interface DeepAgentHistoryTurnStepsLoaded {\n messages: LangChainMessage[];\n /** Older steps of the turn remain. */\n more: boolean;\n}\n\n/** The turns one conversation has paged in, in front of its live window. */\nexport interface DeepAgentHistorySnapshot {\n /** The conversation they belong to. */\n threadId: string;\n /** The message the first page was asked `before`: the live window's first message then. */\n anchor: string;\n /** Whether the anchor is a reply rather than a prompt: the newest turn's rest is in the live window. */\n anchorInsideTurn: boolean;\n /** Turns, oldest first. */\n turns: DeepAgentHistoryTurn[];\n /** Older turns remain beyond the first. */\n more: boolean;\n /** Steps fetched per summarized turn id. */\n steps: ReadonlyMap<string, DeepAgentHistoryTurnStepsLoaded>;\n}\n\n/** How a store asks the host: the thread's `sendCommand` (its answer, the command's payload). */\nexport type DeepAgentHistorySend = (command: HistoryPageCommand | TurnStepsCommand) => unknown;\n\n/**\n * The history paged in for the open conversation: a subscribable store the\n * thread's converter joins in front of its live window and the window sync\n * fills. One per provider, like the tool-output store; it holds one\n * conversation at a time and resets when another one pages.\n *\n * Everything history pages do runs through the store's methods, so a surface\n * that creates no store (it never pages by command) bundles none of it: the\n * shared thread and window sync only call `historyPages?.…`.\n */\nexport interface DeepAgentHistoryStore {\n /** The current snapshot (a new object on every change), or `null` when empty. */\n getSnapshot(): DeepAgentHistorySnapshot | null;\n subscribe(listener: () => void): () => void;\n /**\n * Adds a page asked `before` a message. A page for another conversation, or\n * asked before a message other than the oldest turn held, starts over.\n */\n addPage(page: {\n threadId: string;\n before: string;\n beforeIsPrompt: boolean;\n answer: DeepAgentHistoryPageAnswer;\n }): void;\n /** Adds one summarized turn's older steps. */\n addSteps(steps: { threadId: string; answer: DeepAgentTurnStepsAnswer }): void;\n /** Whether a steps request for the turn is in flight — the loader's dedupe. */\n isLoadingSteps(turn: string): boolean;\n setLoadingSteps(turn: string, loading: boolean): void;\n clear(): void;\n /**\n * The transcript to render: the held turns joined in front of the live\n * window ({@link joinDeepAgentHistory}), and whether they reach the\n * transcript's start (`more.before` false). `live` alone, `atStart` false,\n * while nothing held meets the window.\n */\n join(options: {\n threadId: string | undefined;\n live: LangChainMessage[];\n liveIds: ReadonlySet<string>;\n }): { messages: LangChainMessage[]; atStart: boolean };\n /** Whether the held turns no longer meet the live window ({@link isDeepAgentHistoryDetached}). */\n isDetached(options: { threadId: string | undefined; liveIds: ReadonlySet<string> }): boolean;\n /**\n * Asks the host for the turns before `before` and adds them; resolves how\n * many it answered. Rejects with the host's refusal, or when the answer is\n * not a page this client reads.\n */\n requestOlder(options: {\n send: DeepAgentHistorySend;\n threadId: string;\n before: string;\n beforeIsPrompt: boolean;\n turns?: number;\n }): Promise<number>;\n /**\n * Fetches a summarized turn's next older steps (`history/page` with its\n * `turn`) into the store, newest first. A turn already loading, or with no\n * steps left, is a no-op. Rejects with the host's refusal.\n */\n loadSteps(options: { send: DeepAgentHistorySend; marker: DeepAgentTurnStepsMarker }): Promise<void>;\n}\n\nexport function createDeepAgentHistoryStore(): DeepAgentHistoryStore {\n let snapshot: DeepAgentHistorySnapshot | null = null;\n const loadingSteps = new Set<string>();\n const listeners = new Set<() => void>();\n const publish = (next: DeepAgentHistorySnapshot | null) => {\n snapshot = next;\n for (const listener of listeners) listener();\n };\n const store: DeepAgentHistoryStore = {\n getSnapshot: () => snapshot,\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n addPage({ threadId, before, beforeIsPrompt, answer }) {\n const current = snapshot;\n const continues =\n current !== null && current.threadId === threadId && current.turns[0]?.id === before;\n if (!continues) {\n loadingSteps.clear();\n publish({\n threadId,\n anchor: before,\n anchorInsideTurn: !beforeIsPrompt,\n turns: answer.turns,\n more: answer.more.before,\n steps: new Map(),\n });\n return;\n }\n const held = new Set(current.turns.map((turn) => turn.id));\n publish({\n ...current,\n turns: [...answer.turns.filter((turn) => !held.has(turn.id)), ...current.turns],\n more: answer.more.before,\n });\n },\n addSteps({ threadId, answer }) {\n const current = snapshot;\n if (current === null || current.threadId !== threadId) return;\n if (!current.turns.some((turn) => turn.id === answer.turn)) return;\n const loaded = current.steps.get(answer.turn);\n const held = new Set(loaded?.messages.map((message) => message.id));\n const steps = new Map(current.steps);\n steps.set(answer.turn, {\n messages: [\n ...answer.messages.filter((message) => !held.has(message.id)),\n ...(loaded?.messages ?? []),\n ],\n more: answer.more.before,\n });\n publish({ ...current, steps });\n },\n isLoadingSteps: (turn) => loadingSteps.has(turn),\n setLoadingSteps(turn, loading) {\n if (loading) loadingSteps.add(turn);\n else loadingSteps.delete(turn);\n },\n clear() {\n loadingSteps.clear();\n if (snapshot !== null) publish(null);\n },\n join({ threadId, live, liveIds }) {\n const history = snapshot;\n if (history === null || history.turns.length === 0 || isDeepAgentHistoryDetached({ history, threadId, liveIds })) {\n return { messages: live, atStart: false };\n }\n return { messages: joinDeepAgentHistory({ history, threadId, live, liveIds }), atStart: !history.more };\n },\n isDetached: ({ threadId, liveIds }) =>\n snapshot !== null && isDeepAgentHistoryDetached({ history: snapshot, threadId, liveIds }),\n async requestOlder({ send, threadId, before, beforeIsPrompt, turns }) {\n const answer = readHistoryPageAnswer(await send(buildHistoryPageCommand({ before, turns })));\n if (answer === null) throw new Error('history/page answered in a shape this client cannot read');\n store.addPage({ threadId, before, beforeIsPrompt, answer });\n return answer.turns.length;\n },\n async loadSteps({ send, marker }) {\n const current = snapshot;\n if (current === null || marker.hiddenSteps === 0 || loadingSteps.has(marker.turn)) return;\n // The newest turn of a page asked inside a turn: its later steps are in\n // the live window, so the steps it left out end at the page's anchor.\n const newestInsideTurn = current.anchorInsideTurn && current.turns.at(-1)?.id === marker.turn;\n const before = marker.before ?? (newestInsideTurn ? current.anchor : undefined);\n loadingSteps.add(marker.turn);\n try {\n const answer = readTurnStepsAnswer(await send(buildTurnStepsCommand({ turn: marker.turn, before })));\n if (answer === null) {\n throw new Error('history/page answered steps in a shape this client cannot read');\n }\n store.addSteps({ threadId: current.threadId, answer });\n } finally {\n loadingSteps.delete(marker.turn);\n }\n },\n };\n return store;\n}\n\n/**\n * The marker the join puts on a summarized turn's first reply message: the\n * turn's steps it has not shown yet, so a renderer reads exact counts (\"Used\n * 313 tools\") and knows whether opening it has steps to fetch.\n */\nexport interface DeepAgentTurnStepsMarker {\n /** The turn's first message: the id its steps are paged by. */\n turn: string;\n /** Steps not loaded yet. */\n hiddenSteps: number;\n /** Tool calls among them. */\n hiddenTools: number;\n /** Of which `task` delegations. */\n hiddenDelegations: number;\n /** The oldest step loaded, the next steps request's `before`. */\n before: string | undefined;\n}\n\n/**\n * The tool calls among `messages` the converter shows. The host counts every\n * call of a turn; a quiet call (`QUIET_TOOL_NAMES`) never renders, so it stays\n * in the hidden count once loaded and the turn's total holds still as its\n * steps load.\n */\nfunction toolCalls(messages: readonly LangChainMessage[]): { tools: number; delegations: number } {\n let tools = 0;\n let delegations = 0;\n for (const message of messages) {\n if (message.type !== 'ai') continue;\n for (const call of message.tool_calls ?? []) {\n if (QUIET_TOOL_NAMES.has(call.name)) continue;\n tools += 1;\n if (call.name === 'task') delegations += 1;\n }\n }\n return { tools, delegations };\n}\n\n/** The marker a join put on a source message, or `undefined`. */\nexport function readTurnStepsMarker(message: unknown): DeepAgentTurnStepsMarker | undefined {\n if (!isRecord(message) || !isRecord(message.additional_kwargs)) return undefined;\n const marker = message.additional_kwargs[DEEP_AGENT_TURN_STEPS_KEY];\n if (!isRecord(marker) || !isId(marker.turn)) return undefined;\n const { hiddenSteps, hiddenTools, hiddenDelegations, before } = marker;\n if (!isCount(hiddenSteps) || !isCount(hiddenTools) || !isCount(hiddenDelegations)) return undefined;\n return {\n turn: marker.turn,\n hiddenSteps,\n hiddenTools,\n hiddenDelegations,\n before: isId(before) ? before : undefined,\n };\n}\n\n/** The marked copy of a message, reused while the message and its marker are the same. */\nconst markedCopies = new WeakMap<object, { key: string; message: LangChainMessage }>();\n\nfunction withMarker(message: LangChainMessage, marker: DeepAgentTurnStepsMarker): LangChainMessage {\n const key = JSON.stringify(marker);\n const cached = markedCopies.get(message);\n if (cached?.key === key) return cached.message;\n // Every wire message carries `additional_kwargs` in practice; the upstream\n // type leaves it off tool messages.\n const kwargs = (message as { additional_kwargs?: Record<string, unknown> }).additional_kwargs;\n const marked = {\n ...message,\n additional_kwargs: { ...(kwargs ?? {}), [DEEP_AGENT_TURN_STEPS_KEY]: marker },\n } as LangChainMessage;\n markedCopies.set(message, { key, message: marked });\n return marked;\n}\n\n/**\n * The transcript a converter renders: the paged turns in front of the live\n * window, when they still meet it.\n *\n * The paged turns end just before the snapshot's anchor. While the anchor is\n * in `live`, they are joined in front of it, minus any message `live` already\n * holds (a reveal or an edit paged an interest page over the same range). When\n * the anchor has left the live window (an edit rewound past it, a branch\n * switch), the pages describe another transcript: `live` is returned alone,\n * and {@link isDeepAgentHistoryDetached} tells the window sync to clear them.\n *\n * Each summarized turn gets its fetched steps between its prompt and its\n * answer, and its first reply message the {@link DeepAgentTurnStepsMarker}.\n * The newest turn of a page asked inside a turn has its rest in `live`, so its\n * marker lands on the first live message after its prompt.\n */\nexport function joinDeepAgentHistory({\n history,\n threadId,\n live,\n liveIds,\n}: {\n history: DeepAgentHistorySnapshot | null;\n threadId: string | undefined;\n live: LangChainMessage[];\n /** The live window's chain ids; the anchor must be among them. */\n liveIds: ReadonlySet<string>;\n}): LangChainMessage[] {\n if (history === null || history.turns.length === 0 || isDeepAgentHistoryDetached({ history, threadId, liveIds })) {\n return live;\n }\n const joined: LangChainMessage[] = [];\n let pendingMarker: DeepAgentTurnStepsMarker | null = null;\n // The marker rides an assistant message: a tool result whose call is older\n // than what is loaded (a head that starts on one) converts to no row.\n const markNext = (message: LangChainMessage): LangChainMessage => {\n if (pendingMarker === null || message.type !== 'ai') return message;\n const marked = withMarker(message, pendingMarker);\n pendingMarker = null;\n return marked;\n };\n for (const turn of history.turns) {\n if (turn.steps === null) {\n for (const message of turn.messages) {\n if (!liveIds.has(message.id ?? '')) joined.push(message);\n }\n continue;\n }\n const loaded = history.steps.get(turn.id)?.messages ?? [];\n const [first, ...rest] = turn.messages;\n const prompt = first?.type === 'human' ? first : undefined;\n const answer = prompt === undefined ? turn.messages : rest;\n // The host counts only the messages the page left out; of those, the\n // steps paged in since render on their own, so they leave the hidden count.\n const paged = toolCalls(loaded);\n pendingMarker = {\n turn: turn.id,\n hiddenSteps: Math.max(0, turn.steps.count - loaded.length),\n hiddenTools: Math.max(0, turn.steps.tools - paged.tools),\n hiddenDelegations: Math.max(0, turn.steps.delegations - paged.delegations),\n before: loaded[0]?.id,\n };\n for (const message of [...(prompt ? [prompt] : []), ...loaded, ...answer]) {\n if (liveIds.has(message.id ?? '')) continue;\n joined.push(markNext(message));\n }\n // A summarized turn with no reply shown carries its marker no further,\n // except the newest one of a page asked inside a turn: its rest is live.\n if (pendingMarker !== null && (turn !== history.turns.at(-1) || !history.anchorInsideTurn)) {\n pendingMarker = null;\n }\n }\n for (const message of live) joined.push(markNext(message));\n return joined;\n}\n\n/** Whether the paged turns no longer meet the live window: another conversation, or the anchor left it. */\nexport function isDeepAgentHistoryDetached({\n history,\n threadId,\n liveIds,\n}: {\n history: DeepAgentHistorySnapshot;\n threadId: string | undefined;\n liveIds: ReadonlySet<string>;\n}): boolean {\n if (threadId !== undefined && history.threadId !== threadId) return true;\n return liveIds.size > 0 && !liveIds.has(history.anchor);\n}\n"],"names":["DEEP_AGENT_HISTORY_PAGE_COMMAND","QUIET_TOOL_NAMES"],"mappings":"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"}