@athenaintel/react 0.41.3 → 0.42.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +102 -9
- package/dist/agent-runtime/src/asset-attachment.d.ts +98 -0
- package/dist/agent-runtime/src/athena-asset-drag.d.ts +32 -0
- package/dist/agent-runtime/src/auth-denial.d.ts +29 -0
- package/dist/agent-runtime/src/chat-outbox-attachments.cjs +41 -0
- package/dist/agent-runtime/src/chat-outbox-attachments.cjs.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-attachments.d.ts +38 -0
- package/dist/agent-runtime/src/chat-outbox-attachments.js +41 -0
- package/dist/agent-runtime/src/chat-outbox-attachments.js.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-signals.cjs +63 -0
- package/dist/agent-runtime/src/chat-outbox-signals.cjs.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-signals.d.ts +12 -0
- package/dist/agent-runtime/src/chat-outbox-signals.js +63 -0
- package/dist/agent-runtime/src/chat-outbox-signals.js.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-store.cjs +509 -0
- package/dist/agent-runtime/src/chat-outbox-store.cjs.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-store.d.ts +203 -0
- package/dist/agent-runtime/src/chat-outbox-store.js +509 -0
- package/dist/agent-runtime/src/chat-outbox-store.js.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-thread.cjs +136 -0
- package/dist/agent-runtime/src/chat-outbox-thread.cjs.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-thread.d.ts +118 -0
- package/dist/agent-runtime/src/chat-outbox-thread.js +136 -0
- package/dist/agent-runtime/src/chat-outbox-thread.js.map +1 -0
- package/dist/agent-runtime/src/chat-outbox.cjs +696 -0
- package/dist/agent-runtime/src/chat-outbox.cjs.map +1 -0
- package/dist/agent-runtime/src/chat-outbox.d.ts +285 -0
- package/dist/agent-runtime/src/chat-outbox.js +696 -0
- package/dist/agent-runtime/src/chat-outbox.js.map +1 -0
- package/dist/agent-runtime/src/chat-socket-reachability.d.ts +45 -0
- package/dist/agent-runtime/src/client-tool-bridge.d.ts +152 -0
- package/dist/agent-runtime/src/client-tools.d.ts +133 -0
- package/dist/agent-runtime/src/composer-markdown.cjs +10 -0
- package/dist/agent-runtime/src/composer-markdown.cjs.map +1 -1
- package/dist/agent-runtime/src/composer-markdown.d.ts +108 -0
- package/dist/agent-runtime/src/composer-markdown.js +10 -0
- package/dist/agent-runtime/src/composer-markdown.js.map +1 -1
- package/dist/agent-runtime/src/config-mutations.d.ts +51 -0
- package/dist/agent-runtime/src/conversation-index.d.ts +110 -0
- package/dist/agent-runtime/src/conversation-list.d.ts +343 -0
- package/dist/agent-runtime/src/deep-agent-transport-recipe.cjs +3 -2
- package/dist/agent-runtime/src/deep-agent-transport-recipe.cjs.map +1 -1
- package/dist/agent-runtime/src/deep-agent-transport-recipe.d.ts +166 -0
- package/dist/agent-runtime/src/deep-agent-transport-recipe.js +3 -2
- package/dist/agent-runtime/src/deep-agent-transport-recipe.js.map +1 -1
- package/dist/agent-runtime/src/desktop-handoff.d.ts +139 -0
- package/dist/agent-runtime/src/durable-thread-snapshot-cache.d.ts +60 -0
- package/dist/agent-runtime/src/edit-command.d.ts +156 -0
- package/dist/agent-runtime/src/errors.d.ts +174 -0
- package/dist/agent-runtime/src/execute-output.d.ts +31 -0
- package/dist/agent-runtime/src/generated/runconfig-contract.cjs +16 -2
- package/dist/agent-runtime/src/generated/runconfig-contract.cjs.map +1 -1
- package/dist/agent-runtime/src/generated/runconfig-contract.d.ts +202 -0
- package/dist/agent-runtime/src/generated/runconfig-contract.js +16 -2
- package/dist/agent-runtime/src/generated/runconfig-contract.js.map +1 -1
- package/dist/agent-runtime/src/github-wake-event.d.ts +77 -0
- package/dist/agent-runtime/src/index.d.ts +74 -0
- package/dist/agent-runtime/src/interrupts.cjs +17 -0
- package/dist/agent-runtime/src/interrupts.cjs.map +1 -1
- package/dist/agent-runtime/src/interrupts.d.ts +348 -0
- package/dist/agent-runtime/src/interrupts.js +17 -0
- package/dist/agent-runtime/src/interrupts.js.map +1 -1
- package/dist/agent-runtime/src/lane-follow.d.ts +121 -0
- package/dist/agent-runtime/src/lane-history.cjs +209 -0
- package/dist/agent-runtime/src/lane-history.cjs.map +1 -0
- package/dist/agent-runtime/src/lane-history.d.ts +175 -0
- package/dist/agent-runtime/src/lane-history.js +209 -0
- package/dist/agent-runtime/src/lane-history.js.map +1 -0
- package/dist/agent-runtime/src/lane-images.d.ts +184 -0
- package/dist/agent-runtime/src/message-author.d.ts +43 -0
- package/dist/agent-runtime/src/message-text.cjs +15 -0
- package/dist/agent-runtime/src/message-text.cjs.map +1 -0
- package/dist/agent-runtime/src/message-text.d.ts +47 -0
- package/dist/agent-runtime/src/message-text.js +15 -0
- package/dist/agent-runtime/src/message-text.js.map +1 -0
- package/dist/agent-runtime/src/message-window.cjs +15 -1
- package/dist/agent-runtime/src/message-window.cjs.map +1 -1
- package/dist/agent-runtime/src/message-window.d.ts +159 -0
- package/dist/agent-runtime/src/message-window.js +16 -2
- package/dist/agent-runtime/src/message-window.js.map +1 -1
- package/dist/agent-runtime/src/messages.cjs +88 -4
- package/dist/agent-runtime/src/messages.cjs.map +1 -1
- package/dist/agent-runtime/src/messages.d.ts +603 -0
- package/dist/agent-runtime/src/messages.js +88 -4
- package/dist/agent-runtime/src/messages.js.map +1 -1
- package/dist/agent-runtime/src/model-context.d.ts +22 -0
- package/dist/agent-runtime/src/offline-status.d.ts +157 -0
- package/dist/agent-runtime/src/optimistic-content.d.ts +21 -0
- package/dist/agent-runtime/src/protocol.cjs +12 -4
- package/dist/agent-runtime/src/protocol.cjs.map +1 -1
- package/dist/agent-runtime/src/protocol.d.ts +119 -0
- package/dist/agent-runtime/src/protocol.js +13 -5
- package/dist/agent-runtime/src/protocol.js.map +1 -1
- package/dist/agent-runtime/src/ptc-subcalls.d.ts +51 -0
- package/dist/agent-runtime/src/queue.d.ts +138 -0
- package/dist/agent-runtime/src/quota-safe-local-storage-session.d.ts +154 -0
- package/dist/agent-runtime/src/running-tool-placeholder.cjs +11 -0
- package/dist/agent-runtime/src/running-tool-placeholder.cjs.map +1 -0
- package/dist/agent-runtime/src/running-tool-placeholder.d.ts +25 -0
- package/dist/agent-runtime/src/running-tool-placeholder.js +11 -0
- package/dist/agent-runtime/src/running-tool-placeholder.js.map +1 -0
- package/dist/agent-runtime/src/runtime-messages.d.ts +104 -0
- package/dist/agent-runtime/src/screen-point.d.ts +151 -0
- package/dist/agent-runtime/src/sealed-idb.cjs +112 -0
- package/dist/agent-runtime/src/sealed-idb.cjs.map +1 -0
- package/dist/agent-runtime/src/sealed-idb.d.ts +106 -0
- package/dist/agent-runtime/src/sealed-idb.js +112 -0
- package/dist/agent-runtime/src/sealed-idb.js.map +1 -0
- package/dist/agent-runtime/src/send-recovery.d.ts +40 -0
- package/dist/agent-runtime/src/statewire-attach-observer.d.ts +194 -0
- package/dist/agent-runtime/src/statewire-diagnostics.d.ts +74 -0
- package/dist/agent-runtime/src/statewire-state.d.ts +29 -0
- package/dist/agent-runtime/src/statewire-suspended.cjs.map +1 -1
- package/dist/agent-runtime/src/statewire-suspended.d.ts +27 -0
- package/dist/agent-runtime/src/statewire-suspended.js.map +1 -1
- package/dist/agent-runtime/src/statewire-transport.d.ts +40 -0
- package/dist/agent-runtime/src/streaming-markdown.d.ts +46 -0
- package/dist/agent-runtime/src/subagent-transcripts.cjs +209 -0
- package/dist/agent-runtime/src/subagent-transcripts.cjs.map +1 -0
- package/dist/agent-runtime/src/subagent-transcripts.d.ts +71 -0
- package/dist/agent-runtime/src/subagent-transcripts.js +209 -0
- package/dist/agent-runtime/src/subagent-transcripts.js.map +1 -0
- package/dist/agent-runtime/src/subagents.cjs +253 -0
- package/dist/agent-runtime/src/subagents.cjs.map +1 -0
- package/dist/agent-runtime/src/subagents.d.ts +311 -0
- package/dist/agent-runtime/src/subagents.js +253 -0
- package/dist/agent-runtime/src/subagents.js.map +1 -0
- package/dist/agent-runtime/src/subscription-wake-event.d.ts +111 -0
- package/dist/agent-runtime/src/thread-extras.d.ts +43 -0
- package/dist/agent-runtime/src/thread-handoff.d.ts +364 -0
- package/dist/agent-runtime/src/thread-prewarm-controller.d.ts +76 -0
- package/dist/agent-runtime/src/thread-prewarm.d.ts +118 -0
- package/dist/agent-runtime/src/thread-snapshot-cache.d.ts +99 -0
- package/dist/agent-runtime/src/thread-snapshot-mirror.cjs +46 -117
- package/dist/agent-runtime/src/thread-snapshot-mirror.cjs.map +1 -1
- package/dist/agent-runtime/src/thread-snapshot-mirror.d.ts +101 -0
- package/dist/agent-runtime/src/thread-snapshot-mirror.js +17 -88
- package/dist/agent-runtime/src/thread-snapshot-mirror.js.map +1 -1
- package/dist/agent-runtime/src/thread-status.d.ts +53 -0
- package/dist/agent-runtime/src/tool-metadata.d.ts +146 -0
- package/dist/agent-runtime/src/tool-names.cjs +67 -0
- package/dist/agent-runtime/src/tool-names.cjs.map +1 -1
- package/dist/agent-runtime/src/tool-names.d.ts +60 -0
- package/dist/agent-runtime/src/tool-names.js +68 -1
- package/dist/agent-runtime/src/tool-names.js.map +1 -1
- package/dist/agent-runtime/src/tool-outputs.d.ts +35 -0
- package/dist/agent-runtime/src/tool-result.cjs +1 -0
- package/dist/agent-runtime/src/tool-result.cjs.map +1 -1
- package/dist/agent-runtime/src/tool-result.d.ts +126 -0
- package/dist/agent-runtime/src/tool-result.js +1 -0
- package/dist/agent-runtime/src/tool-result.js.map +1 -1
- package/dist/agent-runtime/src/types.d.ts +159 -0
- package/dist/agent-runtime/src/use-conversation-list.d.ts +76 -0
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.cjs +136 -0
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.cjs.map +1 -0
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.d.ts +64 -0
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.js +136 -0
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.js.map +1 -0
- package/dist/agent-runtime/src/use-deep-agent-config.d.ts +169 -0
- package/dist/agent-runtime/src/use-deep-agent-edit-submit.cjs +13 -0
- package/dist/agent-runtime/src/use-deep-agent-edit-submit.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-edit-submit.d.ts +22 -0
- package/dist/agent-runtime/src/use-deep-agent-edit-submit.js +13 -0
- package/dist/agent-runtime/src/use-deep-agent-edit-submit.js.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-runtime.cjs +20 -2
- package/dist/agent-runtime/src/use-deep-agent-runtime.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-runtime.d.ts +168 -0
- package/dist/agent-runtime/src/use-deep-agent-runtime.js +20 -2
- package/dist/agent-runtime/src/use-deep-agent-runtime.js.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-thread.cjs +12 -4
- package/dist/agent-runtime/src/use-deep-agent-thread.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-thread.d.ts +320 -0
- package/dist/agent-runtime/src/use-deep-agent-thread.js +12 -4
- package/dist/agent-runtime/src/use-deep-agent-thread.js.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-voice.cjs +999 -0
- package/dist/agent-runtime/src/use-deep-agent-voice.cjs.map +1 -0
- package/dist/agent-runtime/src/use-deep-agent-voice.d.ts +409 -0
- package/dist/agent-runtime/src/use-deep-agent-voice.js +999 -0
- package/dist/agent-runtime/src/use-deep-agent-voice.js.map +1 -0
- package/dist/agent-runtime/src/use-deep-agent-window-sync.d.ts +102 -0
- package/dist/agent-runtime/src/use-historical-edit-attachments.d.ts +2 -0
- package/dist/agent-runtime/src/use-thread-handoff-flow.d.ts +84 -0
- package/dist/agent-runtime/src/voice-presentation.d.ts +80 -0
- package/dist/agent-runtime/src/voice-turn-grouping.d.ts +28 -0
- package/dist/agent-runtime/src/voice-wire-types.d.ts +15 -0
- package/dist/agent-runtime/src/withdrawn-turns.d.ts +97 -0
- package/dist/chat/AthenaChat.cjs +72 -5
- package/dist/chat/AthenaChat.cjs.map +1 -1
- package/dist/chat/AthenaChat.js +73 -6
- package/dist/chat/AthenaChat.js.map +1 -1
- package/dist/chat/StatewireApprovalCard.d.ts +1 -1
- package/dist/chat/StatewireClientToolBridge.d.ts +1 -1
- package/dist/chat/StatewireQueuedMessages.cjs +11 -4
- package/dist/chat/StatewireQueuedMessages.cjs.map +1 -1
- package/dist/chat/StatewireQueuedMessages.d.ts +1 -1
- package/dist/chat/StatewireQueuedMessages.js +11 -4
- package/dist/chat/StatewireQueuedMessages.js.map +1 -1
- package/dist/chat/chat-outbox-rows.cjs +223 -0
- package/dist/chat/chat-outbox-rows.cjs.map +1 -0
- package/dist/chat/chat-outbox-rows.d.ts +29 -0
- package/dist/chat/chat-outbox-rows.js +223 -0
- package/dist/chat/chat-outbox-rows.js.map +1 -0
- package/dist/chat/statewire-approval.d.ts +1 -1
- package/dist/chat/statewire-client-tools.d.ts +1 -1
- package/dist/chat/super-grouping/SuperGroupingCard.cjs +3 -1
- package/dist/chat/super-grouping/SuperGroupingCard.cjs.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingCard.d.ts +7 -1
- package/dist/chat/super-grouping/SuperGroupingCard.js +3 -1
- package/dist/chat/super-grouping/SuperGroupingCard.js.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingTranscript.cjs +7 -2
- package/dist/chat/super-grouping/SuperGroupingTranscript.cjs.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingTranscript.d.ts +2 -2
- package/dist/chat/super-grouping/SuperGroupingTranscript.js +7 -2
- package/dist/chat/super-grouping/SuperGroupingTranscript.js.map +1 -1
- package/dist/chat/super-grouping/activity-timeline.cjs +15 -8
- package/dist/chat/super-grouping/activity-timeline.cjs.map +1 -1
- package/dist/chat/super-grouping/activity-timeline.d.ts +18 -8
- package/dist/chat/super-grouping/activity-timeline.js +15 -8
- package/dist/chat/super-grouping/activity-timeline.js.map +1 -1
- package/dist/chat/use-statewire-approval-request.cjs +36 -0
- package/dist/chat/use-statewire-approval-request.cjs.map +1 -1
- package/dist/chat/use-statewire-approval-request.d.ts +49 -1
- package/dist/chat/use-statewire-approval-request.js +39 -3
- package/dist/chat/use-statewire-approval-request.js.map +1 -1
- package/dist/chat-ui/composer/tiptap-composer.cjs +102 -3
- package/dist/chat-ui/composer/tiptap-composer.cjs.map +1 -1
- package/dist/chat-ui/composer/tiptap-composer.d.ts +32 -1
- package/dist/chat-ui/composer/tiptap-composer.js +103 -4
- package/dist/chat-ui/composer/tiptap-composer.js.map +1 -1
- package/dist/chat-ui/header/conversation-history-panel.d.ts +1 -1
- package/dist/chat-ui/index.d.ts +1 -1
- package/dist/chat-ui/messages/message-components.cjs +15 -0
- package/dist/chat-ui/messages/message-components.cjs.map +1 -1
- package/dist/chat-ui/messages/message-components.js +15 -0
- package/dist/chat-ui/messages/message-components.js.map +1 -1
- package/dist/chat-ui/messages/runtime-message.d.ts +1 -1
- package/dist/chat-ui/messages/statewire-continue-run.d.ts +1 -1
- package/dist/chat-ui/messages/user-edit-composer.cjs +15 -2
- package/dist/chat-ui/messages/user-edit-composer.cjs.map +1 -1
- package/dist/chat-ui/messages/user-edit-composer.d.ts +4 -2
- package/dist/chat-ui/messages/user-edit-composer.js +15 -2
- package/dist/chat-ui/messages/user-edit-composer.js.map +1 -1
- package/dist/chat-ui/messages/wake-marker.d.ts +1 -1
- package/dist/chat-ui/rich-text/chat-text-schema.cjs +1 -0
- package/dist/chat-ui/rich-text/chat-text-schema.cjs.map +1 -1
- package/dist/chat-ui/rich-text/chat-text-schema.d.ts +3 -0
- package/dist/chat-ui/rich-text/chat-text-schema.js +1 -0
- package/dist/chat-ui/rich-text/chat-text-schema.js.map +1 -1
- package/dist/chat-ui/statewire.cjs +1 -0
- package/dist/chat-ui/statewire.cjs.map +1 -1
- package/dist/chat-ui/statewire.d.ts +2 -2
- package/dist/chat-ui/statewire.js +2 -1
- package/dist/chat-ui/thread/statewire-history-edge.d.ts +1 -1
- package/dist/composer/AttachmentContext.cjs +8 -4
- package/dist/composer/AttachmentContext.cjs.map +1 -1
- package/dist/composer/AttachmentContext.d.ts +7 -0
- package/dist/composer/AttachmentContext.js +8 -4
- package/dist/composer/AttachmentContext.js.map +1 -1
- package/dist/composer/build-composed-message.cjs +34 -0
- package/dist/composer/build-composed-message.cjs.map +1 -1
- package/dist/composer/build-composed-message.d.ts +20 -0
- package/dist/composer/build-composed-message.js +35 -1
- package/dist/composer/build-composed-message.js.map +1 -1
- package/dist/composer/composer-handoff.cjs +39 -2
- package/dist/composer/composer-handoff.cjs.map +1 -1
- package/dist/composer/composer-handoff.d.ts +28 -3
- package/dist/composer/composer-handoff.js +39 -2
- package/dist/composer/composer-handoff.js.map +1 -1
- package/dist/composer/useAttachFiles.cjs +15 -2
- package/dist/composer/useAttachFiles.cjs.map +1 -1
- package/dist/composer/useAttachFiles.d.ts +11 -0
- package/dist/composer/useAttachFiles.js +15 -2
- package/dist/composer/useAttachFiles.js.map +1 -1
- package/dist/composer/useSendMessage.cjs.map +1 -1
- package/dist/composer/useSendMessage.d.ts +4 -3
- package/dist/composer/useSendMessage.js.map +1 -1
- package/dist/diagnostics/athena-diagnostics.cjs.map +1 -1
- package/dist/diagnostics/athena-diagnostics.d.ts +3 -1
- package/dist/diagnostics/athena-diagnostics.js.map +1 -1
- package/dist/index.cjs +13 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +13 -6
- package/dist/index.js +14 -1
- package/dist/index.js.map +1 -1
- package/dist/offline/chat-outbox.cjs +57 -0
- package/dist/offline/chat-outbox.cjs.map +1 -0
- package/dist/offline/chat-outbox.d.ts +80 -0
- package/dist/offline/chat-outbox.js +57 -0
- package/dist/offline/chat-outbox.js.map +1 -0
- package/dist/offline/offline-history.d.ts +1 -1
- package/dist/provider/AthenaProvider.cjs +162 -8
- package/dist/provider/AthenaProvider.cjs.map +1 -1
- package/dist/provider/AthenaProvider.d.ts +15 -1
- package/dist/provider/AthenaProvider.js +163 -9
- package/dist/provider/AthenaProvider.js.map +1 -1
- package/dist/provider/statewire-window-context.d.ts +1 -1
- package/dist/react/package.json.cjs +1 -1
- package/dist/react/package.json.js +1 -1
- package/dist/references/src/anchors/file-line-range.d.ts +58 -0
- package/dist/references/src/anchors/format.d.ts +21 -0
- package/dist/references/src/anchors/message-anchors.d.ts +71 -0
- package/dist/references/src/anchors/parse.d.ts +8 -0
- package/dist/references/src/anchors/registry-contract.d.ts +24 -0
- package/dist/references/src/anchors/registry.d.ts +19 -0
- package/dist/references/src/anchors/schemas.d.ts +194 -0
- package/dist/references/src/anchors/serialize.d.ts +8 -0
- package/dist/references/src/anchors/time.d.ts +78 -0
- package/dist/references/src/anchors/types.d.ts +474 -0
- package/dist/references/src/asset-bounds.d.ts +27 -0
- package/dist/references/src/asset-links.d.ts +23 -0
- package/dist/references/src/asset-reference.d.ts +16 -0
- package/dist/references/src/formats/format-catalog.d.ts +79 -0
- package/dist/references/src/formats/markdown/parse-reference-markdown.d.ts +28 -0
- package/dist/references/src/formats/markdown/reference-display-name.d.ts +6 -0
- package/dist/references/src/formats/object/asset-object.d.ts +9 -0
- package/dist/references/src/formats/object/callable-object.d.ts +6 -0
- package/dist/references/src/formats/object/decode-reference-object-payload.d.ts +3 -0
- package/dist/references/src/formats/object/external-url-object.d.ts +9 -0
- package/dist/references/src/formats/object/group-object.d.ts +9 -0
- package/dist/references/src/formats/object/navigation-object.d.ts +9 -0
- package/dist/references/src/formats/object/parse-reference-object.d.ts +11 -0
- package/dist/references/src/formats/object/person-object.d.ts +9 -0
- package/dist/references/src/formats/uri/asset-mention-uri.d.ts +9 -0
- package/dist/references/src/formats/uri/asset-spaces-url.d.ts +9 -0
- package/dist/references/src/formats/uri/callable-mention-uris.d.ts +9 -0
- package/dist/references/src/formats/uri/detect-uri-wire.d.ts +9 -0
- package/dist/references/src/formats/uri/group-mention-uri.d.ts +12 -0
- package/dist/references/src/formats/uri/navigation-spaces-url.d.ts +14 -0
- package/dist/references/src/formats/uri/parse-reference-uri.d.ts +20 -0
- package/dist/references/src/formats/uri/person-mention-uri.d.ts +9 -0
- package/dist/references/src/formats/uri/template-placeholder.d.ts +12 -0
- package/dist/references/src/index.d.ts +47 -0
- package/dist/references/src/legacy/index.d.ts +14 -0
- package/dist/references/src/legacy/pre-reference-asset-url.d.ts +57 -0
- package/dist/references/src/legacy/pre-reference-citation-bridge.d.ts +22 -0
- package/dist/references/src/legacy/pre-reference-citation.d.ts +138 -0
- package/dist/references/src/legacy/pre-reference-external-url.d.ts +31 -0
- package/dist/references/src/legacy/pre-reference-format.d.ts +8 -0
- package/dist/references/src/legacy/pre-reference-mention.d.ts +27 -0
- package/dist/references/src/legacy/pre-reference-object.d.ts +8 -0
- package/dist/references/src/legacy/pre-reference-uri.d.ts +12 -0
- package/dist/references/src/legacy.d.ts +2 -0
- package/dist/references/src/mention-href-patterns.d.ts +19 -0
- package/dist/references/src/mention-node/index.d.ts +5 -0
- package/dist/references/src/mention-node/mention-node.d.ts +31 -0
- package/dist/references/src/mention-node/resolve-node-attrs.d.ts +27 -0
- package/dist/references/src/parse-reference.d.ts +23 -0
- package/dist/references/src/schemas.d.ts +463 -0
- package/dist/references/src/serialize-reference.d.ts +50 -0
- package/dist/references/src/sheet-name.d.ts +10 -0
- package/dist/references/src/tool-option-schemas.d.ts +597 -0
- package/dist/references/src/types.d.ts +125 -0
- package/dist/references/src/version-ref.d.ts +30 -0
- package/dist/runtime/statewire-lifecycle.d.ts +1 -1
- package/dist/runtime/statewire-model-lane.d.ts +1 -1
- package/dist/runtime/statewire-server-lane-context.d.ts +1 -1
- package/dist/runtime/statewire-session-key.cjs +7 -0
- package/dist/runtime/statewire-session-key.cjs.map +1 -1
- package/dist/runtime/statewire-session-key.d.ts +16 -0
- package/dist/runtime/statewire-session-key.js +8 -1
- package/dist/runtime/statewire-session-key.js.map +1 -1
- package/dist/runtime/statewire-session-lane.cjs +48 -0
- package/dist/runtime/statewire-session-lane.cjs.map +1 -0
- package/dist/runtime/statewire-session-lane.d.ts +29 -0
- package/dist/runtime/statewire-session-lane.js +48 -0
- package/dist/runtime/statewire-session-lane.js.map +1 -0
- package/dist/runtime/statewire-thread-config-lane.d.ts +1 -1
- package/dist/runtime/useAthenaStatewireRuntime.cjs +16 -5
- package/dist/runtime/useAthenaStatewireRuntime.cjs.map +1 -1
- package/dist/runtime/useAthenaStatewireRuntime.d.ts +15 -1
- package/dist/runtime/useAthenaStatewireRuntime.js +17 -6
- package/dist/runtime/useAthenaStatewireRuntime.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/threads/api.d.ts +1 -1
- package/dist/threads/conversation-list-fetcher.d.ts +1 -1
- package/dist/threads/index-triggered-refresh.cjs +164 -0
- package/dist/threads/index-triggered-refresh.cjs.map +1 -0
- package/dist/threads/index-triggered-refresh.d.ts +70 -0
- package/dist/threads/index-triggered-refresh.js +164 -0
- package/dist/threads/index-triggered-refresh.js.map +1 -0
- package/dist/threads/offline-session-list.d.ts +1 -1
- package/dist/threads/pull-request-display.d.ts +1 -1
- package/dist/threads/session-list-model.d.ts +1 -1
- package/dist/threads/session-list-tab-share.cjs +150 -0
- package/dist/threads/session-list-tab-share.cjs.map +1 -0
- package/dist/threads/session-list-tab-share.d.ts +73 -0
- package/dist/threads/session-list-tab-share.js +150 -0
- package/dist/threads/session-list-tab-share.js.map +1 -0
- package/dist/threads/session-row-parts.d.ts +1 -1
- package/dist/threads/sessions-query.d.ts +1 -1
- package/dist/threads/statewire-thread-list.cjs +42 -16
- package/dist/threads/statewire-thread-list.cjs.map +1 -1
- package/dist/threads/statewire-thread-list.d.ts +11 -2
- package/dist/threads/statewire-thread-list.js +43 -17
- package/dist/threads/statewire-thread-list.js.map +1 -1
- package/dist/threads/thread-prefetcher.d.ts +1 -1
- package/dist/threads/use-athena-session-attention.d.ts +1 -1
- package/dist/threads/use-athena-sessions.cjs +32 -22
- package/dist/threads/use-athena-sessions.cjs.map +1 -1
- package/dist/threads/use-athena-sessions.js +33 -23
- package/dist/threads/use-athena-sessions.js.map +1 -1
- package/dist/threads/use-rest-conversation-history.d.ts +1 -1
- package/dist/threads/use-statewire-conversation-history.d.ts +5 -5
- package/dist/tiptap-markdown-table/src/markdown-table-serializer.d.ts +56 -0
- package/dist/tools/NestedPtcMessages.cjs +14 -9
- package/dist/tools/NestedPtcMessages.cjs.map +1 -1
- package/dist/tools/NestedPtcMessages.d.ts +9 -0
- package/dist/tools/NestedPtcMessages.js +6 -1
- package/dist/tools/NestedPtcMessages.js.map +1 -1
- package/dist/tools/index.d.ts +1 -1
- package/dist/tools/primitives.d.ts +1 -1
- package/dist/tools/subagent-task-tool-ui.cjs +494 -0
- package/dist/tools/subagent-task-tool-ui.cjs.map +1 -0
- package/dist/tools/subagent-task-tool-ui.d.ts +109 -0
- package/dist/tools/subagent-task-tool-ui.js +494 -0
- package/dist/tools/subagent-task-tool-ui.js.map +1 -0
- package/dist/tools/tool-fallback.d.ts +1 -1
- package/dist/tools/tool-icons.d.ts +1 -1
- package/dist/tools/tool-summary.d.ts +1 -1
- package/dist/tools/tool-uis.cjs +4 -0
- package/dist/tools/tool-uis.cjs.map +1 -1
- package/dist/tools/tool-uis.js +4 -0
- package/dist/tools/tool-uis.js.map +1 -1
- package/dist/voice/chat.cjs +6 -0
- package/dist/voice/chat.cjs.map +1 -0
- package/dist/voice/chat.d.ts +2 -0
- package/dist/voice/chat.js +6 -0
- package/dist/voice/chat.js.map +1 -0
- package/dist/voice/livekit-join.cjs +119 -0
- package/dist/voice/livekit-join.cjs.map +1 -0
- package/dist/voice/livekit-join.d.ts +8 -0
- package/dist/voice/livekit-join.js +119 -0
- package/dist/voice/livekit-join.js.map +1 -0
- package/dist/voice/livekit.cjs +32 -0
- package/dist/voice/livekit.cjs.map +1 -0
- package/dist/voice/livekit.d.ts +80 -0
- package/dist/voice/livekit.js +32 -0
- package/dist/voice/livekit.js.map +1 -0
- package/package.json +20 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"messages.cjs","sources":["../../../../agent-runtime/src/messages.ts"],"sourcesContent":["import {\n getExternalStoreMessages,\n type ThreadAssistantMessage,\n type ThreadAssistantMessagePart,\n type ThreadMessage,\n} from '@assistant-ui/core';\nimport {\n convertExternalMessages,\n createExternalMessageConversionCache,\n createMessageConverter,\n type useExternalMessageConverter,\n} from '@assistant-ui/core/react';\nimport { convertLangChainMessages, type LangChainMessage } from '@assistant-ui/react-langgraph';\nimport { runsMaterialize, type StatewireThread } from '@assistant-ui/react-statewire';\nimport {\n ATHENA_MESSAGE_AUTHOR_KEY,\n type DeepAgentMessageAuthor,\n laneEntryAuthor,\n} from './message-author';\nimport { DEEP_AGENT_COMPOSER_MARKDOWN_KEY } from './composer-markdown';\nimport { DEEP_AGENT_TRUNCATED_CONTENT_KEY } from './generated/runconfig-contract';\nimport {\n ATHENA_TRUNCATED_TOOL_OUTPUT_ARTIFACT_KEY,\n readTruncatedToolContent,\n} from './message-window';\nimport { buildOptimisticHumanContent, type OptimisticContentPart } from './optimistic-content';\nimport { readDeepAgentStreamValues } from './statewire-state';\nimport type { DeepAgentToolOutputStore } from './tool-outputs';\nimport { groupSpokenUserTurns } from './voice-turn-grouping';\nimport type { DeepAgentWithdrawnTurns } from './withdrawn-turns';\nimport type {\n DeepAgentLaneProjection,\n DeepAgentStreamValues,\n LangGraphState,\n} from './types';\n\n/**\n * Native message converter for the deep-agent runtime.\n *\n * This is the entire \"conversion\" layer: assistant-ui's shipped\n * `convertLangChainMessages` (from `@assistant-ui/react-langgraph`) wired\n * through `createMessageConverter`. No bespoke per-message mapping — the agora\n * `athena_deep_agent` graph streams standard LangChain messages via\n * `append_langgraph_event`, and the shipped converter renders them.\n */\nexport const messageConverter = createMessageConverter(convertLangChainMessages);\n\n/**\n * One thread's conversion memory: converting through it maps every source\n * message that is unchanged since the previous pass to the IDENTICAL\n * `ThreadMessage`, so a streamed token rebuilds only the turn it lands in\n * instead of every message in the transcript (and every per-message\n * subscriber, memo and tool card below it).\n *\n * Create one per attached thread and drop it with the attach: entries are\n * keyed by source message identity (WeakMaps, so they die with the wire state\n * that holds them), and a fresh cache per attach keeps one thread's converted\n * messages from ever being served for another.\n */\nexport class DeepAgentMessageConversionCache {\n private readonly cache = createExternalMessageConversionCache();\n /**\n * Every cached entry is rebuilt when the metadata object changes identity,\n * so it is created once per cache and never per pass. The tool-args\n * key-order memory keeps a finished tool call's `argsText` in the order its\n * arguments streamed in (assistant-ui's own LangGraph runtime passes the\n * same).\n */\n private readonly metadata: useExternalMessageConverter.Metadata & {\n readonly toolArgsKeyOrderCache: Map<string, Map<string, string[]>>;\n } = { toolArgsKeyOrderCache: new Map() };\n private previous: ThreadMessage[] | null = null;\n /** `convertExternalMessages`' own rows for the previous pass, before parts were kept. */\n private previousConverted: ThreadMessage[] | null = null;\n\n /**\n * Convert one pass's LangChain messages. Returns the previous pass's array\n * itself when every converted message is unchanged, so a packet that moved\n * no message re-renders no message; a re-converted turn keeps the row key\n * of the row it continues (see {@link deepAgentRowKey}) and the previous\n * pass's part objects for the parts that did not change\n * (see {@link keepUnchangedParts}).\n */\n convert(messages: LangChainMessage[], isRunning: boolean): ThreadMessage[] {\n const converted = convertExternalMessages(\n messages,\n convertLangChainMessages,\n isRunning,\n this.metadata,\n this.cache\n );\n const next =\n this.previous !== null && this.previousConverted !== null\n ? keepUnchangedParts({\n previous: this.previous,\n previousConverted: this.previousConverted,\n converted,\n })\n : converted;\n this.previousConverted = converted;\n if (this.previous !== null && isSameMessageList(this.previous, next)) return this.previous;\n this.previous = next;\n return next;\n }\n}\n\n/**\n * Whether a re-converted part renders as the previous pass's did: every own key\n * holds the same value, the source messages assistant-ui binds under a symbol\n * (a new array on every join) compared message by message.\n */\nfunction sameMessagePart(previous: object, next: object): boolean {\n if (previous === next) return true;\n const keys = Reflect.ownKeys(next);\n if (keys.length !== Reflect.ownKeys(previous).length) return false;\n for (const key of keys) {\n if (!Object.prototype.hasOwnProperty.call(previous, key)) return false;\n const before: unknown = Reflect.get(previous, key);\n const after: unknown = Reflect.get(next, key);\n if (Object.is(before, after)) continue;\n const sameSources =\n typeof key === 'symbol' &&\n Array.isArray(before) &&\n Array.isArray(after) &&\n before.length === after.length &&\n before.every((source, index) => Object.is(source, after[index]));\n if (!sameSources) return false;\n }\n return true;\n}\n\n/** Where a row carries a key that differs from its id (see {@link deepAgentRowKey}). */\nconst ROW_KEY = Symbol.for('@athenaintel/agent-runtime/row-key');\n\n/**\n * The key a deep-agent thread message renders under in a message list: its\n * id, except for a turn that grew at its head.\n *\n * assistant-ui joins an agent run's consecutive messages into one turn whose\n * id is its first message's, so a page of older history that folds into the\n * first loaded turn (a long run's earlier steps) gives that turn a new id on\n * every page. The conversion cache keeps such a turn under the key of the row\n * it continues, so a list keyed by it keeps the turn's row, and the row's own\n * state, while the page lands. What is mounted inside the row stays mounted\n * only if the parts render under keys that survive the fold too: assistant-ui\n * keys a toolkit group by its first part, which the fold changes when its\n * steps join that group (`GroupedMessageParts` in `@athenaintel/react` carries\n * the keys over). `message.id` stays the message's id: metadata, links and\n * anchors read it.\n *\n * Takes a converted message or the message state assistant-ui publishes for\n * it, which copies the key. A message from another runtime, or one converted\n * without a conversion cache, renders under its id.\n */\nexport function deepAgentRowKey(message: { readonly id: string }): string {\n const key: unknown = Reflect.get(message, ROW_KEY);\n return typeof key === 'string' ? key : message.id;\n}\n\n/**\n * This pass's rows: the previous pass's row for every message the conversion\n * returned unchanged, and for a re-converted message the previous row it\n * continues, the one holding any of its source messages, else the one with\n * its id. The new row keeps that row's key (see {@link deepAgentRowKey}) and,\n * when both are assistant turns, its part objects wherever a part is\n * unchanged (see {@link withUnchangedParts}).\n *\n * assistant-ui builds every part of a re-converted turn as a new object, and its\n * thread keys each part's state (what a tool card or text part reads) on the\n * part object, so without this every tool card of the turn being generated\n * re-renders on every streamed token although only the streaming text changed.\n */\nfunction keepUnchangedParts({\n previous,\n previousConverted,\n converted,\n}: {\n previous: readonly ThreadMessage[];\n previousConverted: readonly ThreadMessage[];\n converted: readonly ThreadMessage[];\n}): ThreadMessage[] {\n let previousByConverted: Map<ThreadMessage, ThreadMessage> | null = null;\n let previousBySource: Map<unknown, ThreadMessage> | null = null;\n let previousById: Map<string, ThreadMessage> | null = null;\n let rowIds: ReadonlySet<string> | null = null;\n const continuedKeys = new Set<string>();\n const continuedRow = (message: ThreadMessage, index: number): ThreadMessage | undefined => {\n const atIndex: ThreadMessage | undefined = previous[index];\n if (atIndex?.id === message.id) return atIndex;\n previousBySource ??= rowsBySourceMessage(previous);\n for (const source of getExternalStoreMessages(message)) {\n const row = previousBySource.get(source);\n if (row !== undefined) return row;\n }\n previousById ??= new Map(previous.map((row) => [row.id, row]));\n return previousById.get(message.id);\n };\n return converted.map((message, index) => {\n if (message === previousConverted[index]) return previous[index] ?? message;\n // An unchanged row that moved (a message landed above it) keeps its row too.\n previousByConverted ??= new Map(\n previousConverted.map((row, rowIndex) => [row, previous[rowIndex] ?? row])\n );\n const unchanged = previousByConverted.get(message);\n if (unchanged !== undefined) return unchanged;\n const before = continuedRow(message, index);\n const row =\n before?.role === 'assistant' && message.role === 'assistant'\n ? withUnchangedParts({ before, message })\n : message;\n const key = before === undefined ? message.id : deepAgentRowKey(before);\n if (key === message.id) return row;\n // A key another row of this pass already renders under stays with that row.\n rowIds ??= new Set(converted.map((candidate) => candidate.id));\n if (rowIds.has(key) || continuedKeys.has(key)) return row;\n continuedKeys.add(key);\n // A copy: the conversion caches its own rows and serves them again.\n const keyed: ThreadMessage = { ...row };\n Reflect.set(keyed, ROW_KEY, key);\n return keyed;\n });\n}\n\n/** Each source message's row, for finding the row a re-converted message continues. */\nfunction rowsBySourceMessage(rows: readonly ThreadMessage[]): Map<unknown, ThreadMessage> {\n const bySource = new Map<unknown, ThreadMessage>();\n for (const row of rows) {\n for (const source of getExternalStoreMessages(row)) {\n if (!bySource.has(source)) bySource.set(source, row);\n }\n }\n return bySource;\n}\n\n/**\n * `message` with `before`'s part object wherever a part is unchanged. Parts\n * are paired by what they render, not by position: a tool call by its id, any\n * other part by the converted source message it came from (and its place\n * among that message's parts). A page of older steps that folds in at the\n * head of the turn then keeps every part that was already there.\n */\nfunction withUnchangedParts({\n before,\n message,\n}: {\n before: ThreadAssistantMessage;\n message: ThreadAssistantMessage;\n}): ThreadAssistantMessage {\n const toolCalls = new Map<string, ThreadAssistantMessagePart>();\n const bySource = new Map<unknown, ThreadAssistantMessagePart[]>();\n for (const part of before.content) {\n if (part.type === 'tool-call') {\n toolCalls.set(part.toolCallId, part);\n continue;\n }\n const source: unknown = getExternalStoreMessages(part)[0];\n const parts = bySource.get(source);\n if (parts === undefined) bySource.set(source, [part]);\n else parts.push(part);\n }\n const placesBySource = new Map<unknown, number>();\n let kept = 0;\n const content = message.content.map((part) => {\n let candidate: ThreadAssistantMessagePart | undefined;\n if (part.type === 'tool-call') {\n candidate = toolCalls.get(part.toolCallId);\n } else {\n const source: unknown = getExternalStoreMessages(part)[0];\n const place = placesBySource.get(source) ?? 0;\n placesBySource.set(source, place + 1);\n candidate = bySource.get(source)?.[place];\n }\n if (candidate === undefined || !sameMessagePart(candidate, part)) return part;\n kept += 1;\n return candidate;\n });\n return kept === 0 ? message : { ...message, content };\n}\n\n/** A conversion cache for one attached thread (see {@link DeepAgentMessageConversionCache}). */\nexport function createDeepAgentMessageConversionCache(): DeepAgentMessageConversionCache {\n return new DeepAgentMessageConversionCache();\n}\n\nfunction isSameMessageList(a: readonly ThreadMessage[], b: readonly ThreadMessage[]): boolean {\n return a.length === b.length && a.every((message, index) => message === b[index]);\n}\n\nconst wirePartsToOptimisticParts = (\n parts: StatewireThread.UserMessage['parts']\n): OptimisticContentPart[] =>\n parts.flatMap((part): OptimisticContentPart[] => {\n if (part.type === 'text') return [part];\n // Image attachments travel as `file` parts on the run/* commands; map\n // them back to `image` parts so the optimistic bubble renders them.\n if (part.mediaType.startsWith('image/')) return [{ type: 'image', image: part.url }];\n return [];\n });\n\n/**\n * `metadata.custom` flag marking a bubble that is a projection of a run-lane\n * entry — a message the server holds and has NOT dispatched yet.\n *\n * The lane is server-owned and replicated to every client on the thread, so\n * an item queued on one surface projects onto all of them. Surfaces without a\n * queue panel must therefore be able to tell a queued projection apart from a\n * submitted turn, or a message another device queued renders as if this device\n * had already sent it.\n *\n * `convertLangChainMessages` exposes `additional_kwargs.metadata` (and nothing\n * else) as the thread message's `metadata.custom`.\n */\nexport const ATHENA_QUEUED_LANE_KEY = 'athena_queued_lane';\n\n/**\n * Whether a thread message's `metadata.custom` marks it as an undispatched\n * lane projection. Returns a primitive, so it is safe to use directly as a\n * `useAuiState` selector.\n */\nexport function isQueuedLaneMessage(custom: Record<string, unknown> | undefined): boolean {\n return custom?.[ATHENA_QUEUED_LANE_KEY] === true;\n}\n\ninterface LaneEntryMessageCacheEntry {\n selfAuthor: DeepAgentMessageAuthor | null;\n message: LangChainMessage;\n}\n\n/**\n * Per-entry projections, one map per lane state. Lane entries are wire\n * objects folded copy-on-write (like messages, see {@link liftedMessageCache}),\n * so an unchanged entry projects to the IDENTICAL message on every pass and its\n * bubble keeps its converted identity while it waits in a lane or for its\n * dispatch to land. An entry this client's own unacknowledged command still\n * shapes is rebuilt each time statewire re-applies that optimistic fold, and\n * re-projects until the server acknowledges it.\n */\nconst queuedLaneMessageCache = new WeakMap<\n StatewireThread.RunsQueueEntry,\n LaneEntryMessageCacheEntry\n>();\nconst dispatchedLaneMessageCache = new WeakMap<\n StatewireThread.RunsQueueEntry,\n LaneEntryMessageCacheEntry\n>();\n\n/**\n * Project one run-lane entry into the optimistic human message shape.\n *\n * `queued` marks entries still waiting in a lane; a dispatched entry becomes an\n * ordinary submitted turn and carries no marker. Either way the bubble carries\n * its author (see {@link laneEntryAuthor}) under the same `metadata.custom`\n * key the backend stamps on the persisted turn, so the optimistic and\n * authoritative copies of one send render identically — and a second poster's\n * avatar shows on their own send without waiting for the acknowledgment.\n */\nconst laneEntryMessage = ({\n entry,\n queued,\n selfAuthor,\n}: {\n entry: StatewireThread.RunsQueueEntry;\n queued: boolean;\n selfAuthor: DeepAgentMessageAuthor | null;\n}): LangChainMessage => {\n const cache = queued ? queuedLaneMessageCache : dispatchedLaneMessageCache;\n const cached = cache.get(entry);\n if (cached !== undefined && cached.selfAuthor === selfAuthor) return cached.message;\n const message = buildLaneEntryMessage({ entry, queued, selfAuthor });\n cache.set(entry, { selfAuthor, message });\n return message;\n};\n\nconst buildLaneEntryMessage = ({\n entry,\n queued,\n selfAuthor,\n}: {\n entry: StatewireThread.RunsQueueEntry;\n queued: boolean;\n selfAuthor: DeepAgentMessageAuthor | null;\n}): LangChainMessage => {\n const author = laneEntryAuthor(entry, selfAuthor);\n // The draft a composer send came from, so the optimistic bubble renders the\n // typed text the way its persisted copy will (see `composer-markdown.ts`).\n const composerMarkdown: unknown = (entry.metadata as Record<string, unknown> | undefined)?.[\n DEEP_AGENT_COMPOSER_MARKDOWN_KEY\n ];\n const metadata: Record<string, unknown> = {\n ...(queued ? { [ATHENA_QUEUED_LANE_KEY]: true } : {}),\n ...(author ? { [ATHENA_MESSAGE_AUTHOR_KEY]: author } : {}),\n ...(typeof composerMarkdown === 'string'\n ? { [DEEP_AGENT_COMPOSER_MARKDOWN_KEY]: composerMarkdown }\n : {}),\n };\n return {\n id: entry.id,\n type: 'human',\n content: buildOptimisticHumanContent(wirePartsToOptimisticParts(entry.parts)),\n ...(Object.keys(metadata).length > 0 ? { additional_kwargs: { metadata } } : {}),\n };\n};\n\nexport interface DeepAgentMaterializeOptions {\n /** The viewer, stamped onto this client's own not-yet-acknowledged sends. */\n selfAuthor?: DeepAgentMessageAuthor | null;\n}\n\n/**\n * Materialize fold for the statewire path: makes the server's dispatch record\n * concrete in the LangGraph state itself, so direct state reads see dispatched\n * messages and the lib's post-converter dispatch merge stays off.\n */\nexport const createDeepAgentMaterialize =\n ({ selfAuthor = null }: DeepAgentMaterializeOptions = {}) =>\n (draft: DeepAgentStreamValues): void => {\n runsMaterialize(draft, {\n append: (message) => {\n (draft.messages ??= []).push(\n laneEntryMessage({ entry: message, queued: false, selfAuthor })\n );\n },\n rollback: (to) => {\n if (to === null) {\n draft.messages = [];\n return;\n }\n const messages = draft.messages ?? [];\n const keepIndex = messages.findIndex((message) => message.id === to);\n // Unresolved rollback anchor: fail OPEN with the full history (mirrors the edit fold).\n if (keepIndex !== -1) messages.splice(keepIndex + 1);\n },\n });\n };\n\n/** The materialize fold without a viewer identity (surfaces that pass none). */\nexport const deepAgentMaterialize = createDeepAgentMaterialize();\n\n/**\n * Project run lanes into human messages for the converter tail, so a queued or\n * steered item stays visible below the pending-assistant placeholder until its\n * dispatch. Surfaces with a queue panel project only the steer lane\n * (`'steer-only'`); surfaces without one project both lanes (`'both'`).\n *\n * Every projected entry carries {@link ATHENA_QUEUED_LANE_KEY} so a surface\n * without a queue panel can render it as queued rather than as a submitted\n * turn.\n */\nexport const laneTailMessages = (\n state: unknown,\n laneProjection: DeepAgentLaneProjection = 'both',\n selfAuthor: DeepAgentMessageAuthor | null = null\n): LangChainMessage[] => {\n const run = (state as DeepAgentStreamValues | null)?.runs?.[0];\n if (!run) return [];\n const entries =\n laneProjection === 'steer-only' ? run.steerQueue : [...run.queue, ...run.steerQueue];\n return entries.map((entry) => laneEntryMessage({ entry, queued: true, selfAuthor }));\n};\n\n/** Stable id for the derived running-assistant placeholder. */\nexport const PENDING_ASSISTANT_MESSAGE_ID = '__athena_deep_agent_pending_assistant__';\n\n/**\n * The placeholder itself — empty-array content plus an explicit running\n * status: the thinking shimmer keys on `status running && zero content parts`,\n * and the explicit status keeps it pulsing when lane entries render below (the\n * last-message auto status would demote a mid-list placeholder to an empty\n * complete bubble). One shared, frozen object, so the converted \"Thinking…\" row\n * keeps its identity across every pass until the real reply replaces it.\n */\nconst PENDING_ASSISTANT_MESSAGE: LangChainMessage = Object.freeze({\n type: 'ai',\n content: [],\n id: PENDING_ASSISTANT_MESSAGE_ID,\n status: Object.freeze({ type: 'running' }),\n} satisfies LangChainMessage);\n\n/**\n * Append an empty assistant turn while a run is in flight and the visible\n * history does not already end in one, so the thread shows its \"Thinking…\"\n * status line from the moment a message is submitted.\n *\n * Mirrors `hasUpcomingMessage` in assistant-ui's legacy external-store runtime,\n * which synthesized this placeholder itself. `StatewireThread` renders the\n * converter's message list verbatim, so the placeholder has to come from here —\n * derived from the replicated run status on every render (never written into\n * transport state) so it cannot outlive the run, and carrying a stable id so\n * the streaming bubble's identity does not churn when the real assistant\n * message arrives.\n *\n * `tool` messages convert into assistant turns too, so a mid-run tool result\n * must not produce a second placeholder row.\n */\nexport function withPendingAssistantMessage(\n messages: LangChainMessage[],\n isRunning: boolean\n): LangChainMessage[] {\n if (!isRunning) return messages;\n const lastType = messages.at(-1)?.type;\n if (lastType === 'ai' || lastType === 'tool') return messages;\n // Never persisted, so it cannot outlive the run.\n return [...messages, PENDING_ASSISTANT_MESSAGE];\n}\n\n/** Stable id for the synthetic assistant turn that carries a failure when the run produced none. */\nconst RUN_ERROR_SYNTHETIC_AI_ID = '__athena_deep_agent_run_error__';\n\n/**\n * Surface a run failure the base-correct way: stamp `status: { type:'incomplete',\n * reason:'error', error }` onto the assistant turn so `<Thread/>` renders it via\n * `ErrorPrimitive`. This is the core runtime's model (see `useLanggraphRuntime`\n * `onError`) — NOT a fabricated `⚠️ The run failed` assistant text message, and\n * NOT a magic-string contract shared with the agora backend.\n *\n * Stamps a trailing assistant message; if the visible history does not already\n * end with an assistant turn, appends a synthetic empty assistant turn with a\n * STABLE id so it never churns across renders. A `null` error is a no-op. The\n * shipped `convertLangChainMessages` converter passes `message.status` through.\n */\nexport function applyRunErrorStatus(\n messages: LangChainMessage[],\n errorMessage: string | null\n): LangChainMessage[] {\n if (errorMessage === null) return messages;\n const status = { type: 'incomplete', reason: 'error', error: errorMessage } as const;\n const lastMessage = messages.at(-1);\n if (lastMessage?.type !== 'ai') {\n return [\n ...messages,\n { type: 'ai', content: '', id: RUN_ERROR_SYNTHETIC_AI_ID, status } satisfies LangChainMessage,\n ];\n }\n return [...messages.slice(0, -1), { ...lastMessage, status }];\n}\n\n/**\n * `additional_kwargs` flag the backend stamps on run-lifecycle marker messages\n * (agora `athena_deep_agent/run_markers.py`) — e.g. the \"⏹️ Run stopped by\n * user.\" message persisted when a run is cancelled.\n */\nexport const ATHENA_RUN_MARKER_KEY = 'athena_run_marker';\n\n/** The {@link ATHENA_RUN_MARKER_KEY} value for a user-cancelled run. */\nexport const ATHENA_RUN_MARKER_CANCELLED = 'cancelled';\n\n/**\n * `additional_kwargs` key carrying the stop source behind a cancellation\n * marker (agora `stop_signals.py`: `user_stop`, `send_now`, `transport_cancel`,\n * `unattributed`).\n */\nexport const ATHENA_RUN_MARKER_SOURCE_KEY = 'athena_run_marker_source';\n\n/** The stop source for a \"Send now\" promotion pre-empting the live run. */\nexport const ATHENA_STOP_SOURCE_SEND_NOW = 'send_now';\n\n/**\n * The stop source for a spoken follow-up that redirected a voice-delegated\n * run through the steer lane: the user spoke, they never pressed Stop, so it\n * renders as a redirect rather than as \"Conversation stopped\".\n */\nexport const ATHENA_STOP_SOURCE_VOICE_STEER = 'voice_steer';\n\n/** The stop source for a pod-drain pause (server update), not a user stop. */\nexport const ATHENA_STOP_SOURCE_POD_DRAIN = 'pod_drain';\n\n/**\n * The {@link ATHENA_RUN_MARKER_SOURCE_KEY} value for a run whose hosting\n * instance closed under it (a server update that reached its eviction\n * deadline mid-step, or a placement lost to a lease lapse). Same family as a\n * pod drain: nobody stopped the run, the backend resumes it automatically.\n */\nexport const ATHENA_STOP_SOURCE_INSTANCE_CLOSED = 'instance_closed';\n\n/**\n * Whether a cancellation marker's source names the infrastructure — a pod\n * drain or a closed instance — rather than a person or a client action. These\n * endings read as a pause while the server resumes the run.\n */\nexport function isServerUpdateStopSource(source: string | undefined): boolean {\n return source === ATHENA_STOP_SOURCE_POD_DRAIN || source === ATHENA_STOP_SOURCE_INSTANCE_CLOSED;\n}\n\n/**\n * The {@link ATHENA_RUN_MARKER_KEY} value for a failed run (graph error,\n * including the `GraphRecursionError` \"tool call limit was reached\" case).\n * The marker message's text content carries the user-facing failure copy.\n */\nexport const ATHENA_RUN_MARKER_FAILED = 'failed';\n\n/**\n * `additional_kwargs` key carrying the canonical reason a run ended (agora\n * `athena_deep_agent/termination.py`): `user_stop`, `recursion_limit`,\n * `duplicate_call_guard`, `step_budget`, `ended_after_tools`, `model_refusal`,\n * `completed`, …\n * Stamped on run-lifecycle markers and on handoff messages.\n */\nexport const ATHENA_TERMINATION_REASON_KEY = 'athena_termination_reason';\n\n/**\n * `additional_kwargs` flag on the closing message the runtime's **handoff\n * turn** wrote (one tools-disabled model call made when a guard or the step\n * budget ends the run). The message text is the agent's closing summary; the\n * flag lets clients frame it as a runtime ending rather than a normal reply.\n */\nexport const ATHENA_HANDOFF_KEY = 'athena_handoff';\n\n/**\n * Read a run-lifecycle marker out of a thread message's **bound source\n * messages**, bypassing the converter's metadata join entirely.\n *\n * Why this exists: assistant-ui chunks consecutive assistant/tool messages\n * into ONE `ThreadMessage`, and the upstream join copies `metadata.custom`\n * only from the FIRST assistant message of the chunk\n * (`external-message-converter.ts`: the merge sits inside\n * `if (assistantMessage.content.length === 0)`). A failure marker appended\n * after the assistant's own turn is therefore never the first message in its\n * chunk, so `message.metadata.custom.athena_run_marker` is silently dropped\n * and the whole-message gate can't fire.\n *\n * `getExternalStoreMessages` returns the raw LangChain messages bound to the\n * joined thread message, so the marker is found wherever it sits in the chunk.\n * Returns the marker value plus its text content (the user-facing copy).\n */\nexport interface RunMarkerInfo {\n marker: string;\n /** The stop source stamped by the backend, when the marker carries one. */\n source: string | undefined;\n /** The marker message's text — the user-facing copy. */\n text: string | undefined;\n /**\n * True when the marker is the ONLY source message behind this thread message,\n * i.e. it owns the whole row (a cancelled run drops its partial turn, so its\n * marker stands alone).\n *\n * False when the chunk also holds the assistant's own work. Replacing the row\n * in that case would hide completed prose and tool cards — the marker must be\n * styled in place instead.\n */\n isSoleSourceMessage: boolean;\n}\n\nexport function readRunMarkerFromSourceMessages(\n message: Parameters<typeof getExternalStoreMessages>[0] & {\n metadata?: { custom?: Record<string, unknown> | undefined } | undefined;\n content?: unknown;\n }\n): RunMarkerInfo | undefined {\n const sources = getExternalStoreMessages<LangChainMessage>(message);\n for (const source of sources) {\n if (source?.type !== 'ai') continue;\n const kwargs = source.additional_kwargs as Record<string, unknown> | undefined;\n const marker = kwargs?.[ATHENA_RUN_MARKER_KEY];\n if (typeof marker !== 'string') continue;\n const markerSource = kwargs?.[ATHENA_RUN_MARKER_SOURCE_KEY];\n return {\n marker,\n source: typeof markerSource === 'string' ? markerSource : undefined,\n text: typeof source.content === 'string' ? source.content : undefined,\n isSoleSourceMessage: sources.length === 1,\n };\n }\n // Fallback for surfaces whose messages carry no bound source messages (or a\n // converter that already merged the flag): read the joined metadata. Without\n // sources to count, a single text part is the best available \"marker owns the\n // row\" signal.\n const joined = message.metadata?.custom?.[ATHENA_RUN_MARKER_KEY];\n if (typeof joined !== 'string') return undefined;\n const joinedSource = message.metadata?.custom?.[ATHENA_RUN_MARKER_SOURCE_KEY];\n const parts = message.content;\n return {\n marker: joined,\n source: typeof joinedSource === 'string' ? joinedSource : undefined,\n text: undefined,\n isSoleSourceMessage: Array.isArray(parts) ? parts.length <= 1 : true,\n };\n}\n\n/**\n * The marker value when the marker is the SOLE source message behind a thread\n * message (it owns the whole row), else `undefined`.\n *\n * Returns a primitive so it is safe to use directly as a `useAuiState`\n * selector: `readRunMarkerFromSourceMessages` builds a fresh object on every\n * call, and selector snapshots are compared with `Object.is` — returning that\n * object from a selector makes `getSnapshot` unstable and loops the render.\n */\nexport function readSoleRunMarker(\n message: Parameters<typeof readRunMarkerFromSourceMessages>[0]\n): string | undefined {\n const found = readRunMarkerFromSourceMessages(message);\n return found?.isSoleSourceMessage ? found.marker : undefined;\n}\n\n/**\n * Whether a run marker renders nothing: a `send_now` promotion cancels the\n * live run as plumbing, not as a user-visible stop, so its cancellation\n * marker stays in the data for provenance but paints no divider.\n */\nexport function isSilentRunMarker(found: RunMarkerInfo): boolean {\n return (\n found.marker === ATHENA_RUN_MARKER_CANCELLED && found.source === ATHENA_STOP_SOURCE_SEND_NOW\n );\n}\n\n/**\n * Whether a cancellation marker records a server-update pause — a cooperative\n * pod drain, or the hosting instance closing under the run — rather than a\n * stop the user asked for. Rendered with distinct \"paused by a server update\"\n * copy instead of the \"Conversation stopped\" pill; the backend resumes the run.\n */\nexport function isDrainRunMarker(found: RunMarkerInfo): boolean {\n return found.marker === ATHENA_RUN_MARKER_CANCELLED && isServerUpdateStopSource(found.source);\n}\n\n/**\n * Surface the backend's top-level `additional_kwargs.athena_run_marker` flag\n * where the shipped converter can see it.\n *\n * `convertLangChainMessages` exposes ONLY `additional_kwargs.metadata` as the\n * thread message's `metadata.custom`; every other `additional_kwargs` key is\n * dropped. Marker messages persisted before the backend mirrored the flag into\n * `metadata` carry it top-level only, so this lift keeps those threads styling\n * correctly. Non-marker messages pass through with their identity unchanged,\n * and already-mirrored markers are left as-is (idempotent).\n */\nexport function liftRunMarkerIntoMetadata(message: LangChainMessage): LangChainMessage {\n if (message.type !== 'ai') return message;\n const kwargs = message.additional_kwargs as Record<string, unknown> | undefined;\n const marker = kwargs?.[ATHENA_RUN_MARKER_KEY];\n if (typeof marker !== 'string') return message;\n const existingMetadata = kwargs?.metadata;\n const metadata =\n typeof existingMetadata === 'object' && existingMetadata !== null\n ? (existingMetadata as Record<string, unknown>)\n : {};\n if (metadata[ATHENA_RUN_MARKER_KEY] === marker) return message;\n return {\n ...message,\n additional_kwargs: {\n ...kwargs,\n metadata: { ...metadata, [ATHENA_RUN_MARKER_KEY]: marker },\n } as (typeof message)['additional_kwargs'],\n };\n}\n\n/**\n * Mirror the termination reason and handoff flag into the converter's metadata\n * channel. The backend dual-writes both (top-level + `metadata`), so this lift\n * is the back-compat path for messages persisted before the mirror existed and\n * for any emitter that only stamps the top-level key. Idempotent; identity for\n * messages without the keys.\n */\nexport function liftTerminationIntoMetadata(message: LangChainMessage): LangChainMessage {\n if (message.type !== 'ai') return message;\n const kwargs = message.additional_kwargs as Record<string, unknown> | undefined;\n const reason = kwargs?.[ATHENA_TERMINATION_REASON_KEY];\n const handoff = kwargs?.[ATHENA_HANDOFF_KEY];\n const hasReason = typeof reason === 'string';\n const hasHandoff = handoff === true;\n if (!hasReason && !hasHandoff) return message;\n const existingMetadata = kwargs?.metadata;\n const metadata =\n typeof existingMetadata === 'object' && existingMetadata !== null\n ? (existingMetadata as Record<string, unknown>)\n : {};\n const reasonMirrored = !hasReason || metadata[ATHENA_TERMINATION_REASON_KEY] === reason;\n const handoffMirrored = !hasHandoff || metadata[ATHENA_HANDOFF_KEY] === true;\n if (reasonMirrored && handoffMirrored) return message;\n return {\n ...message,\n additional_kwargs: {\n ...kwargs,\n metadata: {\n ...metadata,\n ...(hasReason ? { [ATHENA_TERMINATION_REASON_KEY]: reason } : {}),\n ...(hasHandoff ? { [ATHENA_HANDOFF_KEY]: true } : {}),\n },\n } as (typeof message)['additional_kwargs'],\n };\n}\n\n/**\n * `additional_kwargs` key (and `metadata` mirror) carrying a failure marker's\n * structured error records (agora `athena_deep_agent/run_markers.py`\n * `failure_error_records`): `[{ error, provider?, message? }]`, where `error`\n * is the client code a surface branches on — `context_length_exceeded`,\n * `transient_api_error` (with `provider: 'azure_foundry' |\n * 'external_model_provider'`), `content_filter`, `request_too_large`, … — the\n * same shape the legacy agent node emitted.\n */\nexport const ATHENA_ERRORS_KEY = 'errors';\n\n/**\n * Mirror a failure marker's structured `errors` records into the converter's\n * metadata channel. The backend dual-writes them (top-level + `metadata`), so\n * this lift is the back-compat path for messages that carry only the top-level\n * key (an emitter that never mirrored, or a record persisted before the mirror\n * existed). Records already present in the metadata channel win; no-ops are\n * identity.\n */\nexport function liftErrorsIntoMetadata(message: LangChainMessage): LangChainMessage {\n if (message.type !== 'ai') return message;\n const kwargs = message.additional_kwargs as Record<string, unknown> | undefined;\n const errors = kwargs?.[ATHENA_ERRORS_KEY];\n if (!Array.isArray(errors) || errors.length === 0) return message;\n const existingMetadata = kwargs?.metadata;\n const metadata =\n typeof existingMetadata === 'object' && existingMetadata !== null\n ? (existingMetadata as Record<string, unknown>)\n : {};\n if (Array.isArray(metadata[ATHENA_ERRORS_KEY])) return message;\n return {\n ...message,\n additional_kwargs: {\n ...kwargs,\n metadata: { ...metadata, [ATHENA_ERRORS_KEY]: errors },\n } as (typeof message)['additional_kwargs'],\n };\n}\n\n/**\n * Read a failure's structured `errors` records out of a thread message's\n * **bound source messages**, bypassing the converter's metadata join.\n *\n * Same reason as {@link readRunMarkerFromSourceMessages}: assistant-ui chunks\n * consecutive assistant/tool messages into ONE `ThreadMessage` and copies\n * `metadata.custom` only from the FIRST assistant message of the chunk. The\n * failure marker that carries the records is appended after the assistant's\n * own turn, so `message.metadata.custom.errors` is silently dropped whenever\n * the run produced anything before failing. The bound sources are walked from\n * the tail (the terminal failure wins); the joined metadata is the fallback\n * for surfaces whose messages carry no bound sources. Returns the raw records\n * (callers validate the shape) or `undefined`.\n */\nexport function readMessageErrorsFromSourceMessages(\n message: Parameters<typeof getExternalStoreMessages>[0] & {\n metadata?: { custom?: Record<string, unknown> | undefined } | undefined;\n }\n): unknown[] | undefined {\n const sources = getExternalStoreMessages<LangChainMessage>(message);\n for (let index = sources.length - 1; index >= 0; index -= 1) {\n const source = sources[index];\n if (source?.type !== 'ai') continue;\n const kwargs = source.additional_kwargs as Record<string, unknown> | undefined;\n const metadata = kwargs?.metadata;\n const mirrored =\n typeof metadata === 'object' && metadata !== null\n ? (metadata as Record<string, unknown>)[ATHENA_ERRORS_KEY]\n : undefined;\n const errors = Array.isArray(mirrored) ? mirrored : kwargs?.[ATHENA_ERRORS_KEY];\n if (Array.isArray(errors) && errors.length > 0) return errors;\n }\n const joined = message.metadata?.custom?.[ATHENA_ERRORS_KEY];\n return Array.isArray(joined) && joined.length > 0 ? joined : undefined;\n}\n\n/**\n * Mirror the producing model into the converter's metadata channel. Wire AI\n * messages are full LangChain dumps whose `response_metadata` reports the model\n * that generated them (`model_name` / `model`), but the shipped converter maps\n * only `additional_kwargs.metadata` into `metadata.custom` — so without this\n * lift a surface can only show the CURRENT run config's model, mislabeling\n * earlier messages after a mid-thread model switch. A model already present in\n * the metadata channel (backend-stamped provenance) wins; no-ops are identity.\n */\nexport function liftModelIntoMetadata(message: LangChainMessage): LangChainMessage {\n if (message.type !== 'ai') return message;\n const responseMetadata = (\n message as { response_metadata?: { model_name?: unknown; model?: unknown } }\n ).response_metadata;\n let model: string | undefined;\n if (typeof responseMetadata?.model_name === 'string' && responseMetadata.model_name) {\n model = responseMetadata.model_name;\n } else if (typeof responseMetadata?.model === 'string' && responseMetadata.model) {\n model = responseMetadata.model;\n }\n if (!model) return message;\n const kwargs = message.additional_kwargs as Record<string, unknown> | undefined;\n const existingMetadata = kwargs?.metadata;\n const metadata =\n typeof existingMetadata === 'object' && existingMetadata !== null\n ? (existingMetadata as Record<string, unknown>)\n : {};\n if (typeof metadata.model === 'string' && metadata.model) return message;\n return {\n ...message,\n additional_kwargs: {\n ...kwargs,\n metadata: { ...metadata, model },\n } as (typeof message)['additional_kwargs'],\n };\n}\n\n/**\n * Mirror a per-message conversation-stats snapshot into the converter's\n * metadata channel. Backends stamp the snapshot at the legacy location —\n * top-level `additional_kwargs.conversation_stats` (the deep-agent stats\n * middleware and the legacy agent node both write it there) — but the shipped\n * converter maps only `additional_kwargs.metadata` into `metadata.custom`, so\n * without this lift the model badge can never show a message's OWN context and\n * falls back to thread-level live numbers. A snapshot already present in the\n * metadata channel wins; no-ops are identity.\n */\nexport function liftConversationStatsIntoMetadata(message: LangChainMessage): LangChainMessage {\n if (message.type !== 'ai') return message;\n const kwargs = message.additional_kwargs as Record<string, unknown> | undefined;\n const stats = kwargs?.conversation_stats;\n if (typeof stats !== 'object' || stats === null) return message;\n const existingMetadata = kwargs?.metadata;\n const metadata =\n typeof existingMetadata === 'object' && existingMetadata !== null\n ? (existingMetadata as Record<string, unknown>)\n : {};\n if (typeof metadata.conversation_stats === 'object' && metadata.conversation_stats !== null) {\n return message;\n }\n return {\n ...message,\n additional_kwargs: {\n ...kwargs,\n metadata: { ...metadata, conversation_stats: stats },\n } as (typeof message)['additional_kwargs'],\n };\n}\n\n/**\n * Mirror the compaction boundary flag into the converter's metadata channel.\n * A manual `/compact` persists its summary as a human message tagged with\n * top-level `additional_kwargs.compaction_start` (plus `_created_at` for the\n * divider timestamp) — the same location the legacy runtime used — but the\n * shipped converter maps only `additional_kwargs.metadata` into\n * `metadata.custom`, so without this lift the transcript's\n * \"Previous conversation summarized\" divider can never render. A flag already\n * present in the metadata channel wins; no-ops are identity.\n */\nexport function liftCompactionBoundaryIntoMetadata(message: LangChainMessage): LangChainMessage {\n if (message.type !== 'human') return message;\n const kwargs = message.additional_kwargs as Record<string, unknown> | undefined;\n if (kwargs?.compaction_start !== true) return message;\n const existingMetadata = kwargs?.metadata;\n const metadata =\n typeof existingMetadata === 'object' && existingMetadata !== null\n ? (existingMetadata as Record<string, unknown>)\n : {};\n if (metadata.compaction_start === true) return message;\n const createdAt = kwargs?._created_at;\n return {\n ...message,\n additional_kwargs: {\n ...kwargs,\n metadata: {\n ...metadata,\n compaction_start: true,\n ...(typeof createdAt === 'string' ? { _created_at: createdAt } : {}),\n },\n } as (typeof message)['additional_kwargs'],\n };\n}\n\n/**\n * Mirror the handoff summary flag into the converter's metadata channel.\n * Handoff summaries are persisted as human messages tagged with top-level\n * `additional_kwargs.handoff_summary` (plus `_created_at`) — the same location\n * the backend uses for message metadata — but the shipped converter maps only\n * `additional_kwargs.metadata` into `metadata.custom`, so without this lift\n * the summary would render as a normal user bubble. A flag already present in\n * the metadata channel wins; no-ops are identity.\n */\nexport function liftHandoffSummaryIntoMetadata(message: LangChainMessage): LangChainMessage {\n if (message.type !== 'human') return message;\n const kwargs = message.additional_kwargs as Record<string, unknown> | undefined;\n if (kwargs?.handoff_summary !== true) return message;\n const existingMetadata = kwargs?.metadata;\n const metadata =\n typeof existingMetadata === 'object' && existingMetadata !== null\n ? (existingMetadata as Record<string, unknown>)\n : {};\n if (metadata.handoff_summary === true) return message;\n const createdAt = kwargs?._created_at;\n return {\n ...message,\n additional_kwargs: {\n ...kwargs,\n metadata: {\n ...metadata,\n handoff_summary: true,\n ...(typeof createdAt === 'string' ? { _created_at: createdAt } : {}),\n },\n } as (typeof message)['additional_kwargs'],\n };\n}\n\n/**\n * Mirror an AOP run's provenance into the converter's metadata channel. The\n * backend stamps the kicking-off user message with top-level\n * `additional_kwargs.aop_source` (agora `events/helpers.py`\n * `_build_aop_source_metadata`), which the legacy converter surfaced as\n * `metadata.custom.aop_source` — where the \"AOP · <title>\" badge reads it. The\n * shipped `convertLangChainMessages` maps only `additional_kwargs.metadata`\n * into `metadata.custom`, so without this lift an AOP run's conversation never\n * shows which AOP asset kicked it off. Provenance already present in the\n * metadata channel wins; no-ops are identity.\n */\nexport function liftAopSourceIntoMetadata(message: LangChainMessage): LangChainMessage {\n if (message.type !== 'human') return message;\n const kwargs = message.additional_kwargs as Record<string, unknown> | undefined;\n const aopSource = kwargs?.aop_source;\n if (typeof aopSource !== 'object' || aopSource === null || Array.isArray(aopSource)) {\n return message;\n }\n const existingMetadata = kwargs?.metadata;\n const metadata =\n typeof existingMetadata === 'object' && existingMetadata !== null\n ? (existingMetadata as Record<string, unknown>)\n : {};\n if (typeof metadata.aop_source === 'object' && metadata.aop_source !== null) return message;\n return {\n ...message,\n additional_kwargs: {\n ...kwargs,\n metadata: { ...metadata, aop_source: aopSource },\n } as (typeof message)['additional_kwargs'],\n };\n}\n\nexport function liftBranchIntoMetadata(message: LangChainMessage): LangChainMessage {\n if (message.type !== 'human' && message.type !== 'ai') return message;\n const branch = (message as { branch?: unknown }).branch;\n if (typeof branch !== 'object' || branch === null || Array.isArray(branch)) return message;\n const kwargs = message.additional_kwargs as Record<string, unknown> | undefined;\n const existingMetadata = kwargs?.metadata;\n const metadata =\n typeof existingMetadata === 'object' && existingMetadata !== null\n ? (existingMetadata as Record<string, unknown>)\n : {};\n if (typeof metadata.branch === 'object' && metadata.branch !== null) return message;\n return {\n ...message,\n additional_kwargs: {\n ...kwargs,\n metadata: { ...metadata, branch },\n } as (typeof message)['additional_kwargs'],\n };\n}\n\n/**\n * `additional_kwargs` keys on a ToolMessage that are infrastructure rather than\n * user-set metadata. The filter below additionally skips every `_`-prefixed key.\n */\nconst TOOL_MESSAGE_INTERNAL_KWARGS: ReadonlySet<string> = new Set([\n 'reasoning',\n 'tool_outputs',\n 'hide_from_frontend',\n]);\n\n/**\n * Mirror a ToolMessage's user-set `additional_kwargs` into\n * `artifact._tool_message_metadata` — the location `useToolCallMetadata` reads\n * persisted per-tool-call metadata from (`email_sent_at`, draft edits,\n * `calendar_event_created_at`, …).\n *\n * The `setMessageMetadata` mutation persists those keys onto the ToolMessage's\n * `additional_kwargs` in the checkpoint, and the legacy converter lifted them\n * into the artifact. The shipped `convertLangChainMessages` forwards only\n * `artifact` and drops `additional_kwargs` for tool messages, so without this\n * lift the metadata survives in the checkpoint but never reaches a tool card\n * after a reload. Kwargs values win over same-key artifact entries (the kwargs\n * are the durable write target); messages with no user-set kwargs pass through\n * by identity.\n */\nexport function liftToolMessageMetadataIntoArtifact(message: LangChainMessage): LangChainMessage {\n if (message.type !== 'tool') return message;\n const kwargs = (message as { additional_kwargs?: Record<string, unknown> }).additional_kwargs;\n if (!kwargs) return message;\n const lifted: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(kwargs)) {\n if (key.startsWith('_') || TOOL_MESSAGE_INTERNAL_KWARGS.has(key)) continue;\n lifted[key] = value;\n }\n if (Object.keys(lifted).length === 0) return message;\n const artifact: unknown = message.artifact;\n const artifactRecord =\n typeof artifact === 'object' && artifact !== null && !Array.isArray(artifact)\n ? (artifact as Record<string, unknown>)\n : {};\n const existing = artifactRecord._tool_message_metadata;\n const existingRecord =\n typeof existing === 'object' && existing !== null && !Array.isArray(existing)\n ? (existing as Record<string, unknown>)\n : {};\n return {\n ...message,\n artifact: {\n ...artifactRecord,\n _tool_message_metadata: { ...existingRecord, ...lifted },\n },\n };\n}\n\n/**\n * Lift a windowed wire's tool-output truncation marker into the tool-call\n * part's `artifact` (`_athena_content_truncated: { chars, messageId }`).\n *\n * The host cuts long plain-text tool outputs on a windowed wire and stamps\n * `athena_content_truncated` on the wire message; the shipped converter joins\n * a ToolMessage into its assistant turn's tool-call part and keeps only\n * `artifact` and the result, so without this lift no tool card could tell the\n * output is cut nor which message to ask `history/tool_output` for. Messages\n * without the marker pass through by identity.\n */\nexport function liftTruncatedToolOutputIntoArtifact(message: LangChainMessage): LangChainMessage {\n if (message.type !== 'tool') return message;\n const marker = readTruncatedToolContent(message);\n if (marker === null || typeof message.id !== 'string') return message;\n const artifact: unknown = message.artifact;\n const artifactRecord =\n typeof artifact === 'object' && artifact !== null && !Array.isArray(artifact)\n ? (artifact as Record<string, unknown>)\n : {};\n return {\n ...message,\n artifact: {\n ...artifactRecord,\n [ATHENA_TRUNCATED_TOOL_OUTPUT_ARTIFACT_KEY]: { chars: marker.chars, messageId: message.id },\n },\n };\n}\n\n/**\n * A content list's bare-string entries as typed text parts.\n *\n * LangChain content is `string | (string | ContentBlock)[]`, and a model with\n * no tools bound streams exactly that mix: `langchain_anthropic` coerces text\n * deltas to plain strings when no tools are bound, yet a thinking block still\n * arrives as a list block, so the merged reply is `[\"\", {thinking}, \"text\"]`\n * (the side-question lane's bare model). The shipped converter maps only typed\n * blocks and drops the strings, leaving the reasoning with no answer. Empty\n * strings are dropped; messages with no string entries pass through by\n * identity.\n */\nexport function normalizeStringContentParts(message: LangChainMessage): LangChainMessage {\n const content: unknown = message.content;\n if (!Array.isArray(content) || !content.some((part) => typeof part === 'string')) {\n return message;\n }\n const parts = content.flatMap((part: unknown) => {\n if (typeof part !== 'string') return [part];\n return part.length > 0 ? [{ type: 'text', text: part }] : [];\n });\n return { ...message, content: parts } as LangChainMessage;\n}\n\n/**\n * Per-source cache for {@link substituteToolOutput}: a substituted copy is\n * reused while the wire message and the fetched output are both unchanged, so\n * the lift cache downstream keeps its identity contract.\n */\nconst substitutedToolOutputCache = new WeakMap<\n LangChainMessage,\n { content: unknown; substituted: LangChainMessage }\n>();\n\n/**\n * A cut tool message with its full output put back, when the store holds one\n * fetched for this very output (`history/tool_output` answered for the same\n * `chars` the wire's marker reports); the marker leaves with the cut.\n * Messages that are whole, whose output has not been fetched, or whose fetched\n * output belongs to a length the host has since replaced, pass through by\n * identity — the loader sees the mismatch and fetches again.\n */\nexport function substituteToolOutput(\n message: LangChainMessage,\n toolOutputs: DeepAgentToolOutputStore\n): LangChainMessage {\n if (message.type !== 'tool' || typeof message.id !== 'string') return message;\n const marker = readTruncatedToolContent(message);\n if (marker === null) return message;\n const entry = toolOutputs.entry(message.id);\n if (entry === undefined || entry.chars !== marker.chars) return message;\n const { content } = entry;\n const cached = substitutedToolOutputCache.get(message);\n if (cached !== undefined && cached.content === content) return cached.substituted;\n const { [DEEP_AGENT_TRUNCATED_CONTENT_KEY]: _marker, ...rest } = message as Record<\n string,\n unknown\n >;\n const substituted = { ...rest, content } as unknown as LangChainMessage;\n substitutedToolOutputCache.set(message, { content, substituted });\n return substituted;\n}\n\nconst hasHiddenFrontendFlag = (value: unknown): boolean => {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return false;\n }\n const record = value as Record<string, unknown>;\n if (record.hide_from_frontend === true) return true;\n return hasHiddenFrontendFlag(record.custom);\n};\n\n/**\n * Internal orchestration messages are useful in a trace export but must never\n * become conversation bubbles. Agora stores the flag in `additional_kwargs`;\n * live converter state can expose the same value under `metadata.custom`.\n */\nexport function isMessageHiddenFromFrontend(message: unknown): boolean {\n if (typeof message !== 'object' || message === null || Array.isArray(message)) {\n return false;\n }\n const record = message as Record<string, unknown>;\n return (\n hasHiddenFrontendFlag(record.additional_kwargs) || hasHiddenFrontendFlag(record.metadata)\n );\n}\n\n/**\n * The message `type`s `convertLangChainMessages` actually maps: its\n * `switch (message.type)` covers exactly these four and has no `default`, so it\n * returns `undefined` for anything else (a `RemoveMessage` `type: \"remove\"`\n * from summarization/compaction, a partial chunk, a future type).\n */\nconst CONVERTIBLE_MESSAGE_TYPES: ReadonlySet<string> = new Set(['system', 'human', 'ai', 'tool']);\n\n/**\n * Whether `convertLangChainMessages` can map this message at all.\n *\n * An unmappable entry converts to `undefined`, which assistant-ui's\n * `convertExternalMessages` wraps as `outputs: [undefined]` and then reads\n * `output.role` off — throwing `Cannot read property 'role' of undefined` and\n * taking the entire thread down instead of dropping one message.\n */\nexport function isConvertibleChatMessage(message: unknown): boolean {\n if (typeof message !== 'object' || message === null || Array.isArray(message)) {\n return false;\n }\n const type: unknown = (message as Record<string, unknown>).type;\n return typeof type === 'string' && CONVERTIBLE_MESSAGE_TYPES.has(type);\n}\n\n/**\n * Per-source cache for the lift pipeline in {@link sanitizeLangChainMessages}.\n *\n * The pipeline runs on EVERY state pass (once per streamed token), and the two\n * lifts that fire for essentially every message — {@link liftBranchIntoMetadata}\n * (the backend stamps `branch` on all indexed messages) and\n * {@link liftModelIntoMetadata} — allocate a fresh object each time they lift.\n * Without a cache, every message's identity churns on every token, defeating\n * all downstream per-source memoization (`getExternalStoreMessages`-keyed\n * reads, converter callback caches) and re-deriving the whole thread per token.\n *\n * Object identity is a sound cache key here: every statewire fold (op apply,\n * optimistic, materialize) runs through `statewire`'s copy-on-write\n * `recordMutations`, whose `finalize` returns the ORIGINAL object for\n * untouched nodes and a fresh copy for touched ones. A message is therefore\n * REPLACED — never mutated in place — whenever any of its fields change\n * (including the streaming tail's string-insert content growth), and an\n * unchanged message keeps its exact identity across passes. The corpus test\n * (`statewire-corpus.test.ts`) pins this identity contract against the real\n * client, so a statewire upgrade that switched to in-place mutation would fail\n * there rather than silently serving stale lifts from this cache.\n *\n * Module-level on purpose: keys are the wire message objects themselves, so\n * entries die with their state trees and threads cannot collide.\n */\nconst liftedMessageCache = new WeakMap<LangChainMessage, LangChainMessage>();\n\n/** The full lift chain for one message, memoized per source object. */\nfunction liftMessageIntoMetadataChannels(message: LangChainMessage): LangChainMessage {\n const cached = liftedMessageCache.get(message);\n if (cached !== undefined) return cached;\n const lifted = liftBranchIntoMetadata(\n liftTruncatedToolOutputIntoArtifact(\n liftToolMessageMetadataIntoArtifact(\n liftAopSourceIntoMetadata(\n liftHandoffSummaryIntoMetadata(\n liftCompactionBoundaryIntoMetadata(\n liftConversationStatsIntoMetadata(\n liftModelIntoMetadata(\n liftErrorsIntoMetadata(\n liftTerminationIntoMetadata(\n liftRunMarkerIntoMetadata(normalizeStringContentParts(message))\n )\n )\n )\n )\n )\n )\n )\n )\n )\n );\n liftedMessageCache.set(message, lifted);\n return lifted;\n}\n\n/**\n * The one message pipeline every deep-agent surface renders through:\n *\n * 1. drop messages the shipped converter cannot map (`RemoveMessage` etc. —\n * an unmappable entry would crash the whole thread) and internal\n * orchestration messages flagged hidden-from-frontend;\n * 1a. turn bare-string entries of a content list into typed text parts (see\n * {@link normalizeStringContentParts}) so a tool-less model's answer next\n * to its thinking block is not dropped by the converter;\n * 2. lift run-lifecycle markers into the converter's `metadata` channel\n * (see {@link liftRunMarkerIntoMetadata}) so the cancellation row styles as\n * a status divider instead of a plain assistant bubble, and the termination\n * reason + handoff flag alongside them (see\n * {@link liftTerminationIntoMetadata}) so every surface can render a\n * runtime ending (see `runtime-messages.ts`);\n * 3. lift each AI message's producing model into the same channel\n * (see {@link liftModelIntoMetadata}) so model badges reflect the model that\n * actually generated the message, not the currently configured one;\n * 4. lift each AI message's per-message conversation-stats snapshot into the\n * same channel (see {@link liftConversationStatsIntoMetadata}) so the model\n * badge's hover card shows that message's own context usage;\n * 5. lift the compaction boundary flag on `/compact` summary messages into the\n * same channel (see {@link liftCompactionBoundaryIntoMetadata}) so the\n * transcript renders its \"Previous conversation summarized\" divider;\n * 6. lift the handoff summary flag on carried-over context messages into the\n * same channel (see {@link liftHandoffSummaryIntoMetadata}) so the\n * transcript keeps the summary behind its context panel;\n * 7. lift an AOP run's provenance on its kicking-off user message into the\n * same channel (see {@link liftAopSourceIntoMetadata}) so the message\n * renders its \"AOP · <title>\" origin badge;\n * 8. lift each ToolMessage's user-set `additional_kwargs` into\n * `artifact._tool_message_metadata` (see\n * {@link liftToolMessageMetadataIntoArtifact}) so persisted per-tool-call\n * metadata reaches tool cards after a reload;\n * 9. lift a windowed wire's tool-output truncation marker into the tool-call\n * part's `artifact` (see {@link liftTruncatedToolOutputIntoArtifact}) so a\n * tool card can fetch the whole output — after first putting back any\n * output already fetched (see {@link substituteToolOutput});\n * 10. lift the host's per-message branch stamp into the same channel\n * (see {@link liftBranchIntoMetadata}) so the branch picker renders each\n * message's edit fan-out.\n *\n * Identity-stable per source: an unchanged source message maps to the\n * IDENTICAL lifted object across passes (see {@link liftedMessageCache}).\n */\nexport function sanitizeLangChainMessages(\n messages: readonly LangChainMessage[],\n { toolOutputs }: { toolOutputs?: DeepAgentToolOutputStore } = {}\n): LangChainMessage[] {\n return messages\n .filter((message) => isConvertibleChatMessage(message) && !isMessageHiddenFromFrontend(message))\n .map((message) =>\n liftMessageIntoMetadataChannels(\n toolOutputs ? substituteToolOutput(message, toolOutputs) : message\n )\n );\n}\n\n/** Type guard for the runtime state — an object carrying a `messages` array. */\nexport function isLangGraphState(value: unknown): value is LangGraphState {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'messages' in value &&\n Array.isArray((value as LangGraphState).messages)\n );\n}\n\nexport interface ConvertDeepAgentStateOptions {\n laneProjection?: DeepAgentLaneProjection;\n /**\n * The viewer, as the backend would stamp them: the author of this client's\n * own not-yet-acknowledged lane entries (see {@link laneEntryAuthor}).\n */\n selfAuthor?: DeepAgentMessageAuthor | null;\n /**\n * Full tool outputs fetched back for a windowed wire's cut tool messages\n * (see {@link substituteToolOutput}); omitted on surfaces that never\n * declare a window.\n */\n toolOutputs?: DeepAgentToolOutputStore;\n /**\n * User turns this client took back ahead of the wire (see\n * {@link DeepAgentWithdrawnTurns}): omitted from the transcript, together\n * with the pending-assistant placeholder a withdrawn tail would earn.\n */\n withdrawnTurns?: DeepAgentWithdrawnTurns;\n /**\n * The attached thread's conversion memory (see\n * {@link createDeepAgentMessageConversionCache}): unchanged messages keep\n * their converted identity across passes. Without one every pass converts\n * the whole transcript from scratch.\n */\n conversionCache?: DeepAgentMessageConversionCache;\n}\n\n/**\n * Keep the live assistant turn running when lane entries render after it.\n *\n * assistant-ui derives an assistant message's status from its position: the\n * last message of a running thread is `running`, while an earlier one whose\n * tool call has no result yet reads as `requires-action` (its\n * `AUTO_STATUS_PENDING`). A steer-lane entry projected into the tail — a\n * Steer waiting for the run's next model call, a Send now waiting for the\n * cancel — therefore demoted the turn it follows, and the tool card showed\n * \"Waiting for you\" over a tool that was still executing. An explicit status\n * on the source wins over the derived one (`fromThreadMessageLike`), so while\n * the run is live and a lane tail follows, the last assistant turn keeps the\n * `running` status it would have been given were it still last. Trailing tool\n * messages merge into that turn, so the last `ai` message is the one to stamp.\n */\nfunction keepTailRunningAheadOfLanes(\n messages: LangChainMessage[],\n hasLaneTail: boolean\n): LangChainMessage[] {\n if (!hasLaneTail) return messages;\n for (let index = messages.length - 1; index >= 0; index -= 1) {\n const message = messages[index];\n if (message === undefined) continue;\n if (message.type === 'human' || message.type === 'system') return messages;\n if (message.type === 'ai') {\n if (message.status !== undefined) return messages;\n const stamped = [...messages];\n stamped[index] = runningStampOf(message);\n return stamped;\n }\n }\n return messages;\n}\n\n/**\n * The stamped copies, one per source message: the conversion cache keys on\n * source identity, so the same wire message must yield the same stamped\n * object across passes or every render would reconvert the live turn.\n */\ntype AssistantLangChainMessage = Extract<LangChainMessage, { type: 'ai' }>;\n\nconst runningStamps = new WeakMap<AssistantLangChainMessage, AssistantLangChainMessage>();\n\nfunction runningStampOf(message: AssistantLangChainMessage): AssistantLangChainMessage {\n const cached = runningStamps.get(message);\n if (cached !== undefined) return cached;\n const stamped: AssistantLangChainMessage = { ...message, status: { type: 'running' } };\n runningStamps.set(message, stamped);\n return stamped;\n}\n\n/**\n * Map server state → assistant-ui thread messages.\n *\n * `state.messages` is the authoritative LangChain history streamed by the\n * backend. The replicated run status (`runs[0].status`) drives the\n * pending-assistant placeholder and the running status. Lane entries render at\n * the tail, after the placeholder, while the run is live (the run is still\n * working the history above them); once the thread rests stopped/errored they\n * are omitted (surfaces with a queue panel list them there instead).\n * Consecutive spoken user turns collapse into one user message (see\n * {@link groupSpokenUserTurns}) before conversion.\n */\nexport function convertDeepAgentState(\n state: unknown,\n {\n laneProjection = 'both',\n selfAuthor = null,\n toolOutputs,\n withdrawnTurns,\n conversionCache,\n }: ConvertDeepAgentStateOptions = {}\n) {\n // A wire without a snapshot yet (pre-attach, replay boundary) converts as the\n // typed pre-stream default: an empty resting thread, never `undefined`.\n const values = readDeepAgentStreamValues(state);\n const status = values.runs?.[0]?.status;\n const isRunning = status === 'running';\n const isWithdrawn = (message: LangChainMessage): boolean =>\n withdrawnTurns !== undefined && message.id !== undefined && withdrawnTurns.isWithdrawn(message.id);\n const laneTail = (\n status === 'stopped' || status === 'error'\n ? []\n : laneTailMessages(values, laneProjection, selfAuthor)\n ).filter((message) => !isWithdrawn(message));\n const sanitized: LangChainMessage[] = isLangGraphState(values)\n ? sanitizeLangChainMessages(values.messages, { toolOutputs })\n : [];\n // A withdrawn tail is a turn nobody is answering: no placeholder for it.\n const tail: LangChainMessage | undefined = sanitized[sanitized.length - 1];\n const tailWithdrawn: boolean = tail !== undefined && isWithdrawn(tail);\n const stateMessages = groupSpokenUserTurns(sanitized.filter((message) => !isWithdrawn(message)));\n const sources = [\n ...keepTailRunningAheadOfLanes(\n withPendingAssistantMessage(stateMessages, isRunning && !tailWithdrawn),\n isRunning && laneTail.length > 0\n ),\n ...laneTail,\n ];\n return {\n messages: conversionCache\n ? conversionCache.convert(sources, isRunning)\n : messageConverter.toThreadMessages(sources, isRunning),\n isRunning,\n };\n}\n"],"names":["createMessageConverter","convertLangChainMessages","createExternalMessageConversionCache","convertExternalMessages","getExternalStoreMessages","row","laneEntryAuthor","composerMarkdown","DEEP_AGENT_COMPOSER_MARKDOWN_KEY","ATHENA_MESSAGE_AUTHOR_KEY","buildOptimisticHumanContent","runsMaterialize","readTruncatedToolContent","ATHENA_TRUNCATED_TOOL_OUTPUT_ARTIFACT_KEY","DEEP_AGENT_TRUNCATED_CONTENT_KEY","readDeepAgentStreamValues","groupSpokenUserTurns"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"messages.cjs","sources":["../../../../agent-runtime/src/messages.ts"],"sourcesContent":["import {\n getExternalStoreMessages,\n type MessageTiming,\n type ThreadAssistantMessage,\n type ThreadAssistantMessagePart,\n type ThreadMessage,\n type ThreadStep,\n} from '@assistant-ui/core';\nimport {\n convertExternalMessages,\n createExternalMessageConversionCache,\n createMessageConverter,\n type useExternalMessageConverter,\n} from '@assistant-ui/core/react';\nimport { convertLangChainMessages, type LangChainMessage } from '@assistant-ui/react-langgraph';\nimport { runsMaterialize, type StatewireThread } from '@assistant-ui/react-statewire';\nimport {\n ATHENA_MESSAGE_AUTHOR_KEY,\n type DeepAgentMessageAuthor,\n laneEntryAuthor,\n} from './message-author';\nimport { DEEP_AGENT_COMPOSER_MARKDOWN_KEY } from './composer-markdown';\nimport { DEEP_AGENT_TRUNCATED_CONTENT_KEY } from './generated/runconfig-contract';\nimport {\n ATHENA_TRUNCATED_TOOL_OUTPUT_ARTIFACT_KEY,\n readTruncatedToolContent,\n} from './message-window';\nimport { buildOptimisticHumanContent, type OptimisticContentPart } from './optimistic-content';\nimport { isRunningToolPlaceholderArtifact } from './running-tool-placeholder';\nimport { readDeepAgentStreamValues } from './statewire-state';\nimport type { DeepAgentToolOutputStore } from './tool-outputs';\nimport { groupSpokenUserTurns } from './voice-turn-grouping';\nimport type { DeepAgentWithdrawnTurns } from './withdrawn-turns';\nimport type {\n DeepAgentLaneProjection,\n DeepAgentStreamValues,\n LangGraphState,\n} from './types';\n\n/** Adapters whose `input_tokens` leaves the prompt cache out (agora's `lane_usage`). */\nconst CACHE_EXCLUSIVE_ADAPTERS: ReadonlySet<string> = new Set([\n 'amazon_bedrock',\n 'aws_bedrock',\n 'bedrock',\n]);\n\n/** A token count as the ledger reads one: a number (truncated) or a string of digits, else `fallback`. */\nconst tokens = (value: unknown, fallback = 0): number =>\n typeof value === 'number' && Number.isFinite(value)\n ? Math.trunc(value)\n : typeof value === 'string' && /^\\d+$/.test(value)\n ? Number(value)\n : fallback;\n\n/** The ledger's detail keys for a cache count, the first one present winning. */\nconst CACHE_READ_KEYS = ['cache_read', 'cached', 'cached_tokens', 'cache_read_tokens'];\nconst CACHE_CREATION_KEYS = [\n 'cache_creation',\n 'cache_creation_tokens',\n 'cache_write',\n 'cache_write_tokens',\n];\n\nconst cacheCount = (details: Record<string, unknown>, keys: readonly string[]): number => {\n for (const key of keys) {\n if (details[key] != null) return tokens(details[key]);\n }\n return 0;\n};\n\n/**\n * A model call's token use as assistant-ui's native step usage, read off the\n * LangChain message's `usage_metadata` with the session ledger's rule (agora\n * `normalize_usage_metadata`, as `lane_usage.usage_counts` reads it; both are\n * held to the same shapes): `inputTokens` counts the whole input, the prompt\n * cache's reads and writes included, added in when the adapter left them out\n * (the legacy Bedrock adapter) or the totals prove it did. `undefined` for a\n * message that reports no usage.\n */\nexport function nativeStepUsage(message: LangChainMessage): ThreadStep['usage'] {\n const { usage_metadata: usage, response_metadata: response } = message as {\n usage_metadata?: Record<string, unknown> | null;\n response_metadata?: { model_provider?: unknown };\n };\n if (typeof usage !== 'object' || usage === null) return undefined;\n const input = tokens(usage.input_tokens);\n const output = tokens(usage.output_tokens);\n const total = tokens(usage.total_tokens, input + output);\n const details =\n typeof usage.input_token_details === 'object' && usage.input_token_details !== null\n ? (usage.input_token_details as Record<string, unknown>)\n : {};\n const cached = cacheCount(details, CACHE_READ_KEYS) + cacheCount(details, CACHE_CREATION_KEYS);\n const adapter = response?.model_provider;\n const excluded =\n cached !== 0 &&\n ((typeof adapter === 'string' &&\n CACHE_EXCLUSIVE_ADAPTERS.has(adapter.trim().toLowerCase().replace(/-/g, '_'))) ||\n total < cached + output);\n return { inputTokens: excluded ? input + cached : input, outputTokens: output };\n}\n\n/**\n * The server's clock for a turn as assistant-ui's native message timing. A\n * turn's final AI message carries when the turn started and how long it ran\n * (`agent_start_time`, `agent_duration_seconds`; agora `turn_timing.py`), and a\n * joined turn takes its last message's timing, so the converted turn reads its\n * own. The wire carries no first-token time or chunk count.\n */\nfunction nativeTurnTiming(message: LangChainMessage): MessageTiming | undefined {\n if (message.type !== 'ai') return undefined;\n const kwargs = message.additional_kwargs as Record<string, unknown> | undefined;\n const start = kwargs?.agent_start_time;\n const duration = kwargs?.agent_duration_seconds;\n if (typeof start !== 'number' || typeof duration !== 'number' || !(start > 0 && duration >= 0)) {\n return undefined;\n }\n return {\n streamStartTime: start * 1000,\n totalStreamTime: duration * 1000,\n totalChunks: 0,\n toolCallCount: message.tool_calls?.length ?? 0,\n };\n}\n\n/**\n * The shipped `convertLangChainMessages` with assistant-ui's native step and\n * timing metadata filled in for an AI message: `metadata.steps` holds its model\n * call with its token use ({@link nativeStepUsage}), and a turn's final message\n * carries the turn's `metadata.timing` ({@link nativeTurnTiming}). assistant-ui\n * joins a turn's messages by concatenating their steps (`joinExternalMessages`),\n * so a converted turn lists every model call it made. Any other message converts\n * as the shipped converter has it.\n */\nexport const convertDeepAgentLangChainMessage: useExternalMessageConverter.Callback<\n LangChainMessage\n> = (message, metadata) => {\n const converted = convertLangChainMessages(message, metadata);\n if (message.type !== 'ai' || Array.isArray(converted) || converted.role !== 'assistant') {\n return converted;\n }\n const usage = nativeStepUsage(message);\n const timing = nativeTurnTiming(message);\n if (usage === undefined && timing === undefined) return converted;\n return {\n ...converted,\n metadata: {\n ...converted.metadata,\n ...(usage !== undefined && { steps: [{ messageId: message.id, usage }] }),\n ...(timing !== undefined && { timing }),\n },\n };\n};\n\n/**\n * Native message converter for the deep-agent runtime.\n *\n * This is the entire \"conversion\" layer: assistant-ui's shipped\n * `convertLangChainMessages` (from `@assistant-ui/react-langgraph`) wired\n * through `createMessageConverter`, with the native step and timing metadata\n * the shipped converter leaves out ({@link convertDeepAgentLangChainMessage}).\n * No bespoke per-message mapping — the agora `athena_deep_agent` graph streams\n * standard LangChain messages via `append_langgraph_event`, and the shipped\n * converter renders them.\n */\nexport const messageConverter = createMessageConverter(convertDeepAgentLangChainMessage);\n\n/**\n * The marked copy of each converted assistant turn holding a running tool's\n * placeholder result, keyed on the converted turn: the conversion keeps an\n * unchanged turn's object across passes, so its marked copy keeps its identity\n * too.\n */\nconst preliminaryMarkedTurns = new WeakMap<ThreadMessage, ThreadMessage>();\n\n/**\n * `message` with every tool call whose result is still the backend's\n * running-tool placeholder (see {@link isRunningToolPlaceholderArtifact})\n * marked `isPreliminary`: the result is interim, and the call has not settled.\n *\n * The shipped converter joins a placeholder ToolMessage into its call like any\n * result, which would read as a finished call on every surface: assistant-ui\n * gives a part with a result the `complete` status (cards draw \"done\", and a\n * tool's completion side effects fire with the interim payload), and a tool's\n * `streamCall` reader resolves with it. A preliminary part instead takes its\n * message's status (`running` while the run is) and the reader waits for the\n * real result, while the card still reads the interim one (progress, a deep\n * research id, a streaming description). The real ToolMessage carries no\n * marker, so its part is plain again. Turns without a placeholder pass through\n * by identity.\n */\nexport function markPreliminaryToolResults(message: ThreadMessage): ThreadMessage {\n if (message.role !== 'assistant') return message;\n const cached = preliminaryMarkedTurns.get(message);\n if (cached !== undefined) return cached;\n let content: ThreadAssistantMessagePart[] | null = null;\n for (const [index, part] of message.content.entries()) {\n if (part.type !== 'tool-call' || part.isPreliminary === true) continue;\n if (!isRunningToolPlaceholderArtifact(part.artifact)) continue;\n content ??= [...message.content];\n content[index] = { ...part, isPreliminary: true };\n }\n const marked: ThreadMessage = content === null ? message : { ...message, content };\n preliminaryMarkedTurns.set(message, marked);\n return marked;\n}\n\n/**\n * What a thread's conversion memory does: one pass's messages in, the pass's\n * rows out. {@link DeepAgentMessageConversionCache} is the shared one; a host\n * can build on it (`createSubagentTranscriptConversionCache`).\n */\nexport interface DeepAgentConversionMemory {\n convert(messages: LangChainMessage[], isRunning: boolean): ThreadMessage[];\n}\n\n/**\n * One thread's conversion memory: converting through it maps every source\n * message that is unchanged since the previous pass to the IDENTICAL\n * `ThreadMessage`, so a streamed token rebuilds only the turn it lands in\n * instead of every message in the transcript (and every per-message\n * subscriber, memo and tool card below it).\n *\n * Create one per attached thread and drop it with the attach: entries are\n * keyed by source message identity (WeakMaps, so they die with the wire state\n * that holds them), and a fresh cache per attach keeps one thread's converted\n * messages from ever being served for another.\n */\nexport class DeepAgentMessageConversionCache implements DeepAgentConversionMemory {\n private readonly cache = createExternalMessageConversionCache();\n /**\n * Every cached entry is rebuilt when the metadata object changes identity,\n * so it is created once per cache and never per pass. The tool-args\n * key-order memory keeps a finished tool call's `argsText` in the order its\n * arguments streamed in (assistant-ui's own LangGraph runtime passes the\n * same).\n */\n private readonly metadata: useExternalMessageConverter.Metadata & {\n readonly toolArgsKeyOrderCache: Map<string, Map<string, string[]>>;\n } = { toolArgsKeyOrderCache: new Map() };\n private previous: ThreadMessage[] | null = null;\n /** `convertExternalMessages`' own rows for the previous pass, before parts were kept. */\n private previousConverted: ThreadMessage[] | null = null;\n\n /**\n * Convert one pass's LangChain messages. Returns the previous pass's array\n * itself when every converted message is unchanged, so a packet that moved\n * no message re-renders no message; a re-converted turn keeps the row key\n * of the row it continues (see {@link deepAgentRowKey}) and the previous\n * pass's part objects for the parts that did not change\n * (see {@link keepUnchangedParts}).\n */\n convert(messages: LangChainMessage[], isRunning: boolean): ThreadMessage[] {\n const converted = convertExternalMessages(\n messages,\n convertDeepAgentLangChainMessage,\n isRunning,\n this.metadata,\n this.cache\n ).map(markPreliminaryToolResults);\n const next =\n this.previous !== null && this.previousConverted !== null\n ? keepUnchangedParts({\n previous: this.previous,\n previousConverted: this.previousConverted,\n converted,\n })\n : converted;\n this.previousConverted = converted;\n if (this.previous !== null && isSameMessageList(this.previous, next)) return this.previous;\n this.previous = next;\n return next;\n }\n}\n\n/**\n * Whether a re-converted part renders as the previous pass's did: every own key\n * holds the same value, the source messages assistant-ui binds under a symbol\n * (a new array on every join) compared message by message.\n */\nfunction sameMessagePart(previous: object, next: object): boolean {\n if (previous === next) return true;\n const keys = Reflect.ownKeys(next);\n if (keys.length !== Reflect.ownKeys(previous).length) return false;\n for (const key of keys) {\n if (!Object.prototype.hasOwnProperty.call(previous, key)) return false;\n const before: unknown = Reflect.get(previous, key);\n const after: unknown = Reflect.get(next, key);\n if (Object.is(before, after)) continue;\n const sameSources =\n typeof key === 'symbol' &&\n Array.isArray(before) &&\n Array.isArray(after) &&\n before.length === after.length &&\n before.every((source, index) => Object.is(source, after[index]));\n if (!sameSources) return false;\n }\n return true;\n}\n\n/** Where a row carries a key that differs from its id (see {@link deepAgentRowKey}). */\nconst ROW_KEY = Symbol.for('@athenaintel/agent-runtime/row-key');\n\n/**\n * The key a deep-agent thread message renders under in a message list: its\n * id, except for a turn that grew at its head.\n *\n * assistant-ui joins an agent run's consecutive messages into one turn whose\n * id is its first message's, so a page of older history that folds into the\n * first loaded turn (a long run's earlier steps) gives that turn a new id on\n * every page. The conversion cache keeps such a turn under the key of the row\n * it continues, so a list keyed by it keeps the turn's row, and the row's own\n * state, while the page lands. What is mounted inside the row stays mounted\n * only if the parts render under keys that survive the fold too: assistant-ui\n * keys a toolkit group by its first part, which the fold changes when its\n * steps join that group (`GroupedMessageParts` in `@athenaintel/react` carries\n * the keys over). `message.id` stays the message's id: metadata, links and\n * anchors read it.\n *\n * Takes a converted message or the message state assistant-ui publishes for\n * it, which copies the key. A message from another runtime, or one converted\n * without a conversion cache, renders under its id.\n */\nexport function deepAgentRowKey(message: { readonly id: string }): string {\n const key: unknown = Reflect.get(message, ROW_KEY);\n return typeof key === 'string' ? key : message.id;\n}\n\n/**\n * This pass's rows: the previous pass's row for every message the conversion\n * returned unchanged, and for a re-converted message the previous row it\n * continues, the one holding any of its source messages, else the one with\n * its id. The new row keeps that row's key (see {@link deepAgentRowKey}) and,\n * when both are assistant turns, its part objects wherever a part is\n * unchanged (see {@link withUnchangedParts}).\n *\n * assistant-ui builds every part of a re-converted turn as a new object, and its\n * thread keys each part's state (what a tool card or text part reads) on the\n * part object, so without this every tool card of the turn being generated\n * re-renders on every streamed token although only the streaming text changed.\n */\nfunction keepUnchangedParts({\n previous,\n previousConverted,\n converted,\n}: {\n previous: readonly ThreadMessage[];\n previousConverted: readonly ThreadMessage[];\n converted: readonly ThreadMessage[];\n}): ThreadMessage[] {\n let previousByConverted: Map<ThreadMessage, ThreadMessage> | null = null;\n let previousBySource: Map<unknown, ThreadMessage> | null = null;\n let previousById: Map<string, ThreadMessage> | null = null;\n let rowIds: ReadonlySet<string> | null = null;\n const continuedKeys = new Set<string>();\n const continuedRow = (message: ThreadMessage, index: number): ThreadMessage | undefined => {\n const atIndex: ThreadMessage | undefined = previous[index];\n if (atIndex?.id === message.id) return atIndex;\n previousBySource ??= rowsBySourceMessage(previous);\n for (const source of getExternalStoreMessages(message)) {\n const row = previousBySource.get(source);\n if (row !== undefined) return row;\n }\n previousById ??= new Map(previous.map((row) => [row.id, row]));\n return previousById.get(message.id);\n };\n return converted.map((message, index) => {\n if (message === previousConverted[index]) return previous[index] ?? message;\n // An unchanged row that moved (a message landed above it) keeps its row too.\n previousByConverted ??= new Map(\n previousConverted.map((row, rowIndex) => [row, previous[rowIndex] ?? row])\n );\n const unchanged = previousByConverted.get(message);\n if (unchanged !== undefined) return unchanged;\n const before = continuedRow(message, index);\n const row =\n before?.role === 'assistant' && message.role === 'assistant'\n ? withUnchangedParts({ before, message })\n : message;\n const key = before === undefined ? message.id : deepAgentRowKey(before);\n if (key === message.id) return row;\n // A key another row of this pass already renders under stays with that row.\n rowIds ??= new Set(converted.map((candidate) => candidate.id));\n if (rowIds.has(key) || continuedKeys.has(key)) return row;\n continuedKeys.add(key);\n // A copy: the conversion caches its own rows and serves them again.\n const keyed: ThreadMessage = { ...row };\n Reflect.set(keyed, ROW_KEY, key);\n return keyed;\n });\n}\n\n/** Each source message's row, for finding the row a re-converted message continues. */\nfunction rowsBySourceMessage(rows: readonly ThreadMessage[]): Map<unknown, ThreadMessage> {\n const bySource = new Map<unknown, ThreadMessage>();\n for (const row of rows) {\n for (const source of getExternalStoreMessages(row)) {\n if (!bySource.has(source)) bySource.set(source, row);\n }\n }\n return bySource;\n}\n\n/**\n * `message` with `before`'s part object wherever a part is unchanged. Parts\n * are paired by what they render, not by position: a tool call by its id, any\n * other part by the converted source message it came from (and its place\n * among that message's parts). A page of older steps that folds in at the\n * head of the turn then keeps every part that was already there.\n */\nfunction withUnchangedParts({\n before,\n message,\n}: {\n before: ThreadAssistantMessage;\n message: ThreadAssistantMessage;\n}): ThreadAssistantMessage {\n const toolCalls = new Map<string, ThreadAssistantMessagePart>();\n const bySource = new Map<unknown, ThreadAssistantMessagePart[]>();\n for (const part of before.content) {\n if (part.type === 'tool-call') {\n toolCalls.set(part.toolCallId, part);\n continue;\n }\n const source: unknown = getExternalStoreMessages(part)[0];\n const parts = bySource.get(source);\n if (parts === undefined) bySource.set(source, [part]);\n else parts.push(part);\n }\n const placesBySource = new Map<unknown, number>();\n let kept = 0;\n const content = message.content.map((part) => {\n let candidate: ThreadAssistantMessagePart | undefined;\n if (part.type === 'tool-call') {\n candidate = toolCalls.get(part.toolCallId);\n } else {\n const source: unknown = getExternalStoreMessages(part)[0];\n const place = placesBySource.get(source) ?? 0;\n placesBySource.set(source, place + 1);\n candidate = bySource.get(source)?.[place];\n }\n if (candidate === undefined || !sameMessagePart(candidate, part)) return part;\n kept += 1;\n return candidate;\n });\n return kept === 0 ? message : { ...message, content };\n}\n\n/** A conversion cache for one attached thread (see {@link DeepAgentMessageConversionCache}). */\nexport function createDeepAgentMessageConversionCache(): DeepAgentMessageConversionCache {\n return new DeepAgentMessageConversionCache();\n}\n\nfunction isSameMessageList(a: readonly ThreadMessage[], b: readonly ThreadMessage[]): boolean {\n return a.length === b.length && a.every((message, index) => message === b[index]);\n}\n\nconst wirePartsToOptimisticParts = (\n parts: StatewireThread.UserMessage['parts']\n): OptimisticContentPart[] =>\n parts.flatMap((part): OptimisticContentPart[] => {\n if (part.type === 'text') return [part];\n // Image attachments travel as `file` parts on the run/* commands; map\n // them back to `image` parts so the optimistic bubble renders them.\n if (part.mediaType.startsWith('image/')) return [{ type: 'image', image: part.url }];\n return [];\n });\n\n/**\n * `metadata.custom` flag marking a bubble that is a projection of a run-lane\n * entry — a message the server holds and has NOT dispatched yet.\n *\n * The lane is server-owned and replicated to every client on the thread, so\n * an item queued on one surface projects onto all of them. Surfaces without a\n * queue panel must therefore be able to tell a queued projection apart from a\n * submitted turn, or a message another device queued renders as if this device\n * had already sent it.\n *\n * `convertLangChainMessages` exposes `additional_kwargs.metadata` (and nothing\n * else) as the thread message's `metadata.custom`.\n */\nexport const ATHENA_QUEUED_LANE_KEY = 'athena_queued_lane';\n\n/**\n * Whether a thread message's `metadata.custom` marks it as an undispatched\n * lane projection. Returns a primitive, so it is safe to use directly as a\n * `useAuiState` selector.\n */\nexport function isQueuedLaneMessage(custom: Record<string, unknown> | undefined): boolean {\n return custom?.[ATHENA_QUEUED_LANE_KEY] === true;\n}\n\ninterface LaneEntryMessageCacheEntry {\n selfAuthor: DeepAgentMessageAuthor | null;\n message: LangChainMessage;\n}\n\n/**\n * Per-entry projections, one map per lane state. Lane entries are wire\n * objects folded copy-on-write (like messages, see {@link liftedMessageCache}),\n * so an unchanged entry projects to the IDENTICAL message on every pass and its\n * bubble keeps its converted identity while it waits in a lane or for its\n * dispatch to land. An entry this client's own unacknowledged command still\n * shapes is rebuilt each time statewire re-applies that optimistic fold, and\n * re-projects until the server acknowledges it.\n */\nconst queuedLaneMessageCache = new WeakMap<\n StatewireThread.RunsQueueEntry,\n LaneEntryMessageCacheEntry\n>();\nconst dispatchedLaneMessageCache = new WeakMap<\n StatewireThread.RunsQueueEntry,\n LaneEntryMessageCacheEntry\n>();\n\n/**\n * Project one run-lane entry into the optimistic human message shape.\n *\n * `queued` marks entries still waiting in a lane; a dispatched entry becomes an\n * ordinary submitted turn and carries no marker. Either way the bubble carries\n * its author (see {@link laneEntryAuthor}) under the same `metadata.custom`\n * key the backend stamps on the persisted turn, so the optimistic and\n * authoritative copies of one send render identically — and a second poster's\n * avatar shows on their own send without waiting for the acknowledgment.\n */\nconst laneEntryMessage = ({\n entry,\n queued,\n selfAuthor,\n}: {\n entry: StatewireThread.RunsQueueEntry;\n queued: boolean;\n selfAuthor: DeepAgentMessageAuthor | null;\n}): LangChainMessage => {\n const cache = queued ? queuedLaneMessageCache : dispatchedLaneMessageCache;\n const cached = cache.get(entry);\n if (cached !== undefined && cached.selfAuthor === selfAuthor) return cached.message;\n const message = buildLaneEntryMessage({ entry, queued, selfAuthor });\n cache.set(entry, { selfAuthor, message });\n return message;\n};\n\nconst buildLaneEntryMessage = ({\n entry,\n queued,\n selfAuthor,\n}: {\n entry: StatewireThread.RunsQueueEntry;\n queued: boolean;\n selfAuthor: DeepAgentMessageAuthor | null;\n}): LangChainMessage => {\n const author = laneEntryAuthor(entry, selfAuthor);\n // The draft a composer send came from, so the optimistic bubble renders the\n // typed text the way its persisted copy will (see `composer-markdown.ts`).\n const composerMarkdown: unknown = (entry.metadata as Record<string, unknown> | undefined)?.[\n DEEP_AGENT_COMPOSER_MARKDOWN_KEY\n ];\n const metadata: Record<string, unknown> = {\n ...(queued ? { [ATHENA_QUEUED_LANE_KEY]: true } : {}),\n ...(author ? { [ATHENA_MESSAGE_AUTHOR_KEY]: author } : {}),\n ...(typeof composerMarkdown === 'string'\n ? { [DEEP_AGENT_COMPOSER_MARKDOWN_KEY]: composerMarkdown }\n : {}),\n };\n return {\n id: entry.id,\n type: 'human',\n content: buildOptimisticHumanContent(wirePartsToOptimisticParts(entry.parts)),\n ...(Object.keys(metadata).length > 0 ? { additional_kwargs: { metadata } } : {}),\n };\n};\n\nexport interface DeepAgentMaterializeOptions {\n /** The viewer, stamped onto this client's own not-yet-acknowledged sends. */\n selfAuthor?: DeepAgentMessageAuthor | null;\n}\n\n/**\n * Materialize fold for the statewire path: makes the server's dispatch record\n * concrete in the LangGraph state itself, so direct state reads see dispatched\n * messages and the lib's post-converter dispatch merge stays off.\n */\nexport const createDeepAgentMaterialize =\n ({ selfAuthor = null }: DeepAgentMaterializeOptions = {}) =>\n (draft: DeepAgentStreamValues): void => {\n runsMaterialize(draft, {\n append: (message) => {\n (draft.messages ??= []).push(\n laneEntryMessage({ entry: message, queued: false, selfAuthor })\n );\n },\n rollback: (to) => {\n if (to === null) {\n draft.messages = [];\n return;\n }\n const messages = draft.messages ?? [];\n const keepIndex = messages.findIndex((message) => message.id === to);\n // Unresolved rollback anchor: fail OPEN with the full history (mirrors the edit fold).\n if (keepIndex !== -1) messages.splice(keepIndex + 1);\n },\n });\n };\n\n/** The materialize fold without a viewer identity (surfaces that pass none). */\nexport const deepAgentMaterialize = createDeepAgentMaterialize();\n\n/**\n * Project run lanes into human messages for the converter tail, so a queued or\n * steered item stays visible below the pending-assistant placeholder until its\n * dispatch. Surfaces with a queue panel project only the steer lane\n * (`'steer-only'`); surfaces without one project both lanes (`'both'`).\n *\n * Every projected entry carries {@link ATHENA_QUEUED_LANE_KEY} so a surface\n * without a queue panel can render it as queued rather than as a submitted\n * turn.\n */\nexport const laneTailMessages = (\n state: unknown,\n laneProjection: DeepAgentLaneProjection = 'both',\n selfAuthor: DeepAgentMessageAuthor | null = null\n): LangChainMessage[] => {\n const run = (state as DeepAgentStreamValues | null)?.runs?.[0];\n if (!run) return [];\n const entries =\n laneProjection === 'steer-only' ? run.steerQueue : [...run.queue, ...run.steerQueue];\n return entries.map((entry) => laneEntryMessage({ entry, queued: true, selfAuthor }));\n};\n\n/** Stable id for the derived running-assistant placeholder. */\nexport const PENDING_ASSISTANT_MESSAGE_ID = '__athena_deep_agent_pending_assistant__';\n\n/**\n * The placeholder itself — empty-array content plus an explicit running\n * status: the thinking shimmer keys on `status running && zero content parts`,\n * and the explicit status keeps it pulsing when lane entries render below (the\n * last-message auto status would demote a mid-list placeholder to an empty\n * complete bubble). One shared, frozen object, so the converted \"Thinking…\" row\n * keeps its identity across every pass until the real reply replaces it.\n */\nconst PENDING_ASSISTANT_MESSAGE: LangChainMessage = Object.freeze({\n type: 'ai',\n content: [],\n id: PENDING_ASSISTANT_MESSAGE_ID,\n status: Object.freeze({ type: 'running' }),\n} satisfies LangChainMessage);\n\n/**\n * Append an empty assistant turn while a run is in flight and the visible\n * history does not already end in one, so the thread shows its \"Thinking…\"\n * status line from the moment a message is submitted.\n *\n * Mirrors `hasUpcomingMessage` in assistant-ui's legacy external-store runtime,\n * which synthesized this placeholder itself. `StatewireThread` renders the\n * converter's message list verbatim, so the placeholder has to come from here —\n * derived from the replicated run status on every render (never written into\n * transport state) so it cannot outlive the run, and carrying a stable id so\n * the streaming bubble's identity does not churn when the real assistant\n * message arrives.\n *\n * `tool` messages convert into assistant turns too, so a mid-run tool result\n * must not produce a second placeholder row.\n */\nexport function withPendingAssistantMessage(\n messages: LangChainMessage[],\n isRunning: boolean\n): LangChainMessage[] {\n if (!isRunning) return messages;\n const lastType = messages.at(-1)?.type;\n if (lastType === 'ai' || lastType === 'tool') return messages;\n // Never persisted, so it cannot outlive the run.\n return [...messages, PENDING_ASSISTANT_MESSAGE];\n}\n\n/** Stable id for the synthetic assistant turn that carries a failure when the run produced none. */\nconst RUN_ERROR_SYNTHETIC_AI_ID = '__athena_deep_agent_run_error__';\n\n/**\n * Surface a run failure the base-correct way: stamp `status: { type:'incomplete',\n * reason:'error', error }` onto the assistant turn so `<Thread/>` renders it via\n * `ErrorPrimitive`. This is the core runtime's model (see `useLanggraphRuntime`\n * `onError`) — NOT a fabricated `⚠️ The run failed` assistant text message, and\n * NOT a magic-string contract shared with the agora backend.\n *\n * Stamps a trailing assistant message; if the visible history does not already\n * end with an assistant turn, appends a synthetic empty assistant turn with a\n * STABLE id so it never churns across renders. A `null` error is a no-op. The\n * shipped `convertLangChainMessages` converter passes `message.status` through.\n */\nexport function applyRunErrorStatus(\n messages: LangChainMessage[],\n errorMessage: string | null\n): LangChainMessage[] {\n if (errorMessage === null) return messages;\n const status = { type: 'incomplete', reason: 'error', error: errorMessage } as const;\n const lastMessage = messages.at(-1);\n if (lastMessage?.type !== 'ai') {\n return [\n ...messages,\n { type: 'ai', content: '', id: RUN_ERROR_SYNTHETIC_AI_ID, status } satisfies LangChainMessage,\n ];\n }\n return [...messages.slice(0, -1), { ...lastMessage, status }];\n}\n\n/**\n * `additional_kwargs` flag the backend stamps on run-lifecycle marker messages\n * (agora `athena_deep_agent/run_markers.py`) — e.g. the \"⏹️ Run stopped by\n * user.\" message persisted when a run is cancelled.\n */\nexport const ATHENA_RUN_MARKER_KEY = 'athena_run_marker';\n\n/** The {@link ATHENA_RUN_MARKER_KEY} value for a user-cancelled run. */\nexport const ATHENA_RUN_MARKER_CANCELLED = 'cancelled';\n\n/**\n * `additional_kwargs` key carrying the stop source behind a cancellation\n * marker (agora `stop_signals.py`: `user_stop`, `send_now`, `transport_cancel`,\n * `unattributed`).\n */\nexport const ATHENA_RUN_MARKER_SOURCE_KEY = 'athena_run_marker_source';\n\n/** The stop source for a \"Send now\" promotion pre-empting the live run. */\nexport const ATHENA_STOP_SOURCE_SEND_NOW = 'send_now';\n\n/**\n * The stop source for a spoken follow-up that redirected a voice-delegated\n * run through the steer lane: the user spoke, they never pressed Stop, so it\n * renders as a redirect rather than as \"Conversation stopped\".\n */\nexport const ATHENA_STOP_SOURCE_VOICE_STEER = 'voice_steer';\n\n/** The stop source for a pod-drain pause (server update), not a user stop. */\nexport const ATHENA_STOP_SOURCE_POD_DRAIN = 'pod_drain';\n\n/**\n * The {@link ATHENA_RUN_MARKER_SOURCE_KEY} value for a run whose hosting\n * instance closed under it (a server update that reached its eviction\n * deadline mid-step, or a placement lost to a lease lapse). Same family as a\n * pod drain: nobody stopped the run, the backend resumes it automatically.\n */\nexport const ATHENA_STOP_SOURCE_INSTANCE_CLOSED = 'instance_closed';\n\n/**\n * Whether a cancellation marker's source names the infrastructure — a pod\n * drain or a closed instance — rather than a person or a client action. These\n * endings read as a pause while the server resumes the run.\n */\nexport function isServerUpdateStopSource(source: string | undefined): boolean {\n return source === ATHENA_STOP_SOURCE_POD_DRAIN || source === ATHENA_STOP_SOURCE_INSTANCE_CLOSED;\n}\n\n/**\n * The {@link ATHENA_RUN_MARKER_KEY} value for a failed run (graph error,\n * including the `GraphRecursionError` \"tool call limit was reached\" case).\n * The marker message's text content carries the user-facing failure copy.\n */\nexport const ATHENA_RUN_MARKER_FAILED = 'failed';\n\n/**\n * `additional_kwargs` key carrying the canonical reason a run ended (agora\n * `athena_deep_agent/termination.py`): `user_stop`, `recursion_limit`,\n * `duplicate_call_guard`, `step_budget`, `ended_after_tools`, `model_refusal`,\n * `completed`, …\n * Stamped on run-lifecycle markers and on handoff messages.\n */\nexport const ATHENA_TERMINATION_REASON_KEY = 'athena_termination_reason';\n\n/**\n * `additional_kwargs` flag on the closing message the runtime's **handoff\n * turn** wrote (one tools-disabled model call made when a guard or the step\n * budget ends the run). The message text is the agent's closing summary; the\n * flag lets clients frame it as a runtime ending rather than a normal reply.\n */\nexport const ATHENA_HANDOFF_KEY = 'athena_handoff';\n\n/**\n * Read a run-lifecycle marker out of a thread message's **bound source\n * messages**, bypassing the converter's metadata join entirely.\n *\n * Why this exists: assistant-ui chunks consecutive assistant/tool messages\n * into ONE `ThreadMessage`, and the upstream join copies `metadata.custom`\n * only from the FIRST assistant message of the chunk\n * (`external-message-converter.ts`: the merge sits inside\n * `if (assistantMessage.content.length === 0)`). A failure marker appended\n * after the assistant's own turn is therefore never the first message in its\n * chunk, so `message.metadata.custom.athena_run_marker` is silently dropped\n * and the whole-message gate can't fire.\n *\n * `getExternalStoreMessages` returns the raw LangChain messages bound to the\n * joined thread message, so the marker is found wherever it sits in the chunk.\n * Returns the marker value plus its text content (the user-facing copy).\n */\nexport interface RunMarkerInfo {\n marker: string;\n /** The stop source stamped by the backend, when the marker carries one. */\n source: string | undefined;\n /** The marker message's text — the user-facing copy. */\n text: string | undefined;\n /**\n * True when the marker is the ONLY source message behind this thread message,\n * i.e. it owns the whole row (a cancelled run drops its partial turn, so its\n * marker stands alone).\n *\n * False when the chunk also holds the assistant's own work. Replacing the row\n * in that case would hide completed prose and tool cards — the marker must be\n * styled in place instead.\n */\n isSoleSourceMessage: boolean;\n}\n\nexport function readRunMarkerFromSourceMessages(\n message: Parameters<typeof getExternalStoreMessages>[0] & {\n metadata?: { custom?: Record<string, unknown> | undefined } | undefined;\n content?: unknown;\n }\n): RunMarkerInfo | undefined {\n const sources = getExternalStoreMessages<LangChainMessage>(message);\n for (const source of sources) {\n if (source?.type !== 'ai') continue;\n const kwargs = source.additional_kwargs as Record<string, unknown> | undefined;\n const marker = kwargs?.[ATHENA_RUN_MARKER_KEY];\n if (typeof marker !== 'string') continue;\n const markerSource = kwargs?.[ATHENA_RUN_MARKER_SOURCE_KEY];\n return {\n marker,\n source: typeof markerSource === 'string' ? markerSource : undefined,\n text: typeof source.content === 'string' ? source.content : undefined,\n isSoleSourceMessage: sources.length === 1,\n };\n }\n // Fallback for surfaces whose messages carry no bound source messages (or a\n // converter that already merged the flag): read the joined metadata. Without\n // sources to count, a single text part is the best available \"marker owns the\n // row\" signal.\n const joined = message.metadata?.custom?.[ATHENA_RUN_MARKER_KEY];\n if (typeof joined !== 'string') return undefined;\n const joinedSource = message.metadata?.custom?.[ATHENA_RUN_MARKER_SOURCE_KEY];\n const parts = message.content;\n return {\n marker: joined,\n source: typeof joinedSource === 'string' ? joinedSource : undefined,\n text: undefined,\n isSoleSourceMessage: Array.isArray(parts) ? parts.length <= 1 : true,\n };\n}\n\n/**\n * The marker value when the marker is the SOLE source message behind a thread\n * message (it owns the whole row), else `undefined`.\n *\n * Returns a primitive so it is safe to use directly as a `useAuiState`\n * selector: `readRunMarkerFromSourceMessages` builds a fresh object on every\n * call, and selector snapshots are compared with `Object.is` — returning that\n * object from a selector makes `getSnapshot` unstable and loops the render.\n */\nexport function readSoleRunMarker(\n message: Parameters<typeof readRunMarkerFromSourceMessages>[0]\n): string | undefined {\n const found = readRunMarkerFromSourceMessages(message);\n return found?.isSoleSourceMessage ? found.marker : undefined;\n}\n\n/**\n * Whether a run marker renders nothing: a `send_now` promotion cancels the\n * live run as plumbing, not as a user-visible stop, so its cancellation\n * marker stays in the data for provenance but paints no divider.\n */\nexport function isSilentRunMarker(found: RunMarkerInfo): boolean {\n return (\n found.marker === ATHENA_RUN_MARKER_CANCELLED && found.source === ATHENA_STOP_SOURCE_SEND_NOW\n );\n}\n\n/**\n * Whether a cancellation marker records a server-update pause — a cooperative\n * pod drain, or the hosting instance closing under the run — rather than a\n * stop the user asked for. Rendered with distinct \"paused by a server update\"\n * copy instead of the \"Conversation stopped\" pill; the backend resumes the run.\n */\nexport function isDrainRunMarker(found: RunMarkerInfo): boolean {\n return found.marker === ATHENA_RUN_MARKER_CANCELLED && isServerUpdateStopSource(found.source);\n}\n\n/**\n * Surface the backend's top-level `additional_kwargs.athena_run_marker` flag\n * where the shipped converter can see it.\n *\n * `convertLangChainMessages` exposes ONLY `additional_kwargs.metadata` as the\n * thread message's `metadata.custom`; every other `additional_kwargs` key is\n * dropped. Marker messages persisted before the backend mirrored the flag into\n * `metadata` carry it top-level only, so this lift keeps those threads styling\n * correctly. Non-marker messages pass through with their identity unchanged,\n * and already-mirrored markers are left as-is (idempotent).\n */\nexport function liftRunMarkerIntoMetadata(message: LangChainMessage): LangChainMessage {\n if (message.type !== 'ai') return message;\n const kwargs = message.additional_kwargs as Record<string, unknown> | undefined;\n const marker = kwargs?.[ATHENA_RUN_MARKER_KEY];\n if (typeof marker !== 'string') return message;\n const existingMetadata = kwargs?.metadata;\n const metadata =\n typeof existingMetadata === 'object' && existingMetadata !== null\n ? (existingMetadata as Record<string, unknown>)\n : {};\n if (metadata[ATHENA_RUN_MARKER_KEY] === marker) return message;\n return {\n ...message,\n additional_kwargs: {\n ...kwargs,\n metadata: { ...metadata, [ATHENA_RUN_MARKER_KEY]: marker },\n } as (typeof message)['additional_kwargs'],\n };\n}\n\n/**\n * Mirror the termination reason and handoff flag into the converter's metadata\n * channel. The backend dual-writes both (top-level + `metadata`), so this lift\n * is the back-compat path for messages persisted before the mirror existed and\n * for any emitter that only stamps the top-level key. Idempotent; identity for\n * messages without the keys.\n */\nexport function liftTerminationIntoMetadata(message: LangChainMessage): LangChainMessage {\n if (message.type !== 'ai') return message;\n const kwargs = message.additional_kwargs as Record<string, unknown> | undefined;\n const reason = kwargs?.[ATHENA_TERMINATION_REASON_KEY];\n const handoff = kwargs?.[ATHENA_HANDOFF_KEY];\n const hasReason = typeof reason === 'string';\n const hasHandoff = handoff === true;\n if (!hasReason && !hasHandoff) return message;\n const existingMetadata = kwargs?.metadata;\n const metadata =\n typeof existingMetadata === 'object' && existingMetadata !== null\n ? (existingMetadata as Record<string, unknown>)\n : {};\n const reasonMirrored = !hasReason || metadata[ATHENA_TERMINATION_REASON_KEY] === reason;\n const handoffMirrored = !hasHandoff || metadata[ATHENA_HANDOFF_KEY] === true;\n if (reasonMirrored && handoffMirrored) return message;\n return {\n ...message,\n additional_kwargs: {\n ...kwargs,\n metadata: {\n ...metadata,\n ...(hasReason ? { [ATHENA_TERMINATION_REASON_KEY]: reason } : {}),\n ...(hasHandoff ? { [ATHENA_HANDOFF_KEY]: true } : {}),\n },\n } as (typeof message)['additional_kwargs'],\n };\n}\n\n/**\n * `additional_kwargs` key (and `metadata` mirror) carrying a failure marker's\n * structured error records (agora `athena_deep_agent/run_markers.py`\n * `failure_error_records`): `[{ error, provider?, message? }]`, where `error`\n * is the client code a surface branches on — `context_length_exceeded`,\n * `transient_api_error` (with `provider: 'azure_foundry' |\n * 'external_model_provider'`), `content_filter`, `request_too_large`, … — the\n * same shape the legacy agent node emitted.\n */\nexport const ATHENA_ERRORS_KEY = 'errors';\n\n/**\n * Mirror a failure marker's structured `errors` records into the converter's\n * metadata channel. The backend dual-writes them (top-level + `metadata`), so\n * this lift is the back-compat path for messages that carry only the top-level\n * key (an emitter that never mirrored, or a record persisted before the mirror\n * existed). Records already present in the metadata channel win; no-ops are\n * identity.\n */\nexport function liftErrorsIntoMetadata(message: LangChainMessage): LangChainMessage {\n if (message.type !== 'ai') return message;\n const kwargs = message.additional_kwargs as Record<string, unknown> | undefined;\n const errors = kwargs?.[ATHENA_ERRORS_KEY];\n if (!Array.isArray(errors) || errors.length === 0) return message;\n const existingMetadata = kwargs?.metadata;\n const metadata =\n typeof existingMetadata === 'object' && existingMetadata !== null\n ? (existingMetadata as Record<string, unknown>)\n : {};\n if (Array.isArray(metadata[ATHENA_ERRORS_KEY])) return message;\n return {\n ...message,\n additional_kwargs: {\n ...kwargs,\n metadata: { ...metadata, [ATHENA_ERRORS_KEY]: errors },\n } as (typeof message)['additional_kwargs'],\n };\n}\n\n/**\n * Read a failure's structured `errors` records out of a thread message's\n * **bound source messages**, bypassing the converter's metadata join.\n *\n * Same reason as {@link readRunMarkerFromSourceMessages}: assistant-ui chunks\n * consecutive assistant/tool messages into ONE `ThreadMessage` and copies\n * `metadata.custom` only from the FIRST assistant message of the chunk. The\n * failure marker that carries the records is appended after the assistant's\n * own turn, so `message.metadata.custom.errors` is silently dropped whenever\n * the run produced anything before failing. The bound sources are walked from\n * the tail (the terminal failure wins); the joined metadata is the fallback\n * for surfaces whose messages carry no bound sources. Returns the raw records\n * (callers validate the shape) or `undefined`.\n */\nexport function readMessageErrorsFromSourceMessages(\n message: Parameters<typeof getExternalStoreMessages>[0] & {\n metadata?: { custom?: Record<string, unknown> | undefined } | undefined;\n }\n): unknown[] | undefined {\n const sources = getExternalStoreMessages<LangChainMessage>(message);\n for (let index = sources.length - 1; index >= 0; index -= 1) {\n const source = sources[index];\n if (source?.type !== 'ai') continue;\n const kwargs = source.additional_kwargs as Record<string, unknown> | undefined;\n const metadata = kwargs?.metadata;\n const mirrored =\n typeof metadata === 'object' && metadata !== null\n ? (metadata as Record<string, unknown>)[ATHENA_ERRORS_KEY]\n : undefined;\n const errors = Array.isArray(mirrored) ? mirrored : kwargs?.[ATHENA_ERRORS_KEY];\n if (Array.isArray(errors) && errors.length > 0) return errors;\n }\n const joined = message.metadata?.custom?.[ATHENA_ERRORS_KEY];\n return Array.isArray(joined) && joined.length > 0 ? joined : undefined;\n}\n\n/**\n * Mirror the producing model into the converter's metadata channel. Wire AI\n * messages are full LangChain dumps whose `response_metadata` reports the model\n * that generated them (`model_name` / `model`), but the shipped converter maps\n * only `additional_kwargs.metadata` into `metadata.custom` — so without this\n * lift a surface can only show the CURRENT run config's model, mislabeling\n * earlier messages after a mid-thread model switch. A model already present in\n * the metadata channel (backend-stamped provenance) wins; no-ops are identity.\n */\nexport function liftModelIntoMetadata(message: LangChainMessage): LangChainMessage {\n if (message.type !== 'ai') return message;\n const responseMetadata = (\n message as { response_metadata?: { model_name?: unknown; model?: unknown } }\n ).response_metadata;\n let model: string | undefined;\n if (typeof responseMetadata?.model_name === 'string' && responseMetadata.model_name) {\n model = responseMetadata.model_name;\n } else if (typeof responseMetadata?.model === 'string' && responseMetadata.model) {\n model = responseMetadata.model;\n }\n if (!model) return message;\n const kwargs = message.additional_kwargs as Record<string, unknown> | undefined;\n const existingMetadata = kwargs?.metadata;\n const metadata =\n typeof existingMetadata === 'object' && existingMetadata !== null\n ? (existingMetadata as Record<string, unknown>)\n : {};\n if (typeof metadata.model === 'string' && metadata.model) return message;\n return {\n ...message,\n additional_kwargs: {\n ...kwargs,\n metadata: { ...metadata, model },\n } as (typeof message)['additional_kwargs'],\n };\n}\n\n/**\n * Mirror a per-message conversation-stats snapshot into the converter's\n * metadata channel. Backends stamp the snapshot at the legacy location —\n * top-level `additional_kwargs.conversation_stats` (the deep-agent stats\n * middleware and the legacy agent node both write it there) — but the shipped\n * converter maps only `additional_kwargs.metadata` into `metadata.custom`, so\n * without this lift the model badge can never show a message's OWN context and\n * falls back to thread-level live numbers. A snapshot already present in the\n * metadata channel wins; no-ops are identity.\n */\nexport function liftConversationStatsIntoMetadata(message: LangChainMessage): LangChainMessage {\n if (message.type !== 'ai') return message;\n const kwargs = message.additional_kwargs as Record<string, unknown> | undefined;\n const stats = kwargs?.conversation_stats;\n if (typeof stats !== 'object' || stats === null) return message;\n const existingMetadata = kwargs?.metadata;\n const metadata =\n typeof existingMetadata === 'object' && existingMetadata !== null\n ? (existingMetadata as Record<string, unknown>)\n : {};\n if (typeof metadata.conversation_stats === 'object' && metadata.conversation_stats !== null) {\n return message;\n }\n return {\n ...message,\n additional_kwargs: {\n ...kwargs,\n metadata: { ...metadata, conversation_stats: stats },\n } as (typeof message)['additional_kwargs'],\n };\n}\n\n/**\n * Mirror the compaction boundary flag into the converter's metadata channel.\n * A manual `/compact` persists its summary as a human message tagged with\n * top-level `additional_kwargs.compaction_start` (plus `_created_at` for the\n * divider timestamp) — the same location the legacy runtime used — but the\n * shipped converter maps only `additional_kwargs.metadata` into\n * `metadata.custom`, so without this lift the transcript's\n * \"Previous conversation summarized\" divider can never render. A flag already\n * present in the metadata channel wins; no-ops are identity.\n */\nexport function liftCompactionBoundaryIntoMetadata(message: LangChainMessage): LangChainMessage {\n if (message.type !== 'human') return message;\n const kwargs = message.additional_kwargs as Record<string, unknown> | undefined;\n if (kwargs?.compaction_start !== true) return message;\n const existingMetadata = kwargs?.metadata;\n const metadata =\n typeof existingMetadata === 'object' && existingMetadata !== null\n ? (existingMetadata as Record<string, unknown>)\n : {};\n if (metadata.compaction_start === true) return message;\n const createdAt = kwargs?._created_at;\n return {\n ...message,\n additional_kwargs: {\n ...kwargs,\n metadata: {\n ...metadata,\n compaction_start: true,\n ...(typeof createdAt === 'string' ? { _created_at: createdAt } : {}),\n },\n } as (typeof message)['additional_kwargs'],\n };\n}\n\n/**\n * Mirror the handoff summary flag into the converter's metadata channel.\n * Handoff summaries are persisted as human messages tagged with top-level\n * `additional_kwargs.handoff_summary` (plus `_created_at`) — the same location\n * the backend uses for message metadata — but the shipped converter maps only\n * `additional_kwargs.metadata` into `metadata.custom`, so without this lift\n * the summary would render as a normal user bubble. A flag already present in\n * the metadata channel wins; no-ops are identity.\n */\nexport function liftHandoffSummaryIntoMetadata(message: LangChainMessage): LangChainMessage {\n if (message.type !== 'human') return message;\n const kwargs = message.additional_kwargs as Record<string, unknown> | undefined;\n if (kwargs?.handoff_summary !== true) return message;\n const existingMetadata = kwargs?.metadata;\n const metadata =\n typeof existingMetadata === 'object' && existingMetadata !== null\n ? (existingMetadata as Record<string, unknown>)\n : {};\n if (metadata.handoff_summary === true) return message;\n const createdAt = kwargs?._created_at;\n return {\n ...message,\n additional_kwargs: {\n ...kwargs,\n metadata: {\n ...metadata,\n handoff_summary: true,\n ...(typeof createdAt === 'string' ? { _created_at: createdAt } : {}),\n },\n } as (typeof message)['additional_kwargs'],\n };\n}\n\n/**\n * Mirror an AOP run's provenance into the converter's metadata channel. The\n * backend stamps the kicking-off user message with top-level\n * `additional_kwargs.aop_source` (agora `events/helpers.py`\n * `_build_aop_source_metadata`), which the legacy converter surfaced as\n * `metadata.custom.aop_source` — where the \"AOP · <title>\" badge reads it. The\n * shipped `convertLangChainMessages` maps only `additional_kwargs.metadata`\n * into `metadata.custom`, so without this lift an AOP run's conversation never\n * shows which AOP asset kicked it off. Provenance already present in the\n * metadata channel wins; no-ops are identity.\n */\nexport function liftAopSourceIntoMetadata(message: LangChainMessage): LangChainMessage {\n if (message.type !== 'human') return message;\n const kwargs = message.additional_kwargs as Record<string, unknown> | undefined;\n const aopSource = kwargs?.aop_source;\n if (typeof aopSource !== 'object' || aopSource === null || Array.isArray(aopSource)) {\n return message;\n }\n const existingMetadata = kwargs?.metadata;\n const metadata =\n typeof existingMetadata === 'object' && existingMetadata !== null\n ? (existingMetadata as Record<string, unknown>)\n : {};\n if (typeof metadata.aop_source === 'object' && metadata.aop_source !== null) return message;\n return {\n ...message,\n additional_kwargs: {\n ...kwargs,\n metadata: { ...metadata, aop_source: aopSource },\n } as (typeof message)['additional_kwargs'],\n };\n}\n\nexport function liftBranchIntoMetadata(message: LangChainMessage): LangChainMessage {\n if (message.type !== 'human' && message.type !== 'ai') return message;\n const branch = (message as { branch?: unknown }).branch;\n if (typeof branch !== 'object' || branch === null || Array.isArray(branch)) return message;\n const kwargs = message.additional_kwargs as Record<string, unknown> | undefined;\n const existingMetadata = kwargs?.metadata;\n const metadata =\n typeof existingMetadata === 'object' && existingMetadata !== null\n ? (existingMetadata as Record<string, unknown>)\n : {};\n if (typeof metadata.branch === 'object' && metadata.branch !== null) return message;\n return {\n ...message,\n additional_kwargs: {\n ...kwargs,\n metadata: { ...metadata, branch },\n } as (typeof message)['additional_kwargs'],\n };\n}\n\n/**\n * `additional_kwargs` keys on a ToolMessage that are infrastructure rather than\n * user-set metadata. The filter below additionally skips every `_`-prefixed key.\n */\nconst TOOL_MESSAGE_INTERNAL_KWARGS: ReadonlySet<string> = new Set([\n 'reasoning',\n 'tool_outputs',\n 'hide_from_frontend',\n]);\n\n/**\n * Mirror a ToolMessage's user-set `additional_kwargs` into\n * `artifact._tool_message_metadata` — the location `useToolCallMetadata` reads\n * persisted per-tool-call metadata from (`email_sent_at`, draft edits,\n * `calendar_event_created_at`, …).\n *\n * The `setMessageMetadata` mutation persists those keys onto the ToolMessage's\n * `additional_kwargs` in the checkpoint, and the legacy converter lifted them\n * into the artifact. The shipped `convertLangChainMessages` forwards only\n * `artifact` and drops `additional_kwargs` for tool messages, so without this\n * lift the metadata survives in the checkpoint but never reaches a tool card\n * after a reload. Kwargs values win over same-key artifact entries (the kwargs\n * are the durable write target); messages with no user-set kwargs pass through\n * by identity.\n */\nexport function liftToolMessageMetadataIntoArtifact(message: LangChainMessage): LangChainMessage {\n if (message.type !== 'tool') return message;\n const kwargs = (message as { additional_kwargs?: Record<string, unknown> }).additional_kwargs;\n if (!kwargs) return message;\n const lifted: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(kwargs)) {\n if (key.startsWith('_') || TOOL_MESSAGE_INTERNAL_KWARGS.has(key)) continue;\n lifted[key] = value;\n }\n if (Object.keys(lifted).length === 0) return message;\n const artifact: unknown = message.artifact;\n const artifactRecord =\n typeof artifact === 'object' && artifact !== null && !Array.isArray(artifact)\n ? (artifact as Record<string, unknown>)\n : {};\n const existing = artifactRecord._tool_message_metadata;\n const existingRecord =\n typeof existing === 'object' && existing !== null && !Array.isArray(existing)\n ? (existing as Record<string, unknown>)\n : {};\n return {\n ...message,\n artifact: {\n ...artifactRecord,\n _tool_message_metadata: { ...existingRecord, ...lifted },\n },\n };\n}\n\n/**\n * Lift a windowed wire's tool-output truncation marker into the tool-call\n * part's `artifact` (`_athena_content_truncated: { chars, messageId }`).\n *\n * The host cuts long plain-text tool outputs on a windowed wire and stamps\n * `athena_content_truncated` on the wire message; the shipped converter joins\n * a ToolMessage into its assistant turn's tool-call part and keeps only\n * `artifact` and the result, so without this lift no tool card could tell the\n * output is cut nor which message to ask `history/tool_output` for. Messages\n * without the marker pass through by identity.\n */\nexport function liftTruncatedToolOutputIntoArtifact(message: LangChainMessage): LangChainMessage {\n if (message.type !== 'tool') return message;\n const marker = readTruncatedToolContent(message);\n if (marker === null || typeof message.id !== 'string') return message;\n const artifact: unknown = message.artifact;\n const artifactRecord =\n typeof artifact === 'object' && artifact !== null && !Array.isArray(artifact)\n ? (artifact as Record<string, unknown>)\n : {};\n return {\n ...message,\n artifact: {\n ...artifactRecord,\n [ATHENA_TRUNCATED_TOOL_OUTPUT_ARTIFACT_KEY]: { chars: marker.chars, messageId: message.id },\n },\n };\n}\n\n/**\n * A content list's bare-string entries as typed text parts.\n *\n * LangChain content is `string | (string | ContentBlock)[]`, and a model with\n * no tools bound streams exactly that mix: `langchain_anthropic` coerces text\n * deltas to plain strings when no tools are bound, yet a thinking block still\n * arrives as a list block, so the merged reply is `[\"\", {thinking}, \"text\"]`\n * (the side-question lane's bare model). The shipped converter maps only typed\n * blocks and drops the strings, leaving the reasoning with no answer. Empty\n * strings are dropped; messages with no string entries pass through by\n * identity.\n */\nexport function normalizeStringContentParts(message: LangChainMessage): LangChainMessage {\n const content: unknown = message.content;\n if (!Array.isArray(content) || !content.some((part) => typeof part === 'string')) {\n return message;\n }\n const parts = content.flatMap((part: unknown) => {\n if (typeof part !== 'string') return [part];\n return part.length > 0 ? [{ type: 'text', text: part }] : [];\n });\n return { ...message, content: parts } as LangChainMessage;\n}\n\n/**\n * Per-source cache for {@link substituteToolOutput}: a substituted copy is\n * reused while the wire message and the fetched output are both unchanged, so\n * the lift cache downstream keeps its identity contract.\n */\nconst substitutedToolOutputCache = new WeakMap<\n LangChainMessage,\n { content: unknown; substituted: LangChainMessage }\n>();\n\n/**\n * A cut tool message with its full output put back, when the store holds one\n * fetched for this very output (`history/tool_output` answered for the same\n * `chars` the wire's marker reports); the marker leaves with the cut.\n * Messages that are whole, whose output has not been fetched, or whose fetched\n * output belongs to a length the host has since replaced, pass through by\n * identity — the loader sees the mismatch and fetches again.\n */\nexport function substituteToolOutput(\n message: LangChainMessage,\n toolOutputs: DeepAgentToolOutputStore\n): LangChainMessage {\n if (message.type !== 'tool' || typeof message.id !== 'string') return message;\n const marker = readTruncatedToolContent(message);\n if (marker === null) return message;\n const entry = toolOutputs.entry(message.id);\n if (entry === undefined || entry.chars !== marker.chars) return message;\n const { content } = entry;\n const cached = substitutedToolOutputCache.get(message);\n if (cached !== undefined && cached.content === content) return cached.substituted;\n const { [DEEP_AGENT_TRUNCATED_CONTENT_KEY]: _marker, ...rest } = message as Record<\n string,\n unknown\n >;\n const substituted = { ...rest, content } as unknown as LangChainMessage;\n substitutedToolOutputCache.set(message, { content, substituted });\n return substituted;\n}\n\nconst hasHiddenFrontendFlag = (value: unknown): boolean => {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) {\n return false;\n }\n const record = value as Record<string, unknown>;\n if (record.hide_from_frontend === true) return true;\n return hasHiddenFrontendFlag(record.custom);\n};\n\n/**\n * Internal orchestration messages are useful in a trace export but must never\n * become conversation bubbles. Agora stores the flag in `additional_kwargs`;\n * live converter state can expose the same value under `metadata.custom`.\n */\nexport function isMessageHiddenFromFrontend(message: unknown): boolean {\n if (typeof message !== 'object' || message === null || Array.isArray(message)) {\n return false;\n }\n const record = message as Record<string, unknown>;\n return (\n hasHiddenFrontendFlag(record.additional_kwargs) || hasHiddenFrontendFlag(record.metadata)\n );\n}\n\n/**\n * The message `type`s `convertLangChainMessages` actually maps: its\n * `switch (message.type)` covers exactly these four and has no `default`, so it\n * returns `undefined` for anything else (a `RemoveMessage` `type: \"remove\"`\n * from summarization/compaction, a partial chunk, a future type).\n */\nconst CONVERTIBLE_MESSAGE_TYPES: ReadonlySet<string> = new Set(['system', 'human', 'ai', 'tool']);\n\n/**\n * Whether `convertLangChainMessages` can map this message at all.\n *\n * An unmappable entry converts to `undefined`, which assistant-ui's\n * `convertExternalMessages` wraps as `outputs: [undefined]` and then reads\n * `output.role` off — throwing `Cannot read property 'role' of undefined` and\n * taking the entire thread down instead of dropping one message.\n */\nexport function isConvertibleChatMessage(message: unknown): boolean {\n if (typeof message !== 'object' || message === null || Array.isArray(message)) {\n return false;\n }\n const type: unknown = (message as Record<string, unknown>).type;\n return typeof type === 'string' && CONVERTIBLE_MESSAGE_TYPES.has(type);\n}\n\n/**\n * Per-source cache for the lift pipeline in {@link sanitizeLangChainMessages}.\n *\n * The pipeline runs on EVERY state pass (once per streamed token), and the two\n * lifts that fire for essentially every message — {@link liftBranchIntoMetadata}\n * (the backend stamps `branch` on all indexed messages) and\n * {@link liftModelIntoMetadata} — allocate a fresh object each time they lift.\n * Without a cache, every message's identity churns on every token, defeating\n * all downstream per-source memoization (`getExternalStoreMessages`-keyed\n * reads, converter callback caches) and re-deriving the whole thread per token.\n *\n * Object identity is a sound cache key here: every statewire fold (op apply,\n * optimistic, materialize) runs through `statewire`'s copy-on-write\n * `recordMutations`, whose `finalize` returns the ORIGINAL object for\n * untouched nodes and a fresh copy for touched ones. A message is therefore\n * REPLACED — never mutated in place — whenever any of its fields change\n * (including the streaming tail's string-insert content growth), and an\n * unchanged message keeps its exact identity across passes. The corpus test\n * (`statewire-corpus.test.ts`) pins this identity contract against the real\n * client, so a statewire upgrade that switched to in-place mutation would fail\n * there rather than silently serving stale lifts from this cache.\n *\n * Module-level on purpose: keys are the wire message objects themselves, so\n * entries die with their state trees and threads cannot collide.\n */\nconst liftedMessageCache = new WeakMap<LangChainMessage, LangChainMessage>();\n\n/** The full lift chain for one message, memoized per source object. */\nfunction liftMessageIntoMetadataChannels(message: LangChainMessage): LangChainMessage {\n const cached = liftedMessageCache.get(message);\n if (cached !== undefined) return cached;\n const lifted = liftBranchIntoMetadata(\n liftTruncatedToolOutputIntoArtifact(\n liftToolMessageMetadataIntoArtifact(\n liftAopSourceIntoMetadata(\n liftHandoffSummaryIntoMetadata(\n liftCompactionBoundaryIntoMetadata(\n liftConversationStatsIntoMetadata(\n liftModelIntoMetadata(\n liftErrorsIntoMetadata(\n liftTerminationIntoMetadata(\n liftRunMarkerIntoMetadata(normalizeStringContentParts(message))\n )\n )\n )\n )\n )\n )\n )\n )\n )\n );\n liftedMessageCache.set(message, lifted);\n return lifted;\n}\n\n/**\n * The one message pipeline every deep-agent surface renders through:\n *\n * 1. drop messages the shipped converter cannot map (`RemoveMessage` etc. —\n * an unmappable entry would crash the whole thread) and internal\n * orchestration messages flagged hidden-from-frontend;\n * 1a. turn bare-string entries of a content list into typed text parts (see\n * {@link normalizeStringContentParts}) so a tool-less model's answer next\n * to its thinking block is not dropped by the converter;\n * 2. lift run-lifecycle markers into the converter's `metadata` channel\n * (see {@link liftRunMarkerIntoMetadata}) so the cancellation row styles as\n * a status divider instead of a plain assistant bubble, and the termination\n * reason + handoff flag alongside them (see\n * {@link liftTerminationIntoMetadata}) so every surface can render a\n * runtime ending (see `runtime-messages.ts`);\n * 3. lift each AI message's producing model into the same channel\n * (see {@link liftModelIntoMetadata}) so model badges reflect the model that\n * actually generated the message, not the currently configured one;\n * 4. lift each AI message's per-message conversation-stats snapshot into the\n * same channel (see {@link liftConversationStatsIntoMetadata}) so the model\n * badge's hover card shows that message's own context usage;\n * 5. lift the compaction boundary flag on `/compact` summary messages into the\n * same channel (see {@link liftCompactionBoundaryIntoMetadata}) so the\n * transcript renders its \"Previous conversation summarized\" divider;\n * 6. lift the handoff summary flag on carried-over context messages into the\n * same channel (see {@link liftHandoffSummaryIntoMetadata}) so the\n * transcript keeps the summary behind its context panel;\n * 7. lift an AOP run's provenance on its kicking-off user message into the\n * same channel (see {@link liftAopSourceIntoMetadata}) so the message\n * renders its \"AOP · <title>\" origin badge;\n * 8. lift each ToolMessage's user-set `additional_kwargs` into\n * `artifact._tool_message_metadata` (see\n * {@link liftToolMessageMetadataIntoArtifact}) so persisted per-tool-call\n * metadata reaches tool cards after a reload;\n * 9. lift a windowed wire's tool-output truncation marker into the tool-call\n * part's `artifact` (see {@link liftTruncatedToolOutputIntoArtifact}) so a\n * tool card can fetch the whole output — after first putting back any\n * output already fetched (see {@link substituteToolOutput});\n * 10. lift the host's per-message branch stamp into the same channel\n * (see {@link liftBranchIntoMetadata}) so the branch picker renders each\n * message's edit fan-out.\n *\n * Identity-stable per source: an unchanged source message maps to the\n * IDENTICAL lifted object across passes (see {@link liftedMessageCache}).\n */\nexport function sanitizeLangChainMessages(\n messages: readonly LangChainMessage[],\n { toolOutputs }: { toolOutputs?: DeepAgentToolOutputStore } = {}\n): LangChainMessage[] {\n return messages\n .filter((message) => isConvertibleChatMessage(message) && !isMessageHiddenFromFrontend(message))\n .map((message) =>\n liftMessageIntoMetadataChannels(\n toolOutputs ? substituteToolOutput(message, toolOutputs) : message\n )\n );\n}\n\n/** Type guard for the runtime state — an object carrying a `messages` array. */\nexport function isLangGraphState(value: unknown): value is LangGraphState {\n return (\n typeof value === 'object' &&\n value !== null &&\n 'messages' in value &&\n Array.isArray((value as LangGraphState).messages)\n );\n}\n\nexport interface ConvertDeepAgentStateOptions {\n laneProjection?: DeepAgentLaneProjection;\n /**\n * The viewer, as the backend would stamp them: the author of this client's\n * own not-yet-acknowledged lane entries (see {@link laneEntryAuthor}).\n */\n selfAuthor?: DeepAgentMessageAuthor | null;\n /**\n * Full tool outputs fetched back for a windowed wire's cut tool messages\n * (see {@link substituteToolOutput}); omitted on surfaces that never\n * declare a window.\n */\n toolOutputs?: DeepAgentToolOutputStore;\n /**\n * User turns this client took back ahead of the wire (see\n * {@link DeepAgentWithdrawnTurns}): omitted from the transcript, together\n * with the pending-assistant placeholder a withdrawn tail would earn.\n */\n withdrawnTurns?: DeepAgentWithdrawnTurns;\n /**\n * The attached thread's conversion memory (see\n * {@link createDeepAgentMessageConversionCache}): unchanged messages keep\n * their converted identity across passes. Without one every pass converts\n * the whole transcript from scratch.\n */\n conversionCache?: DeepAgentConversionMemory;\n}\n\n/**\n * Keep the live assistant turn running when lane entries render after it.\n *\n * assistant-ui derives an assistant message's status from its position: the\n * last message of a running thread is `running`, while an earlier one whose\n * tool call has no result yet reads as `requires-action` (its\n * `AUTO_STATUS_PENDING`). A steer-lane entry projected into the tail — a\n * Steer waiting for the run's next model call, a Send now waiting for the\n * cancel — therefore demoted the turn it follows, and the tool card showed\n * \"Waiting for you\" over a tool that was still executing. An explicit status\n * on the source wins over the derived one (`fromThreadMessageLike`), so while\n * the run is live and a lane tail follows, the last assistant turn keeps the\n * `running` status it would have been given were it still last. Trailing tool\n * messages merge into that turn, so the last `ai` message is the one to stamp.\n */\nfunction keepTailRunningAheadOfLanes(\n messages: LangChainMessage[],\n hasLaneTail: boolean\n): LangChainMessage[] {\n if (!hasLaneTail) return messages;\n for (let index = messages.length - 1; index >= 0; index -= 1) {\n const message = messages[index];\n if (message === undefined) continue;\n if (message.type === 'human' || message.type === 'system') return messages;\n if (message.type === 'ai') {\n if (message.status !== undefined) return messages;\n const stamped = [...messages];\n stamped[index] = runningStampOf(message);\n return stamped;\n }\n }\n return messages;\n}\n\n/**\n * The stamped copies, one per source message: the conversion cache keys on\n * source identity, so the same wire message must yield the same stamped\n * object across passes or every render would reconvert the live turn.\n */\ntype AssistantLangChainMessage = Extract<LangChainMessage, { type: 'ai' }>;\n\nconst runningStamps = new WeakMap<AssistantLangChainMessage, AssistantLangChainMessage>();\n\nfunction runningStampOf(message: AssistantLangChainMessage): AssistantLangChainMessage {\n const cached = runningStamps.get(message);\n if (cached !== undefined) return cached;\n const stamped: AssistantLangChainMessage = { ...message, status: { type: 'running' } };\n runningStamps.set(message, stamped);\n return stamped;\n}\n\n/**\n * Map server state → assistant-ui thread messages.\n *\n * `state.messages` is the authoritative LangChain history streamed by the\n * backend. The replicated run status (`runs[0].status`) drives the\n * pending-assistant placeholder and the running status. Lane entries render at\n * the tail, after the placeholder, while the run is live (the run is still\n * working the history above them); once the thread rests stopped/errored they\n * are omitted (surfaces with a queue panel list them there instead).\n * Consecutive spoken user turns collapse into one user message (see\n * {@link groupSpokenUserTurns}) before conversion.\n */\nexport function convertDeepAgentState(\n state: unknown,\n {\n laneProjection = 'both',\n selfAuthor = null,\n toolOutputs,\n withdrawnTurns,\n conversionCache,\n }: ConvertDeepAgentStateOptions = {}\n) {\n // A wire without a snapshot yet (pre-attach, replay boundary) converts as the\n // typed pre-stream default: an empty resting thread, never `undefined`.\n const values = readDeepAgentStreamValues(state);\n const status = values.runs?.[0]?.status;\n const isRunning = status === 'running';\n const isWithdrawn = (message: LangChainMessage): boolean =>\n withdrawnTurns !== undefined && message.id !== undefined && withdrawnTurns.isWithdrawn(message.id);\n const laneTail = (\n status === 'stopped' || status === 'error'\n ? []\n : laneTailMessages(values, laneProjection, selfAuthor)\n ).filter((message) => !isWithdrawn(message));\n const sanitized: LangChainMessage[] = isLangGraphState(values)\n ? sanitizeLangChainMessages(values.messages, { toolOutputs })\n : [];\n // A withdrawn tail is a turn nobody is answering: no placeholder for it.\n const tail: LangChainMessage | undefined = sanitized[sanitized.length - 1];\n const tailWithdrawn: boolean = tail !== undefined && isWithdrawn(tail);\n const stateMessages = groupSpokenUserTurns(sanitized.filter((message) => !isWithdrawn(message)));\n const sources = [\n ...keepTailRunningAheadOfLanes(\n withPendingAssistantMessage(stateMessages, isRunning && !tailWithdrawn),\n isRunning && laneTail.length > 0\n ),\n ...laneTail,\n ];\n return {\n messages: conversionCache\n ? conversionCache.convert(sources, isRunning)\n : messageConverter.toThreadMessages(sources, isRunning).map(markPreliminaryToolResults),\n isRunning,\n };\n}\n"],"names":["convertLangChainMessages","createMessageConverter","isRunningToolPlaceholderArtifact","createExternalMessageConversionCache","convertExternalMessages","getExternalStoreMessages","row","laneEntryAuthor","composerMarkdown","DEEP_AGENT_COMPOSER_MARKDOWN_KEY","ATHENA_MESSAGE_AUTHOR_KEY","buildOptimisticHumanContent","runsMaterialize","readTruncatedToolContent","ATHENA_TRUNCATED_TOOL_OUTPUT_ARTIFACT_KEY","DEEP_AGENT_TRUNCATED_CONTENT_KEY","readDeepAgentStreamValues","groupSpokenUserTurns"],"mappings":"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"}
|