@athenaintel/react 0.57.2 → 0.59.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +759 -9
- package/dist/agent-runtime/src/addressed-agents.cjs +16 -0
- package/dist/agent-runtime/src/addressed-agents.cjs.map +1 -0
- package/dist/agent-runtime/src/addressed-agents.d.ts +30 -0
- package/dist/agent-runtime/src/addressed-agents.js +16 -0
- package/dist/agent-runtime/src/addressed-agents.js.map +1 -0
- package/dist/agent-runtime/src/answer-label.cjs +4 -3
- package/dist/agent-runtime/src/answer-label.cjs.map +1 -1
- package/dist/agent-runtime/src/answer-label.d.ts +13 -6
- package/dist/agent-runtime/src/answer-label.js +4 -3
- package/dist/agent-runtime/src/answer-label.js.map +1 -1
- package/dist/agent-runtime/src/chat-outbox-attachments.cjs.map +1 -1
- package/dist/agent-runtime/src/chat-outbox-attachments.d.ts +1 -1
- package/dist/agent-runtime/src/chat-outbox-attachments.js.map +1 -1
- package/dist/agent-runtime/src/chat-outbox-entry.cjs +101 -0
- package/dist/agent-runtime/src/chat-outbox-entry.cjs.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-entry.d.ts +99 -0
- package/dist/agent-runtime/src/chat-outbox-entry.js +101 -0
- package/dist/agent-runtime/src/chat-outbox-entry.js.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-legacy.cjs +252 -0
- package/dist/agent-runtime/src/chat-outbox-legacy.cjs.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-legacy.d.ts +96 -0
- package/dist/agent-runtime/src/chat-outbox-legacy.js +252 -0
- package/dist/agent-runtime/src/chat-outbox-legacy.js.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-policy.cjs +30 -0
- package/dist/agent-runtime/src/chat-outbox-policy.cjs.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-policy.d.ts +42 -0
- package/dist/agent-runtime/src/chat-outbox-policy.js +30 -0
- package/dist/agent-runtime/src/chat-outbox-policy.js.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-storage.cjs +306 -0
- package/dist/agent-runtime/src/chat-outbox-storage.cjs.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-storage.d.ts +194 -0
- package/dist/agent-runtime/src/chat-outbox-storage.js +306 -0
- package/dist/agent-runtime/src/chat-outbox-storage.js.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-thread.cjs +21 -94
- package/dist/agent-runtime/src/chat-outbox-thread.cjs.map +1 -1
- package/dist/agent-runtime/src/chat-outbox-thread.d.ts +22 -18
- package/dist/agent-runtime/src/chat-outbox-thread.js +21 -94
- package/dist/agent-runtime/src/chat-outbox-thread.js.map +1 -1
- package/dist/agent-runtime/src/chat-outbox.cjs +492 -547
- package/dist/agent-runtime/src/chat-outbox.cjs.map +1 -1
- package/dist/agent-runtime/src/chat-outbox.d.ts +110 -142
- package/dist/agent-runtime/src/chat-outbox.js +492 -547
- package/dist/agent-runtime/src/chat-outbox.js.map +1 -1
- package/dist/agent-runtime/src/composer-markdown.cjs.map +1 -1
- package/dist/agent-runtime/src/composer-markdown.d.ts +1 -1
- package/dist/agent-runtime/src/composer-markdown.js.map +1 -1
- package/dist/agent-runtime/src/deep-agent-transport-recipe.cjs +3 -1
- package/dist/agent-runtime/src/deep-agent-transport-recipe.cjs.map +1 -1
- package/dist/agent-runtime/src/deep-agent-transport-recipe.d.ts +8 -1
- package/dist/agent-runtime/src/deep-agent-transport-recipe.js +3 -1
- package/dist/agent-runtime/src/deep-agent-transport-recipe.js.map +1 -1
- package/dist/agent-runtime/src/dictation-preferences.d.ts +356 -0
- package/dist/agent-runtime/src/dictation-record.d.ts +279 -0
- package/dist/agent-runtime/src/dictation-session.d.ts +106 -7
- package/dist/agent-runtime/src/dictation-snippets.d.ts +9 -0
- package/dist/agent-runtime/src/dictation-transfer.d.ts +142 -0
- package/dist/agent-runtime/src/edit-command.cjs.map +1 -1
- package/dist/agent-runtime/src/edit-command.d.ts +1 -1
- package/dist/agent-runtime/src/edit-command.js.map +1 -1
- package/dist/agent-runtime/src/errors.cjs +1 -0
- package/dist/agent-runtime/src/errors.cjs.map +1 -1
- package/dist/agent-runtime/src/errors.js +1 -0
- package/dist/agent-runtime/src/errors.js.map +1 -1
- package/dist/agent-runtime/src/generated/runconfig-contract.cjs +24 -0
- package/dist/agent-runtime/src/generated/runconfig-contract.cjs.map +1 -1
- package/dist/agent-runtime/src/generated/runconfig-contract.d.ts +3 -3
- package/dist/agent-runtime/src/generated/runconfig-contract.js +24 -0
- package/dist/agent-runtime/src/generated/runconfig-contract.js.map +1 -1
- package/dist/agent-runtime/src/index.d.ts +14 -8
- package/dist/agent-runtime/src/lane-follow.cjs +289 -0
- package/dist/agent-runtime/src/lane-follow.cjs.map +1 -0
- package/dist/agent-runtime/src/lane-follow.js +289 -0
- package/dist/agent-runtime/src/lane-follow.js.map +1 -0
- package/dist/agent-runtime/src/lane-images.cjs +387 -0
- package/dist/agent-runtime/src/lane-images.cjs.map +1 -0
- package/dist/agent-runtime/src/lane-images.js +387 -0
- package/dist/agent-runtime/src/lane-images.js.map +1 -0
- package/dist/agent-runtime/src/message-window.js +1 -1
- package/dist/agent-runtime/src/messages.cjs +19 -1
- package/dist/agent-runtime/src/messages.cjs.map +1 -1
- package/dist/agent-runtime/src/messages.d.ts +8 -0
- package/dist/agent-runtime/src/messages.js +21 -3
- package/dist/agent-runtime/src/messages.js.map +1 -1
- package/dist/agent-runtime/src/named-agents.cjs +301 -0
- package/dist/agent-runtime/src/named-agents.cjs.map +1 -0
- package/dist/agent-runtime/src/named-agents.d.ts +246 -0
- package/dist/agent-runtime/src/named-agents.js +301 -0
- package/dist/agent-runtime/src/named-agents.js.map +1 -0
- package/dist/agent-runtime/src/offline-status.cjs.map +1 -1
- package/dist/agent-runtime/src/offline-status.d.ts +66 -2
- package/dist/agent-runtime/src/offline-status.js.map +1 -1
- package/dist/agent-runtime/src/ptc-subcalls.cjs +41 -0
- package/dist/agent-runtime/src/ptc-subcalls.cjs.map +1 -0
- package/dist/agent-runtime/src/ptc-subcalls.js +41 -0
- package/dist/agent-runtime/src/ptc-subcalls.js.map +1 -0
- package/dist/agent-runtime/src/queue.cjs +2 -2
- package/dist/agent-runtime/src/queue.cjs.map +1 -1
- package/dist/agent-runtime/src/queue.d.ts +20 -25
- package/dist/agent-runtime/src/queue.js +2 -2
- package/dist/agent-runtime/src/queue.js.map +1 -1
- package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs +314 -84
- package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs.map +1 -1
- package/dist/agent-runtime/src/quota-safe-local-storage-session.d.ts +137 -40
- package/dist/agent-runtime/src/quota-safe-local-storage-session.js +318 -88
- package/dist/agent-runtime/src/quota-safe-local-storage-session.js.map +1 -1
- package/dist/agent-runtime/src/run-send.cjs +54 -0
- package/dist/agent-runtime/src/run-send.cjs.map +1 -0
- package/dist/agent-runtime/src/run-send.d.ts +51 -0
- package/dist/agent-runtime/src/run-send.js +54 -0
- package/dist/agent-runtime/src/run-send.js.map +1 -0
- package/dist/agent-runtime/src/running-tool-placeholder.cjs +6 -0
- package/dist/agent-runtime/src/running-tool-placeholder.cjs.map +1 -1
- package/dist/agent-runtime/src/running-tool-placeholder.js +6 -0
- package/dist/agent-runtime/src/running-tool-placeholder.js.map +1 -1
- package/dist/agent-runtime/src/runtime.d.ts +9 -5
- package/dist/agent-runtime/src/sealed-idb.cjs +64 -0
- package/dist/agent-runtime/src/sealed-idb.cjs.map +1 -1
- package/dist/agent-runtime/src/sealed-idb.d.ts +16 -0
- package/dist/agent-runtime/src/sealed-idb.js +64 -0
- package/dist/agent-runtime/src/sealed-idb.js.map +1 -1
- package/dist/agent-runtime/src/send-recovery.cjs +90 -118
- package/dist/agent-runtime/src/send-recovery.cjs.map +1 -1
- package/dist/agent-runtime/src/send-recovery.d.ts +25 -29
- package/dist/agent-runtime/src/send-recovery.js +90 -118
- package/dist/agent-runtime/src/send-recovery.js.map +1 -1
- package/dist/agent-runtime/src/statewire-diagnostics.d.ts +4 -1
- package/dist/agent-runtime/src/statewire-held-sends.cjs +191 -0
- package/dist/agent-runtime/src/statewire-held-sends.cjs.map +1 -0
- package/dist/agent-runtime/src/statewire-held-sends.d.ts +119 -0
- package/dist/agent-runtime/src/statewire-held-sends.js +191 -0
- package/dist/agent-runtime/src/statewire-held-sends.js.map +1 -0
- package/dist/agent-runtime/src/statewire-state.cjs +4 -0
- package/dist/agent-runtime/src/statewire-state.cjs.map +1 -1
- package/dist/agent-runtime/src/statewire-state.js +4 -0
- package/dist/agent-runtime/src/statewire-state.js.map +1 -1
- package/dist/agent-runtime/src/statewire-transport.cjs +8 -2
- package/dist/agent-runtime/src/statewire-transport.cjs.map +1 -1
- package/dist/agent-runtime/src/statewire-transport.d.ts +14 -5
- package/dist/agent-runtime/src/statewire-transport.js +8 -2
- package/dist/agent-runtime/src/statewire-transport.js.map +1 -1
- package/dist/agent-runtime/src/subagent-transcripts.cjs +1 -23
- package/dist/agent-runtime/src/subagent-transcripts.cjs.map +1 -1
- package/dist/agent-runtime/src/subagent-transcripts.js +3 -25
- package/dist/agent-runtime/src/subagent-transcripts.js.map +1 -1
- package/dist/agent-runtime/src/subagents.cjs +22 -29
- package/dist/agent-runtime/src/subagents.cjs.map +1 -1
- package/dist/agent-runtime/src/subagents.js +23 -30
- package/dist/agent-runtime/src/subagents.js.map +1 -1
- package/dist/agent-runtime/src/thread-extras.cjs +27 -19
- package/dist/agent-runtime/src/thread-extras.cjs.map +1 -1
- package/dist/agent-runtime/src/thread-extras.d.ts +19 -6
- package/dist/agent-runtime/src/thread-extras.js +27 -19
- package/dist/agent-runtime/src/thread-extras.js.map +1 -1
- package/dist/agent-runtime/src/thread-handoff-flow-machine.d.ts +8 -8
- package/dist/agent-runtime/src/tool-metadata.cjs +12 -0
- package/dist/agent-runtime/src/tool-metadata.cjs.map +1 -1
- package/dist/agent-runtime/src/tool-metadata.js +12 -0
- package/dist/agent-runtime/src/tool-metadata.js.map +1 -1
- package/dist/agent-runtime/src/tool-names.cjs +21 -0
- package/dist/agent-runtime/src/tool-names.cjs.map +1 -1
- package/dist/agent-runtime/src/tool-names.d.ts +8 -0
- package/dist/agent-runtime/src/tool-names.js +21 -0
- package/dist/agent-runtime/src/tool-names.js.map +1 -1
- package/dist/agent-runtime/src/typed-interrupt-kinds.cjs +247 -0
- package/dist/agent-runtime/src/typed-interrupt-kinds.cjs.map +1 -0
- package/dist/agent-runtime/src/typed-interrupt-kinds.d.ts +173 -0
- package/dist/agent-runtime/src/typed-interrupt-kinds.js +247 -0
- package/dist/agent-runtime/src/typed-interrupt-kinds.js.map +1 -0
- package/dist/agent-runtime/src/typed-interrupts.cjs +48 -0
- package/dist/agent-runtime/src/typed-interrupts.cjs.map +1 -0
- package/dist/agent-runtime/src/typed-interrupts.d.ts +75 -0
- package/dist/agent-runtime/src/typed-interrupts.js +48 -0
- package/dist/agent-runtime/src/typed-interrupts.js.map +1 -0
- package/dist/agent-runtime/src/types.d.ts +1 -1
- package/dist/agent-runtime/src/use-conversation-list.cjs +1 -0
- package/dist/agent-runtime/src/use-conversation-list.cjs.map +1 -1
- package/dist/agent-runtime/src/use-conversation-list.d.ts +7 -0
- package/dist/agent-runtime/src/use-conversation-list.js +1 -0
- package/dist/agent-runtime/src/use-conversation-list.js.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.cjs +46 -29
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.d.ts +14 -22
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.js +46 -29
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.js.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-runtime.cjs +78 -14
- package/dist/agent-runtime/src/use-deep-agent-runtime.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-runtime.d.ts +34 -7
- package/dist/agent-runtime/src/use-deep-agent-runtime.js +79 -15
- package/dist/agent-runtime/src/use-deep-agent-runtime.js.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-thread.cjs +16 -1
- package/dist/agent-runtime/src/use-deep-agent-thread.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-thread.d.ts +7 -2
- package/dist/agent-runtime/src/use-deep-agent-thread.js +16 -1
- package/dist/agent-runtime/src/use-deep-agent-thread.js.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-voice.cjs +30 -4
- package/dist/agent-runtime/src/use-deep-agent-voice.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-voice.d.ts +22 -4
- package/dist/agent-runtime/src/use-deep-agent-voice.js +30 -4
- package/dist/agent-runtime/src/use-deep-agent-voice.js.map +1 -1
- package/dist/agent-runtime/src/withdrawn-turns.d.ts +5 -4
- package/dist/agent-runtime/src/word-device-fit.d.ts +174 -0
- package/dist/agent-runtime/src/work-in.d.ts +127 -0
- package/dist/assets/AthenaAssetEmbed.cjs.map +1 -1
- package/dist/assets/AthenaAssetEmbed.d.ts +6 -1
- package/dist/assets/AthenaAssetEmbed.js.map +1 -1
- package/dist/assets/asset-panel-store.cjs +13 -5
- package/dist/assets/asset-panel-store.cjs.map +1 -1
- package/dist/assets/asset-panel-store.d.ts +33 -2
- package/dist/assets/asset-panel-store.js +13 -5
- package/dist/assets/asset-panel-store.js.map +1 -1
- package/dist/auth/AthenaCredentialSourceContext.cjs +11 -0
- package/dist/auth/AthenaCredentialSourceContext.cjs.map +1 -1
- package/dist/auth/AthenaCredentialSourceContext.d.ts +6 -0
- package/dist/auth/AthenaCredentialSourceContext.js +11 -0
- package/dist/auth/AthenaCredentialSourceContext.js.map +1 -1
- package/dist/auth/account-identity.cjs +13 -2
- package/dist/auth/account-identity.cjs.map +1 -1
- package/dist/auth/account-identity.d.ts +9 -0
- package/dist/auth/account-identity.js +13 -2
- package/dist/auth/account-identity.js.map +1 -1
- package/dist/auth/credential-source.cjs +20 -4
- package/dist/auth/credential-source.cjs.map +1 -1
- package/dist/auth/credential-source.d.ts +9 -0
- package/dist/auth/credential-source.js +20 -4
- package/dist/auth/credential-source.js.map +1 -1
- package/dist/catalog/chat-pickers.cjs +31 -0
- package/dist/catalog/chat-pickers.cjs.map +1 -1
- package/dist/catalog/chat-pickers.d.ts +17 -0
- package/dist/catalog/chat-pickers.js +33 -2
- package/dist/catalog/chat-pickers.js.map +1 -1
- package/dist/catalog/runtime-catalog.cjs +63 -3
- package/dist/catalog/runtime-catalog.cjs.map +1 -1
- package/dist/catalog/runtime-catalog.d.ts +63 -3
- package/dist/catalog/runtime-catalog.js +64 -4
- package/dist/catalog/runtime-catalog.js.map +1 -1
- package/dist/chat/AthenaChat.cjs +290 -97
- package/dist/chat/AthenaChat.cjs.map +1 -1
- package/dist/chat/AthenaChat.d.ts +80 -4
- package/dist/chat/AthenaChat.js +290 -97
- package/dist/chat/AthenaChat.js.map +1 -1
- package/dist/chat/StatewireApprovalCard.cjs +35 -5
- package/dist/chat/StatewireApprovalCard.cjs.map +1 -1
- package/dist/chat/StatewireApprovalCard.d.ts +55 -2
- package/dist/chat/StatewireApprovalCard.js +37 -7
- package/dist/chat/StatewireApprovalCard.js.map +1 -1
- package/dist/chat/StatewireQueuedMessages.cjs +17 -2
- package/dist/chat/StatewireQueuedMessages.cjs.map +1 -1
- package/dist/chat/StatewireQueuedMessages.d.ts +8 -45
- package/dist/chat/StatewireQueuedMessages.js +18 -3
- package/dist/chat/StatewireQueuedMessages.js.map +1 -1
- package/dist/chat/chat-agent-mentions.cjs +70 -0
- package/dist/chat/chat-agent-mentions.cjs.map +1 -0
- package/dist/chat/chat-agent-mentions.d.ts +13 -0
- package/dist/chat/chat-agent-mentions.js +70 -0
- package/dist/chat/chat-agent-mentions.js.map +1 -0
- package/dist/chat/composer-actions.cjs +12 -0
- package/dist/chat/composer-actions.cjs.map +1 -0
- package/dist/chat/composer-actions.d.ts +22 -0
- package/dist/chat/composer-actions.js +12 -0
- package/dist/chat/composer-actions.js.map +1 -0
- package/dist/chat/follow-up-suggestions.cjs +185 -0
- package/dist/chat/follow-up-suggestions.cjs.map +1 -0
- package/dist/chat/follow-up-suggestions.d.ts +64 -0
- package/dist/chat/follow-up-suggestions.js +185 -0
- package/dist/chat/follow-up-suggestions.js.map +1 -0
- package/dist/chat/super-grouping/ToolTimeline.cjs +4 -3
- package/dist/chat/super-grouping/ToolTimeline.cjs.map +1 -1
- package/dist/chat/super-grouping/ToolTimeline.d.ts +7 -3
- package/dist/chat/super-grouping/ToolTimeline.js +4 -3
- package/dist/chat/super-grouping/ToolTimeline.js.map +1 -1
- package/dist/chat/turn-changes.cjs +284 -0
- package/dist/chat/turn-changes.cjs.map +1 -0
- package/dist/chat/turn-changes.d.ts +130 -0
- package/dist/chat/turn-changes.js +284 -0
- package/dist/chat/turn-changes.js.map +1 -0
- package/dist/chat/typed-interrupts/StatewireTypedInterruptCard.cjs +31 -0
- package/dist/chat/typed-interrupts/StatewireTypedInterruptCard.cjs.map +1 -0
- package/dist/chat/typed-interrupts/StatewireTypedInterruptCard.d.ts +31 -0
- package/dist/chat/typed-interrupts/StatewireTypedInterruptCard.js +31 -0
- package/dist/chat/typed-interrupts/StatewireTypedInterruptCard.js.map +1 -0
- package/dist/chat/typed-interrupts/approval-cards.cjs +250 -0
- package/dist/chat/typed-interrupts/approval-cards.cjs.map +1 -0
- package/dist/chat/typed-interrupts/approval-cards.d.ts +22 -0
- package/dist/chat/typed-interrupts/approval-cards.js +250 -0
- package/dist/chat/typed-interrupts/approval-cards.js.map +1 -0
- package/dist/chat/typed-interrupts/form-cards.cjs +289 -0
- package/dist/chat/typed-interrupts/form-cards.cjs.map +1 -0
- package/dist/chat/typed-interrupts/form-cards.d.ts +6 -0
- package/dist/chat/typed-interrupts/form-cards.js +289 -0
- package/dist/chat/typed-interrupts/form-cards.js.map +1 -0
- package/dist/chat/typed-interrupts/interrupt-card-shell.cjs +182 -0
- package/dist/chat/typed-interrupts/interrupt-card-shell.cjs.map +1 -0
- package/dist/chat/typed-interrupts/interrupt-card-shell.d.ts +47 -0
- package/dist/chat/typed-interrupts/interrupt-card-shell.js +182 -0
- package/dist/chat/typed-interrupts/interrupt-card-shell.js.map +1 -0
- package/dist/chat/typed-interrupts/json-schema-form.cjs +388 -0
- package/dist/chat/typed-interrupts/json-schema-form.cjs.map +1 -0
- package/dist/chat/typed-interrupts/json-schema-form.d.ts +33 -0
- package/dist/chat/typed-interrupts/json-schema-form.js +388 -0
- package/dist/chat/typed-interrupts/json-schema-form.js.map +1 -0
- package/dist/chat/typed-interrupts/questionnaire-card.cjs +449 -0
- package/dist/chat/typed-interrupts/questionnaire-card.cjs.map +1 -0
- package/dist/chat/typed-interrupts/questionnaire-card.d.ts +20 -0
- package/dist/chat/typed-interrupts/questionnaire-card.js +449 -0
- package/dist/chat/typed-interrupts/questionnaire-card.js.map +1 -0
- package/dist/chat/typed-interrupts/request-file-card.cjs +159 -0
- package/dist/chat/typed-interrupts/request-file-card.cjs.map +1 -0
- package/dist/chat/typed-interrupts/request-file-card.d.ts +2 -0
- package/dist/chat/typed-interrupts/request-file-card.js +159 -0
- package/dist/chat/typed-interrupts/request-file-card.js.map +1 -0
- package/dist/chat/typed-interrupts/toolkit-selection-card.cjs +189 -0
- package/dist/chat/typed-interrupts/toolkit-selection-card.cjs.map +1 -0
- package/dist/chat/typed-interrupts/toolkit-selection-card.d.ts +23 -0
- package/dist/chat/typed-interrupts/toolkit-selection-card.js +189 -0
- package/dist/chat/typed-interrupts/toolkit-selection-card.js.map +1 -0
- package/dist/chat/typed-interrupts/typed-interrupt-body.cjs +26 -0
- package/dist/chat/typed-interrupts/typed-interrupt-body.cjs.map +1 -0
- package/dist/chat/typed-interrupts/typed-interrupt-body.d.ts +3 -0
- package/dist/chat/typed-interrupts/typed-interrupt-body.js +26 -0
- package/dist/chat/typed-interrupts/typed-interrupt-body.js.map +1 -0
- package/dist/chat/typed-interrupts/typed-interrupt-graphql.cjs +105 -0
- package/dist/chat/typed-interrupts/typed-interrupt-graphql.cjs.map +1 -0
- package/dist/chat/typed-interrupts/typed-interrupt-graphql.d.ts +29 -0
- package/dist/chat/typed-interrupts/typed-interrupt-graphql.js +105 -0
- package/dist/chat/typed-interrupts/typed-interrupt-graphql.js.map +1 -0
- package/dist/chat/typed-interrupts/typed-interrupt-notice.cjs +70 -0
- package/dist/chat/typed-interrupts/typed-interrupt-notice.cjs.map +1 -0
- package/dist/chat/typed-interrupts/typed-interrupt-notice.d.ts +45 -0
- package/dist/chat/typed-interrupts/typed-interrupt-notice.js +70 -0
- package/dist/chat/typed-interrupts/typed-interrupt-notice.js.map +1 -0
- package/dist/chat/typed-interrupts/typed-interrupt-panel.cjs +76 -0
- package/dist/chat/typed-interrupts/typed-interrupt-panel.cjs.map +1 -0
- package/dist/chat/typed-interrupts/typed-interrupt-panel.d.ts +11 -0
- package/dist/chat/typed-interrupts/typed-interrupt-panel.js +76 -0
- package/dist/chat/typed-interrupts/typed-interrupt-panel.js.map +1 -0
- package/dist/chat/typed-interrupts/typed-interrupt-types.d.ts +46 -0
- package/dist/chat/typed-interrupts/use-interrupt-draft.cjs +106 -0
- package/dist/chat/typed-interrupts/use-interrupt-draft.cjs.map +1 -0
- package/dist/chat/typed-interrupts/use-interrupt-draft.d.ts +29 -0
- package/dist/chat/typed-interrupts/use-interrupt-draft.js +106 -0
- package/dist/chat/typed-interrupts/use-interrupt-draft.js.map +1 -0
- package/dist/chat/typed-interrupts/use-statewire-typed-interrupt.cjs +231 -0
- package/dist/chat/typed-interrupts/use-statewire-typed-interrupt.cjs.map +1 -0
- package/dist/chat/typed-interrupts/use-statewire-typed-interrupt.d.ts +66 -0
- package/dist/chat/typed-interrupts/use-statewire-typed-interrupt.js +231 -0
- package/dist/chat/typed-interrupts/use-statewire-typed-interrupt.js.map +1 -0
- package/dist/chat-ui/composer/composer-named-agents.cjs +13 -0
- package/dist/chat-ui/composer/composer-named-agents.cjs.map +1 -0
- package/dist/chat-ui/composer/composer-named-agents.d.ts +20 -0
- package/dist/chat-ui/composer/composer-named-agents.js +13 -0
- package/dist/chat-ui/composer/composer-named-agents.js.map +1 -0
- package/dist/chat-ui/composer/slash-command-menu.cjs +143 -0
- package/dist/chat-ui/composer/slash-command-menu.cjs.map +1 -0
- package/dist/chat-ui/composer/slash-command-menu.d.ts +19 -0
- package/dist/chat-ui/composer/slash-command-menu.js +143 -0
- package/dist/chat-ui/composer/slash-command-menu.js.map +1 -0
- package/dist/chat-ui/composer/slash-commands-extension.cjs +51 -0
- package/dist/chat-ui/composer/slash-commands-extension.cjs.map +1 -0
- package/dist/chat-ui/composer/slash-commands-extension.d.ts +39 -0
- package/dist/chat-ui/composer/slash-commands-extension.js +51 -0
- package/dist/chat-ui/composer/slash-commands-extension.js.map +1 -0
- package/dist/chat-ui/composer/slash-commands.cjs +74 -0
- package/dist/chat-ui/composer/slash-commands.cjs.map +1 -0
- package/dist/chat-ui/composer/slash-commands.d.ts +82 -0
- package/dist/chat-ui/composer/slash-commands.js +74 -0
- package/dist/chat-ui/composer/slash-commands.js.map +1 -0
- package/dist/chat-ui/composer/tiptap-composer.cjs +135 -9
- package/dist/chat-ui/composer/tiptap-composer.cjs.map +1 -1
- package/dist/chat-ui/composer/tiptap-composer.d.ts +61 -2
- package/dist/chat-ui/composer/tiptap-composer.js +135 -9
- package/dist/chat-ui/composer/tiptap-composer.js.map +1 -1
- package/dist/chat-ui/index.cjs +3 -0
- package/dist/chat-ui/index.cjs.map +1 -1
- package/dist/chat-ui/index.d.ts +3 -2
- package/dist/chat-ui/index.js +3 -0
- package/dist/chat-ui/index.js.map +1 -1
- package/dist/chat-ui/mentions/mention-chip.cjs +1 -1
- package/dist/chat-ui/mentions/mention-chip.cjs.map +1 -1
- package/dist/chat-ui/mentions/mention-chip.js +2 -2
- package/dist/chat-ui/mentions/mention-chip.js.map +1 -1
- package/dist/chat-ui/mentions/mention-extension.cjs +8 -1
- package/dist/chat-ui/mentions/mention-extension.cjs.map +1 -1
- package/dist/chat-ui/mentions/mention-extension.js +8 -1
- package/dist/chat-ui/mentions/mention-extension.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/get-scope-name.cjs +1 -0
- package/dist/chat-ui/mentions/suggestions/components/get-scope-name.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/get-scope-name.js +1 -0
- package/dist/chat-ui/mentions/suggestions/components/get-scope-name.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/mention-icon.cjs +2 -0
- package/dist/chat-ui/mentions/suggestions/components/mention-icon.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/mention-icon.js +3 -1
- package/dist/chat-ui/mentions/suggestions/components/mention-icon.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/menu-item.cjs +1 -1
- package/dist/chat-ui/mentions/suggestions/components/menu-item.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/menu-item.js +1 -1
- package/dist/chat-ui/mentions/suggestions/components/menu-item.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/api-client.cjs +36 -0
- package/dist/chat-ui/mentions/suggestions/data/api-client.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/api-client.d.ts +42 -0
- package/dist/chat-ui/mentions/suggestions/data/api-client.js +36 -0
- package/dist/chat-ui/mentions/suggestions/data/api-client.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs +235 -19
- package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/sources/index.d.ts +88 -10
- package/dist/chat-ui/mentions/suggestions/data/sources/index.js +236 -20
- package/dist/chat-ui/mentions/suggestions/data/sources/index.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/types.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/types.d.ts +27 -1
- package/dist/chat-ui/mentions/suggestions/data/types.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.cjs +56 -5
- package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.d.ts +26 -6
- package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.js +57 -6
- package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/mention-suggestions.extension.cjs +34 -17
- package/dist/chat-ui/mentions/suggestions/mention-suggestions.extension.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/mention-suggestions.extension.d.ts +19 -1
- package/dist/chat-ui/mentions/suggestions/mention-suggestions.extension.js +35 -18
- package/dist/chat-ui/mentions/suggestions/mention-suggestions.extension.js.map +1 -1
- package/dist/chat-ui/statewire.d.ts +1 -1
- package/dist/chat-ui/thread/statewire-history-edge.cjs +15 -0
- package/dist/chat-ui/thread/statewire-history-edge.cjs.map +1 -1
- package/dist/chat-ui/thread/statewire-history-edge.d.ts +4 -1
- package/dist/chat-ui/thread/statewire-history-edge.js +15 -0
- package/dist/chat-ui/thread/statewire-history-edge.js.map +1 -1
- package/dist/collab/client.cjs +17 -5
- package/dist/collab/client.cjs.map +1 -1
- package/dist/collab/client.d.ts +22 -7
- package/dist/collab/client.js +17 -5
- package/dist/collab/client.js.map +1 -1
- package/dist/composer/ComposerAttachedReferences.cjs +119 -0
- package/dist/composer/ComposerAttachedReferences.cjs.map +1 -0
- package/dist/composer/ComposerAttachedReferences.d.ts +26 -0
- package/dist/composer/ComposerAttachedReferences.js +119 -0
- package/dist/composer/ComposerAttachedReferences.js.map +1 -0
- package/dist/composer/ComposerNamedAgents.cjs +63 -0
- package/dist/composer/ComposerNamedAgents.cjs.map +1 -0
- package/dist/composer/ComposerNamedAgents.d.ts +16 -0
- package/dist/composer/ComposerNamedAgents.js +63 -0
- package/dist/composer/ComposerNamedAgents.js.map +1 -0
- package/dist/composer/attached-references.cjs +159 -0
- package/dist/composer/attached-references.cjs.map +1 -0
- package/dist/composer/attached-references.d.ts +86 -0
- package/dist/composer/attached-references.js +159 -0
- package/dist/composer/attached-references.js.map +1 -0
- package/dist/composer/build-composed-message.cjs +14 -7
- package/dist/composer/build-composed-message.cjs.map +1 -1
- package/dist/composer/build-composed-message.d.ts +6 -1
- package/dist/composer/build-composed-message.js +14 -7
- package/dist/composer/build-composed-message.js.map +1 -1
- package/dist/composer/composer-handoff.cjs +6 -2
- package/dist/composer/composer-handoff.cjs.map +1 -1
- package/dist/composer/composer-handoff.d.ts +7 -1
- package/dist/composer/composer-handoff.js +6 -2
- package/dist/composer/composer-handoff.js.map +1 -1
- package/dist/composer/folder-upload.cjs +149 -0
- package/dist/composer/folder-upload.cjs.map +1 -0
- package/dist/composer/folder-upload.d.ts +79 -0
- package/dist/composer/folder-upload.js +149 -0
- package/dist/composer/folder-upload.js.map +1 -0
- package/dist/composer/index.d.ts +1 -1
- package/dist/composer/useAttachToChat.cjs +35 -0
- package/dist/composer/useAttachToChat.cjs.map +1 -0
- package/dist/composer/useAttachToChat.d.ts +54 -0
- package/dist/composer/useAttachToChat.js +35 -0
- package/dist/composer/useAttachToChat.js.map +1 -0
- package/dist/composer/useAttachedReferencesComposerProps.cjs +19 -0
- package/dist/composer/useAttachedReferencesComposerProps.cjs.map +1 -0
- package/dist/composer/useAttachedReferencesComposerProps.d.ts +12 -0
- package/dist/composer/useAttachedReferencesComposerProps.js +19 -0
- package/dist/composer/useAttachedReferencesComposerProps.js.map +1 -0
- package/dist/composer/useFileUpload.cjs +95 -7
- package/dist/composer/useFileUpload.cjs.map +1 -1
- package/dist/composer/useFileUpload.d.ts +21 -2
- package/dist/composer/useFileUpload.js +95 -7
- package/dist/composer/useFileUpload.js.map +1 -1
- package/dist/data/athena-api-error.cjs +125 -0
- package/dist/data/athena-api-error.cjs.map +1 -0
- package/dist/data/athena-api-error.d.ts +96 -0
- package/dist/data/athena-api-error.js +125 -0
- package/dist/data/athena-api-error.js.map +1 -0
- package/dist/data/athena-data-client.cjs +106 -0
- package/dist/data/athena-data-client.cjs.map +1 -0
- package/dist/data/athena-data-client.d.ts +74 -0
- package/dist/data/athena-data-client.js +106 -0
- package/dist/data/athena-data-client.js.map +1 -0
- package/dist/data/athena-member.cjs +93 -0
- package/dist/data/athena-member.cjs.map +1 -0
- package/dist/data/athena-member.d.ts +125 -0
- package/dist/data/athena-member.js +93 -0
- package/dist/data/athena-member.js.map +1 -0
- package/dist/data/athena-request.cjs +458 -0
- package/dist/data/athena-request.cjs.map +1 -0
- package/dist/data/athena-request.d.ts +120 -0
- package/dist/data/athena-request.js +458 -0
- package/dist/data/athena-request.js.map +1 -0
- package/dist/data/use-athena-fetch.cjs +14 -0
- package/dist/data/use-athena-fetch.cjs.map +1 -0
- package/dist/data/use-athena-fetch.d.ts +19 -0
- package/dist/data/use-athena-fetch.js +14 -0
- package/dist/data/use-athena-fetch.js.map +1 -0
- package/dist/data/use-athena-graphql.cjs +66 -0
- package/dist/data/use-athena-graphql.cjs.map +1 -0
- package/dist/data/use-athena-graphql.d.ts +56 -0
- package/dist/data/use-athena-graphql.js +66 -0
- package/dist/data/use-athena-graphql.js.map +1 -0
- package/dist/data/use-athena-rest.cjs +33 -0
- package/dist/data/use-athena-rest.cjs.map +1 -0
- package/dist/data/use-athena-rest.d.ts +21 -0
- package/dist/data/use-athena-rest.js +33 -0
- package/dist/data/use-athena-rest.js.map +1 -0
- package/dist/data/use-semantic-query.cjs +44 -0
- package/dist/data/use-semantic-query.cjs.map +1 -0
- package/dist/data/use-semantic-query.d.ts +92 -0
- package/dist/data/use-semantic-query.js +44 -0
- package/dist/data/use-semantic-query.js.map +1 -0
- package/dist/diagnostics/athena-diagnostics.cjs.map +1 -1
- package/dist/diagnostics/athena-diagnostics.d.ts +5 -1
- package/dist/diagnostics/athena-diagnostics.js.map +1 -1
- package/dist/diagnostics/errors.cjs +7 -0
- package/dist/diagnostics/errors.cjs.map +1 -1
- package/dist/diagnostics/errors.d.ts +7 -0
- package/dist/diagnostics/errors.js +7 -0
- package/dist/diagnostics/errors.js.map +1 -1
- package/dist/index.cjs +155 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +72 -13
- package/dist/index.js +148 -4
- package/dist/index.js.map +1 -1
- package/dist/keryx-http/src/initial-sync.cjs +64 -16
- package/dist/keryx-http/src/initial-sync.cjs.map +1 -1
- package/dist/keryx-http/src/initial-sync.d.ts +31 -1
- package/dist/keryx-http/src/initial-sync.js +64 -16
- package/dist/keryx-http/src/initial-sync.js.map +1 -1
- package/dist/keryx-http/src/own-awareness.cjs +20 -0
- package/dist/keryx-http/src/own-awareness.cjs.map +1 -0
- package/dist/keryx-http/src/own-awareness.d.ts +50 -0
- package/dist/keryx-http/src/own-awareness.js +20 -0
- package/dist/keryx-http/src/own-awareness.js.map +1 -0
- package/dist/keryx-http/src/update-attributions.cjs +26 -1
- package/dist/keryx-http/src/update-attributions.cjs.map +1 -1
- package/dist/keryx-http/src/update-attributions.d.ts +10 -1
- package/dist/keryx-http/src/update-attributions.js +26 -1
- package/dist/keryx-http/src/update-attributions.js.map +1 -1
- package/dist/offline/chat-outbox.cjs +262 -26
- package/dist/offline/chat-outbox.cjs.map +1 -1
- package/dist/offline/chat-outbox.d.ts +90 -12
- package/dist/offline/chat-outbox.js +263 -27
- package/dist/offline/chat-outbox.js.map +1 -1
- package/dist/provider/AthenaProvider.cjs +56 -19
- package/dist/provider/AthenaProvider.cjs.map +1 -1
- package/dist/provider/AthenaProvider.d.ts +24 -8
- package/dist/provider/AthenaProvider.js +57 -20
- package/dist/provider/AthenaProvider.js.map +1 -1
- package/dist/react/package.json.cjs +1 -1
- package/dist/react/package.json.js +1 -1
- package/dist/references/src/anchors/types.cjs +5 -0
- package/dist/references/src/anchors/types.cjs.map +1 -1
- package/dist/references/src/anchors/types.js +5 -0
- package/dist/references/src/anchors/types.js.map +1 -1
- package/dist/references/src/attachable.cjs +149 -0
- package/dist/references/src/attachable.cjs.map +1 -0
- package/dist/references/src/attachable.d.ts +87 -0
- package/dist/references/src/attachable.js +149 -0
- package/dist/references/src/attachable.js.map +1 -0
- package/dist/runtime/StatewirePlanModeLaneSync.cjs +93 -0
- package/dist/runtime/StatewirePlanModeLaneSync.cjs.map +1 -0
- package/dist/runtime/StatewirePlanModeLaneSync.d.ts +34 -0
- package/dist/runtime/StatewirePlanModeLaneSync.js +93 -0
- package/dist/runtime/StatewirePlanModeLaneSync.js.map +1 -0
- package/dist/runtime/StatewireThreadConfigLaneSync.cjs +2 -0
- package/dist/runtime/StatewireThreadConfigLaneSync.cjs.map +1 -1
- package/dist/runtime/StatewireThreadConfigLaneSync.d.ts +4 -0
- package/dist/runtime/StatewireThreadConfigLaneSync.js +2 -0
- package/dist/runtime/StatewireThreadConfigLaneSync.js.map +1 -1
- package/dist/runtime/statewire-plan-mode.cjs +71 -0
- package/dist/runtime/statewire-plan-mode.cjs.map +1 -0
- package/dist/runtime/statewire-plan-mode.d.ts +88 -0
- package/dist/runtime/statewire-plan-mode.js +71 -0
- package/dist/runtime/statewire-plan-mode.js.map +1 -0
- package/dist/runtime/statewire-run-config.cjs +3 -1
- package/dist/runtime/statewire-run-config.cjs.map +1 -1
- package/dist/runtime/statewire-run-config.d.ts +7 -0
- package/dist/runtime/statewire-run-config.js +3 -1
- package/dist/runtime/statewire-run-config.js.map +1 -1
- package/dist/runtime/statewire-session-key.cjs +11 -5
- package/dist/runtime/statewire-session-key.cjs.map +1 -1
- package/dist/runtime/statewire-session-key.d.ts +22 -10
- package/dist/runtime/statewire-session-key.js +11 -5
- package/dist/runtime/statewire-session-key.js.map +1 -1
- package/dist/runtime/useAthenaStatewireRuntime.cjs +65 -8
- package/dist/runtime/useAthenaStatewireRuntime.cjs.map +1 -1
- package/dist/runtime/useAthenaStatewireRuntime.d.ts +26 -10
- package/dist/runtime/useAthenaStatewireRuntime.js +67 -10
- package/dist/runtime/useAthenaStatewireRuntime.js.map +1 -1
- package/dist/search/useAthenaAssets.cjs +394 -0
- package/dist/search/useAthenaAssets.cjs.map +1 -0
- package/dist/search/useAthenaAssets.d.ts +186 -0
- package/dist/search/useAthenaAssets.js +394 -0
- package/dist/search/useAthenaAssets.js.map +1 -0
- package/dist/sheet-range/index.cjs +4 -0
- package/dist/sheet-range/index.cjs.map +1 -1
- package/dist/sheet-range/index.d.ts +4 -2
- package/dist/sheet-range/index.js +4 -0
- package/dist/sheet-range/index.js.map +1 -1
- package/dist/sheet-range/query-range.cjs +102 -0
- package/dist/sheet-range/query-range.cjs.map +1 -0
- package/dist/sheet-range/query-range.d.ts +46 -0
- package/dist/sheet-range/query-range.js +102 -0
- package/dist/sheet-range/query-range.js.map +1 -0
- package/dist/styles.css +1 -1
- package/dist/subagents/index.cjs +49 -0
- package/dist/subagents/index.cjs.map +1 -0
- package/dist/subagents/index.d.ts +16 -0
- package/dist/subagents/index.js +49 -0
- package/dist/subagents/index.js.map +1 -0
- package/dist/subagents/lane-follow.cjs +19 -0
- package/dist/subagents/lane-follow.cjs.map +1 -0
- package/dist/subagents/lane-follow.d.ts +9 -0
- package/dist/subagents/lane-follow.js +19 -0
- package/dist/subagents/lane-follow.js.map +1 -0
- package/dist/subagents/lane-model.cjs +178 -0
- package/dist/subagents/lane-model.cjs.map +1 -0
- package/dist/subagents/lane-model.d.ts +140 -0
- package/dist/subagents/lane-model.js +178 -0
- package/dist/subagents/lane-model.js.map +1 -0
- package/dist/subagents/lane-parts.cjs +517 -0
- package/dist/subagents/lane-parts.cjs.map +1 -0
- package/dist/subagents/lane-parts.d.ts +130 -0
- package/dist/subagents/lane-parts.js +517 -0
- package/dist/subagents/lane-parts.js.map +1 -0
- package/dist/subagents/subagent-lane-group.cjs +215 -0
- package/dist/subagents/subagent-lane-group.cjs.map +1 -0
- package/dist/subagents/subagent-lane-group.d.ts +67 -0
- package/dist/subagents/subagent-lane-group.js +215 -0
- package/dist/subagents/subagent-lane-group.js.map +1 -0
- package/dist/subagents/subagent-transcript-drawer.cjs +431 -0
- package/dist/subagents/subagent-transcript-drawer.cjs.map +1 -0
- package/dist/subagents/subagent-transcript-drawer.d.ts +78 -0
- package/dist/subagents/subagent-transcript-drawer.js +431 -0
- package/dist/subagents/subagent-transcript-drawer.js.map +1 -0
- package/dist/subagents/task-subagent-group.cjs +115 -0
- package/dist/subagents/task-subagent-group.cjs.map +1 -0
- package/dist/subagents/task-subagent-group.d.ts +36 -0
- package/dist/subagents/task-subagent-group.js +115 -0
- package/dist/subagents/task-subagent-group.js.map +1 -0
- package/dist/subagents/use-omitted-images-in-view.cjs +68 -0
- package/dist/subagents/use-omitted-images-in-view.cjs.map +1 -0
- package/dist/subagents/use-omitted-images-in-view.d.ts +21 -0
- package/dist/subagents/use-omitted-images-in-view.js +68 -0
- package/dist/subagents/use-omitted-images-in-view.js.map +1 -0
- package/dist/threads/Inbox.cjs +2 -2
- package/dist/threads/Inbox.cjs.map +1 -1
- package/dist/threads/SessionList.cjs +6 -6
- package/dist/threads/SessionList.cjs.map +1 -1
- package/dist/threads/SessionsPage.cjs +13 -7
- package/dist/threads/SessionsPage.cjs.map +1 -1
- package/dist/threads/SessionsPage.d.ts +10 -1
- package/dist/threads/SessionsPage.js +9 -3
- package/dist/threads/SessionsPage.js.map +1 -1
- package/dist/threads/session-list-model.cjs.map +1 -1
- package/dist/threads/session-list-model.d.ts +2 -1
- package/dist/threads/session-list-model.js.map +1 -1
- package/dist/threads/session-row-parts.cjs +3 -3
- package/dist/threads/session-row-parts.cjs.map +1 -1
- package/dist/threads/sessions-page-model.cjs +13 -5
- package/dist/threads/sessions-page-model.cjs.map +1 -1
- package/dist/threads/sessions-page-model.d.ts +7 -0
- package/dist/threads/sessions-page-model.js +11 -3
- package/dist/threads/sessions-page-model.js.map +1 -1
- package/dist/threads/sessions-page-storage.cjs +8 -8
- package/dist/threads/sessions-page-storage.cjs.map +1 -1
- package/dist/threads/sessions-page-storage.d.ts +5 -1
- package/dist/threads/sessions-page-storage.js +8 -8
- package/dist/threads/sessions-page-storage.js.map +1 -1
- package/dist/threads/use-athena-sessions.cjs +1 -0
- package/dist/threads/use-athena-sessions.cjs.map +1 -1
- package/dist/threads/use-athena-sessions.d.ts +7 -0
- package/dist/threads/use-athena-sessions.js +1 -0
- package/dist/threads/use-athena-sessions.js.map +1 -1
- package/dist/threads/use-athena-thread-agent.cjs +31 -0
- package/dist/threads/use-athena-thread-agent.cjs.map +1 -0
- package/dist/threads/use-athena-thread-agent.d.ts +38 -0
- package/dist/threads/use-athena-thread-agent.js +31 -0
- package/dist/threads/use-athena-thread-agent.js.map +1 -0
- package/dist/threads/use-athena-thread-plan-mode.cjs +18 -0
- package/dist/threads/use-athena-thread-plan-mode.cjs.map +1 -0
- package/dist/threads/use-athena-thread-plan-mode.d.ts +18 -0
- package/dist/threads/use-athena-thread-plan-mode.js +18 -0
- package/dist/threads/use-athena-thread-plan-mode.js.map +1 -0
- package/dist/threads/use-rest-conversation-history.d.ts +1 -0
- package/dist/tools/agent-creations.cjs +97 -0
- package/dist/tools/agent-creations.cjs.map +1 -0
- package/dist/tools/agent-creations.d.ts +38 -0
- package/dist/tools/agent-creations.js +97 -0
- package/dist/tools/agent-creations.js.map +1 -0
- package/dist/tools/agent-highlights.cjs +100 -0
- package/dist/tools/agent-highlights.cjs.map +1 -0
- package/dist/tools/agent-highlights.d.ts +57 -0
- package/dist/tools/agent-highlights.js +100 -0
- package/dist/tools/agent-highlights.js.map +1 -0
- package/dist/tools/append-document-tool-ui.cjs +1 -0
- package/dist/tools/append-document-tool-ui.cjs.map +1 -1
- package/dist/tools/append-document-tool-ui.d.ts +7 -0
- package/dist/tools/append-document-tool-ui.js +2 -1
- package/dist/tools/append-document-tool-ui.js.map +1 -1
- package/dist/tools/auto-open-tools.cjs +144 -71
- package/dist/tools/auto-open-tools.cjs.map +1 -1
- package/dist/tools/auto-open-tools.d.ts +131 -1
- package/dist/tools/auto-open-tools.js +145 -72
- package/dist/tools/auto-open-tools.js.map +1 -1
- package/dist/tools/browser-tool-uis.cjs +594 -0
- package/dist/tools/browser-tool-uis.cjs.map +1 -0
- package/dist/tools/browser-tool-uis.d.ts +8 -0
- package/dist/tools/browser-tool-uis.js +594 -0
- package/dist/tools/browser-tool-uis.js.map +1 -0
- package/dist/tools/computer-asset-tool-uis.cjs +313 -0
- package/dist/tools/computer-asset-tool-uis.cjs.map +1 -0
- package/dist/tools/computer-asset-tool-uis.d.ts +5 -0
- package/dist/tools/computer-asset-tool-uis.js +313 -0
- package/dist/tools/computer-asset-tool-uis.js.map +1 -0
- package/dist/tools/document-edit-tool-uis.cjs +218 -0
- package/dist/tools/document-edit-tool-uis.cjs.map +1 -0
- package/dist/tools/document-edit-tool-uis.d.ts +40 -0
- package/dist/tools/document-edit-tool-uis.js +218 -0
- package/dist/tools/document-edit-tool-uis.js.map +1 -0
- package/dist/tools/drive-tool-uis.cjs +425 -0
- package/dist/tools/drive-tool-uis.cjs.map +1 -0
- package/dist/tools/drive-tool-uis.d.ts +120 -0
- package/dist/tools/drive-tool-uis.js +425 -0
- package/dist/tools/drive-tool-uis.js.map +1 -0
- package/dist/tools/email-calendar-tool-uis.cjs +789 -0
- package/dist/tools/email-calendar-tool-uis.cjs.map +1 -0
- package/dist/tools/email-calendar-tool-uis.d.ts +129 -0
- package/dist/tools/email-calendar-tool-uis.js +789 -0
- package/dist/tools/email-calendar-tool-uis.js.map +1 -0
- package/dist/tools/ontology-tool-uis.cjs +83 -0
- package/dist/tools/ontology-tool-uis.cjs.map +1 -0
- package/dist/tools/ontology-tool-uis.d.ts +9 -0
- package/dist/tools/ontology-tool-uis.js +83 -0
- package/dist/tools/ontology-tool-uis.js.map +1 -0
- package/dist/tools/orchestration-tool-uis.cjs +586 -0
- package/dist/tools/orchestration-tool-uis.cjs.map +1 -0
- package/dist/tools/orchestration-tool-uis.d.ts +141 -0
- package/dist/tools/orchestration-tool-uis.js +586 -0
- package/dist/tools/orchestration-tool-uis.js.map +1 -0
- package/dist/tools/presentation-edit-tool-uis.cjs +516 -0
- package/dist/tools/presentation-edit-tool-uis.cjs.map +1 -0
- package/dist/tools/presentation-edit-tool-uis.d.ts +73 -0
- package/dist/tools/presentation-edit-tool-uis.js +516 -0
- package/dist/tools/presentation-edit-tool-uis.js.map +1 -0
- package/dist/tools/project-tool-uis.cjs +213 -0
- package/dist/tools/project-tool-uis.cjs.map +1 -0
- package/dist/tools/project-tool-uis.d.ts +14 -0
- package/dist/tools/project-tool-uis.js +213 -0
- package/dist/tools/project-tool-uis.js.map +1 -0
- package/dist/tools/sandbox-tool-uis.cjs +491 -0
- package/dist/tools/sandbox-tool-uis.cjs.map +1 -0
- package/dist/tools/sandbox-tool-uis.d.ts +116 -0
- package/dist/tools/sandbox-tool-uis.js +491 -0
- package/dist/tools/sandbox-tool-uis.js.map +1 -0
- package/dist/tools/sheet-query-tool-ui.cjs +138 -0
- package/dist/tools/sheet-query-tool-ui.cjs.map +1 -0
- package/dist/tools/sheet-query-tool-ui.d.ts +15 -0
- package/dist/tools/sheet-query-tool-ui.js +138 -0
- package/dist/tools/sheet-query-tool-ui.js.map +1 -0
- package/dist/tools/studio-screenshot-tool-uis.cjs +262 -0
- package/dist/tools/studio-screenshot-tool-uis.cjs.map +1 -0
- package/dist/tools/studio-screenshot-tool-uis.d.ts +52 -0
- package/dist/tools/studio-screenshot-tool-uis.js +262 -0
- package/dist/tools/studio-screenshot-tool-uis.js.map +1 -0
- package/dist/tools/subagent-task-tool-ui.cjs +24 -475
- package/dist/tools/subagent-task-tool-ui.cjs.map +1 -1
- package/dist/tools/subagent-task-tool-ui.d.ts +19 -103
- package/dist/tools/subagent-task-tool-ui.js +28 -479
- package/dist/tools/subagent-task-tool-ui.js.map +1 -1
- package/dist/tools/tool-summary.cjs +36 -0
- package/dist/tools/tool-summary.cjs.map +1 -1
- package/dist/tools/tool-summary.js +36 -0
- package/dist/tools/tool-summary.js.map +1 -1
- package/dist/tools/tool-uis.cjs +181 -53
- package/dist/tools/tool-uis.cjs.map +1 -1
- package/dist/tools/tool-uis.d.ts +40 -0
- package/dist/tools/tool-uis.js +183 -55
- package/dist/tools/tool-uis.js.map +1 -1
- package/dist/typed-interrupts/index.cjs +15 -0
- package/dist/typed-interrupts/index.cjs.map +1 -0
- package/dist/typed-interrupts/index.d.ts +20 -0
- package/dist/typed-interrupts/index.js +15 -0
- package/dist/typed-interrupts/index.js.map +1 -0
- package/dist/workbench/session-workbench-panes.cjs +6 -6
- package/dist/workbench/session-workbench-panes.cjs.map +1 -1
- package/package.json +28 -6
- package/dist/agent-runtime/src/chat-outbox-store.cjs +0 -510
- package/dist/agent-runtime/src/chat-outbox-store.cjs.map +0 -1
- package/dist/agent-runtime/src/chat-outbox-store.d.ts +0 -210
- package/dist/agent-runtime/src/chat-outbox-store.js +0 -510
- package/dist/agent-runtime/src/chat-outbox-store.js.map +0 -1
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const attachable = require("../references/src/attachable.cjs");
|
|
3
4
|
const AttachmentContext = require("./AttachmentContext.cjs");
|
|
4
5
|
const composerMessage = require("../chat-ui/composer/composer-message.cjs");
|
|
5
6
|
const composerMarkdown = require("../agent-runtime/src/composer-markdown.cjs");
|
|
@@ -54,7 +55,9 @@ function holdComposedSend({
|
|
|
54
55
|
carried = [],
|
|
55
56
|
quote,
|
|
56
57
|
send,
|
|
57
|
-
appUrl
|
|
58
|
+
appUrl,
|
|
59
|
+
addressedAgents,
|
|
60
|
+
attachedReferences = []
|
|
58
61
|
}) {
|
|
59
62
|
const composed = buildComposedSend({ attachments, quote, send, appUrl });
|
|
60
63
|
if (!composed) return null;
|
|
@@ -72,12 +75,16 @@ function holdComposedSend({
|
|
|
72
75
|
return outbox.hold({
|
|
73
76
|
text: composed.text,
|
|
74
77
|
composerMarkdown: composed.draftMarkdown,
|
|
75
|
-
metadata:
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
metadata: attachable.withAttachedReferences(
|
|
79
|
+
composerMarkdown.withDeepAgentComposerMarkdown({
|
|
80
|
+
metadata: void 0,
|
|
81
|
+
text: composed.text,
|
|
82
|
+
markdown: composed.draftMarkdown
|
|
83
|
+
}),
|
|
84
|
+
attachedReferences
|
|
85
|
+
),
|
|
86
|
+
attachments: [...named.values()],
|
|
87
|
+
...addressedAgents && { addressedAgents }
|
|
81
88
|
});
|
|
82
89
|
}
|
|
83
90
|
exports.buildComposedMessage = buildComposedMessage;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-composed-message.cjs","sources":["../../src/composer/build-composed-message.ts"],"sourcesContent":["import {\n type ChatOutbox,\n type ChatOutboxAttachment,\n type ChatOutboxEntry,\n withDeepAgentComposerMarkdown,\n} from '@athenaintel/agent-runtime';\nimport type { UploadedAsset } from './useFileUpload';\nimport type { QuoteData } from './QuoteContext';\nimport { buildAttachmentMarkdownWithAppUrl } from './AttachmentContext';\nimport {\n type ComposerSend,\n escapeCharacterReferences,\n} from '../chat-ui/composer/composer-message';\n\n/**\n * Assembles a composed message from attachments, a quote, and user text.\n * Used by both the TipTap Enter-key submit and the send-button click handler\n * to avoid duplicating the message-assembly logic.\n *\n * Returns an empty string if all inputs are empty.\n */\nexport function buildComposedMessage(opts: {\n attachments?: UploadedAsset[];\n quote?: QuoteData | null;\n userText?: string;\n appUrl?: string;\n}): string {\n const parts: string[] = [];\n\n if (opts.attachments && opts.attachments.length > 0) {\n const attachmentMd = buildAttachmentMarkdownWithAppUrl({\n attachments: opts.attachments,\n appUrl: opts.appUrl,\n });\n if (attachmentMd) parts.push(attachmentMd);\n }\n\n if (opts.quote) {\n const quotedLines = opts.quote.text.split('\\n').map((l) => `> ${l}`).join('\\n');\n const sourceLabel = opts.quote.sourceTitle\n ? `From \"${opts.quote.sourceTitle}\"`\n : opts.quote.sourceRole === 'assistant'\n ? 'Quoting assistant'\n : 'Quoting';\n parts.push(`${sourceLabel}:\\n${quotedLines}`);\n }\n\n const trimmed = opts.userText?.trim();\n if (trimmed) parts.push(trimmed);\n\n return parts.join('\\n\\n');\n}\n\n/**\n * The composed message a send delivers and the draft it came from: the same\n * attachments and quote around the editor's text as typed in one, and around\n * the editor's draft in the other (`ComposerSend`). `null` when there is\n * nothing to send.\n *\n * The quote and the attachment titles are text the person did not type in\n * the editor, and the message carries them as they are. The draft writes an\n * `&` in them that starts a character reference as `&`, as the composer's\n * draft does for typed text, so it reads back as the message and stays a draft\n * of the message's own text (`isComposerMarkdownOfText`, which agora applies\n * too): a quoted `<` would otherwise read as `<` in the draft and the\n * message would lose its composer markdown.\n */\nexport function buildComposedSend({\n attachments,\n quote,\n send,\n appUrl,\n}: {\n attachments?: UploadedAsset[];\n quote?: QuoteData | null;\n send: ComposerSend;\n appUrl?: string;\n}): ComposerSend | null {\n const text = buildComposedMessage({ attachments, quote, userText: send.text, appUrl });\n if (!text) return null;\n const draftMarkdown = buildComposedMessage({\n attachments: attachments?.map((attachment) => ({\n ...attachment,\n title: escapeCharacterReferences(attachment.title),\n })),\n quote: quote && {\n ...quote,\n text: escapeCharacterReferences(quote.text),\n ...(quote.sourceTitle !== undefined && {\n sourceTitle: escapeCharacterReferences(quote.sourceTitle),\n }),\n },\n userText: send.draftMarkdown,\n appUrl,\n });\n return { text, draftMarkdown };\n}\n\n/**\n * Holds a composed message in the chat outbox while sends are on hold (Athena can't be reached, or\n * earlier messages still wait): the uploaded attachments and the quote around the editor's text,\n * exactly as {@link buildComposedSend} would send them, so it goes with them once Athena is back.\n * The attachments are files already in Athena (an upload that finished before the drop); they are\n * named on the held message so the outbox asks Athena, right before it goes, that each can still\n * be opened. Cancel or Edit gives back the composed draft: the attachments as mentions in the\n * editor, the quote as quoted lines, nothing lost. `carried` are files already in Athena the\n * editor's own draft carries (mentions a held message gave back), named with the pills. `null`\n * when there is nothing to hold.\n */\nexport function holdComposedSend({\n outbox,\n attachments,\n carried = [],\n quote,\n send,\n appUrl,\n}: {\n outbox: ChatOutbox;\n attachments?: UploadedAsset[];\n carried?: readonly ChatOutboxAttachment[];\n quote?: QuoteData | null;\n send: ComposerSend;\n appUrl?: string;\n}): ChatOutboxEntry | null {\n const composed = buildComposedSend({ attachments, quote, send, appUrl });\n if (!composed) return null;\n const named = new Map<string, ChatOutboxAttachment>();\n for (const attachment of attachments ?? []) {\n named.set(attachment.id, {\n assetId: attachment.id,\n title: attachment.title,\n ...(attachment.mediaType && { mediaType: attachment.mediaType }),\n });\n }\n for (const attachment of carried) {\n if (!named.has(attachment.assetId)) named.set(attachment.assetId, attachment);\n }\n return outbox.hold({\n text: composed.text,\n composerMarkdown: composed.draftMarkdown,\n metadata: withDeepAgentComposerMarkdown({\n
|
|
1
|
+
{"version":3,"file":"build-composed-message.cjs","sources":["../../src/composer/build-composed-message.ts"],"sourcesContent":["import {\n type ChatOutbox,\n type ChatOutboxAttachment,\n type ChatOutboxEntry,\n withDeepAgentComposerMarkdown,\n} from '@athenaintel/agent-runtime';\nimport {\n type AttachableReference,\n withAttachedReferences,\n} from '@athenaintel/references/attachable';\nimport type { UploadedAsset } from './useFileUpload';\nimport type { QuoteData } from './QuoteContext';\nimport { buildAttachmentMarkdownWithAppUrl } from './AttachmentContext';\nimport {\n type ComposerSend,\n escapeCharacterReferences,\n} from '../chat-ui/composer/composer-message';\n\n/**\n * Assembles a composed message from attachments, a quote, and user text.\n * Used by both the TipTap Enter-key submit and the send-button click handler\n * to avoid duplicating the message-assembly logic.\n *\n * Returns an empty string if all inputs are empty.\n */\nexport function buildComposedMessage(opts: {\n attachments?: UploadedAsset[];\n quote?: QuoteData | null;\n userText?: string;\n appUrl?: string;\n}): string {\n const parts: string[] = [];\n\n if (opts.attachments && opts.attachments.length > 0) {\n const attachmentMd = buildAttachmentMarkdownWithAppUrl({\n attachments: opts.attachments,\n appUrl: opts.appUrl,\n });\n if (attachmentMd) parts.push(attachmentMd);\n }\n\n if (opts.quote) {\n const quotedLines = opts.quote.text.split('\\n').map((l) => `> ${l}`).join('\\n');\n const sourceLabel = opts.quote.sourceTitle\n ? `From \"${opts.quote.sourceTitle}\"`\n : opts.quote.sourceRole === 'assistant'\n ? 'Quoting assistant'\n : 'Quoting';\n parts.push(`${sourceLabel}:\\n${quotedLines}`);\n }\n\n const trimmed = opts.userText?.trim();\n if (trimmed) parts.push(trimmed);\n\n return parts.join('\\n\\n');\n}\n\n/**\n * The composed message a send delivers and the draft it came from: the same\n * attachments and quote around the editor's text as typed in one, and around\n * the editor's draft in the other (`ComposerSend`). `null` when there is\n * nothing to send.\n *\n * The quote and the attachment titles are text the person did not type in\n * the editor, and the message carries them as they are. The draft writes an\n * `&` in them that starts a character reference as `&`, as the composer's\n * draft does for typed text, so it reads back as the message and stays a draft\n * of the message's own text (`isComposerMarkdownOfText`, which agora applies\n * too): a quoted `<` would otherwise read as `<` in the draft and the\n * message would lose its composer markdown.\n */\nexport function buildComposedSend({\n attachments,\n quote,\n send,\n appUrl,\n}: {\n attachments?: UploadedAsset[];\n quote?: QuoteData | null;\n send: ComposerSend;\n appUrl?: string;\n}): ComposerSend | null {\n const text = buildComposedMessage({ attachments, quote, userText: send.text, appUrl });\n if (!text) return null;\n const draftMarkdown = buildComposedMessage({\n attachments: attachments?.map((attachment) => ({\n ...attachment,\n title: escapeCharacterReferences(attachment.title),\n })),\n quote: quote && {\n ...quote,\n text: escapeCharacterReferences(quote.text),\n ...(quote.sourceTitle !== undefined && {\n sourceTitle: escapeCharacterReferences(quote.sourceTitle),\n }),\n },\n userText: send.draftMarkdown,\n appUrl,\n });\n return { text, draftMarkdown };\n}\n\n/**\n * Holds a composed message in the chat outbox while sends are on hold (Athena can't be reached, or\n * earlier messages still wait): the uploaded attachments and the quote around the editor's text,\n * exactly as {@link buildComposedSend} would send them, so it goes with them once Athena is back.\n * The attachments are files already in Athena (an upload that finished before the drop); they are\n * named on the held message so the outbox asks Athena, right before it goes, that each can still\n * be opened. Cancel or Edit gives back the composed draft: the attachments as mentions in the\n * editor, the quote as quoted lines, nothing lost. `carried` are files already in Athena the\n * editor's own draft carries (mentions a held message gave back), named with the pills. `null`\n * when there is nothing to hold.\n */\nexport function holdComposedSend({\n outbox,\n attachments,\n carried = [],\n quote,\n send,\n appUrl,\n addressedAgents,\n attachedReferences = [],\n}: {\n outbox: ChatOutbox;\n attachments?: UploadedAsset[];\n carried?: readonly ChatOutboxAttachment[];\n quote?: QuoteData | null;\n send: ComposerSend;\n appUrl?: string;\n /** The agents the message names (`message.metadata.addressedAgents`). */\n addressedAgents?: readonly string[];\n /** The references attached to the message (`message.metadata.attachedReferences`). */\n attachedReferences?: readonly AttachableReference[];\n}): ChatOutboxEntry | null {\n const composed = buildComposedSend({ attachments, quote, send, appUrl });\n if (!composed) return null;\n const named = new Map<string, ChatOutboxAttachment>();\n for (const attachment of attachments ?? []) {\n named.set(attachment.id, {\n assetId: attachment.id,\n title: attachment.title,\n ...(attachment.mediaType && { mediaType: attachment.mediaType }),\n });\n }\n for (const attachment of carried) {\n if (!named.has(attachment.assetId)) named.set(attachment.assetId, attachment);\n }\n return outbox.hold({\n text: composed.text,\n composerMarkdown: composed.draftMarkdown,\n metadata: withAttachedReferences(\n withDeepAgentComposerMarkdown({\n metadata: undefined,\n text: composed.text,\n markdown: composed.draftMarkdown,\n }),\n attachedReferences,\n ),\n attachments: [...named.values()],\n ...(addressedAgents && { addressedAgents }),\n });\n}\n"],"names":["buildAttachmentMarkdownWithAppUrl","escapeCharacterReferences","withAttachedReferences","withDeepAgentComposerMarkdown"],"mappings":";;;;;;AAyBO,SAAS,qBAAqB,MAK1B;;AACT,QAAM,QAAkB,CAAA;AAExB,MAAI,KAAK,eAAe,KAAK,YAAY,SAAS,GAAG;AACnD,UAAM,eAAeA,kBAAAA,kCAAkC;AAAA,MACrD,aAAa,KAAK;AAAA,MAClB,QAAQ,KAAK;AAAA,IAAA,CACd;AACD,QAAI,aAAc,OAAM,KAAK,YAAY;AAAA,EAC3C;AAEA,MAAI,KAAK,OAAO;AACd,UAAM,cAAc,KAAK,MAAM,KAAK,MAAM,IAAI,EAAE,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI;AAC9E,UAAM,cAAc,KAAK,MAAM,cAC3B,SAAS,KAAK,MAAM,WAAW,MAC/B,KAAK,MAAM,eAAe,cACxB,sBACA;AACN,UAAM,KAAK,GAAG,WAAW;AAAA,EAAM,WAAW,EAAE;AAAA,EAC9C;AAEA,QAAM,WAAU,UAAK,aAAL,mBAAe;AAC/B,MAAI,QAAS,OAAM,KAAK,OAAO;AAE/B,SAAO,MAAM,KAAK,MAAM;AAC1B;AAgBO,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKwB;AACtB,QAAM,OAAO,qBAAqB,EAAE,aAAa,OAAO,UAAU,KAAK,MAAM,QAAQ;AACrF,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,gBAAgB,qBAAqB;AAAA,IACzC,aAAa,2CAAa,IAAI,CAAC,gBAAgB;AAAA,MAC7C,GAAG;AAAA,MACH,OAAOC,gBAAAA,0BAA0B,WAAW,KAAK;AAAA,IAAA;AAAA,IAEnD,OAAO,SAAS;AAAA,MACd,GAAG;AAAA,MACH,MAAMA,gBAAAA,0BAA0B,MAAM,IAAI;AAAA,MAC1C,GAAI,MAAM,gBAAgB,UAAa;AAAA,QACrC,aAAaA,gBAAAA,0BAA0B,MAAM,WAAW;AAAA,MAAA;AAAA,IAC1D;AAAA,IAEF,UAAU,KAAK;AAAA,IACf;AAAA,EAAA,CACD;AACD,SAAO,EAAE,MAAM,cAAA;AACjB;AAaO,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA,UAAU,CAAA;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,qBAAqB,CAAA;AACvB,GAW2B;AACzB,QAAM,WAAW,kBAAkB,EAAE,aAAa,OAAO,MAAM,QAAQ;AACvE,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,4BAAY,IAAA;AAClB,aAAW,cAAc,eAAe,IAAI;AAC1C,UAAM,IAAI,WAAW,IAAI;AAAA,MACvB,SAAS,WAAW;AAAA,MACpB,OAAO,WAAW;AAAA,MAClB,GAAI,WAAW,aAAa,EAAE,WAAW,WAAW,UAAA;AAAA,IAAU,CAC/D;AAAA,EACH;AACA,aAAW,cAAc,SAAS;AAChC,QAAI,CAAC,MAAM,IAAI,WAAW,OAAO,EAAG,OAAM,IAAI,WAAW,SAAS,UAAU;AAAA,EAC9E;AACA,SAAO,OAAO,KAAK;AAAA,IACjB,MAAM,SAAS;AAAA,IACf,kBAAkB,SAAS;AAAA,IAC3B,UAAUC,WAAAA;AAAAA,MACRC,+CAA8B;AAAA,QAC5B,UAAU;AAAA,QACV,MAAM,SAAS;AAAA,QACf,UAAU,SAAS;AAAA,MAAA,CACpB;AAAA,MACD;AAAA,IAAA;AAAA,IAEF,aAAa,CAAC,GAAG,MAAM,QAAQ;AAAA,IAC/B,GAAI,mBAAmB,EAAE,gBAAA;AAAA,EAAgB,CAC1C;AACH;;;;"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type ChatOutbox, type ChatOutboxAttachment, type ChatOutboxEntry } from '../agent-runtime/src/index';
|
|
2
|
+
import { type AttachableReference } from '../references/src/attachable';
|
|
2
3
|
import type { UploadedAsset } from './useFileUpload';
|
|
3
4
|
import type { QuoteData } from './QuoteContext';
|
|
4
5
|
import { type ComposerSend } from '../chat-ui/composer/composer-message';
|
|
@@ -46,11 +47,15 @@ export declare function buildComposedSend({ attachments, quote, send, appUrl, }:
|
|
|
46
47
|
* editor's own draft carries (mentions a held message gave back), named with the pills. `null`
|
|
47
48
|
* when there is nothing to hold.
|
|
48
49
|
*/
|
|
49
|
-
export declare function holdComposedSend({ outbox, attachments, carried, quote, send, appUrl, }: {
|
|
50
|
+
export declare function holdComposedSend({ outbox, attachments, carried, quote, send, appUrl, addressedAgents, attachedReferences, }: {
|
|
50
51
|
outbox: ChatOutbox;
|
|
51
52
|
attachments?: UploadedAsset[];
|
|
52
53
|
carried?: readonly ChatOutboxAttachment[];
|
|
53
54
|
quote?: QuoteData | null;
|
|
54
55
|
send: ComposerSend;
|
|
55
56
|
appUrl?: string;
|
|
57
|
+
/** The agents the message names (`message.metadata.addressedAgents`). */
|
|
58
|
+
addressedAgents?: readonly string[];
|
|
59
|
+
/** The references attached to the message (`message.metadata.attachedReferences`). */
|
|
60
|
+
attachedReferences?: readonly AttachableReference[];
|
|
56
61
|
}): ChatOutboxEntry | null;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { withAttachedReferences } from "../references/src/attachable.js";
|
|
1
2
|
import { buildAttachmentMarkdownWithAppUrl } from "./AttachmentContext.js";
|
|
2
3
|
import { escapeCharacterReferences } from "../chat-ui/composer/composer-message.js";
|
|
3
4
|
import { withDeepAgentComposerMarkdown } from "../agent-runtime/src/composer-markdown.js";
|
|
@@ -52,7 +53,9 @@ function holdComposedSend({
|
|
|
52
53
|
carried = [],
|
|
53
54
|
quote,
|
|
54
55
|
send,
|
|
55
|
-
appUrl
|
|
56
|
+
appUrl,
|
|
57
|
+
addressedAgents,
|
|
58
|
+
attachedReferences = []
|
|
56
59
|
}) {
|
|
57
60
|
const composed = buildComposedSend({ attachments, quote, send, appUrl });
|
|
58
61
|
if (!composed) return null;
|
|
@@ -70,12 +73,16 @@ function holdComposedSend({
|
|
|
70
73
|
return outbox.hold({
|
|
71
74
|
text: composed.text,
|
|
72
75
|
composerMarkdown: composed.draftMarkdown,
|
|
73
|
-
metadata:
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
76
|
+
metadata: withAttachedReferences(
|
|
77
|
+
withDeepAgentComposerMarkdown({
|
|
78
|
+
metadata: void 0,
|
|
79
|
+
text: composed.text,
|
|
80
|
+
markdown: composed.draftMarkdown
|
|
81
|
+
}),
|
|
82
|
+
attachedReferences
|
|
83
|
+
),
|
|
84
|
+
attachments: [...named.values()],
|
|
85
|
+
...addressedAgents && { addressedAgents }
|
|
79
86
|
});
|
|
80
87
|
}
|
|
81
88
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-composed-message.js","sources":["../../src/composer/build-composed-message.ts"],"sourcesContent":["import {\n type ChatOutbox,\n type ChatOutboxAttachment,\n type ChatOutboxEntry,\n withDeepAgentComposerMarkdown,\n} from '@athenaintel/agent-runtime';\nimport type { UploadedAsset } from './useFileUpload';\nimport type { QuoteData } from './QuoteContext';\nimport { buildAttachmentMarkdownWithAppUrl } from './AttachmentContext';\nimport {\n type ComposerSend,\n escapeCharacterReferences,\n} from '../chat-ui/composer/composer-message';\n\n/**\n * Assembles a composed message from attachments, a quote, and user text.\n * Used by both the TipTap Enter-key submit and the send-button click handler\n * to avoid duplicating the message-assembly logic.\n *\n * Returns an empty string if all inputs are empty.\n */\nexport function buildComposedMessage(opts: {\n attachments?: UploadedAsset[];\n quote?: QuoteData | null;\n userText?: string;\n appUrl?: string;\n}): string {\n const parts: string[] = [];\n\n if (opts.attachments && opts.attachments.length > 0) {\n const attachmentMd = buildAttachmentMarkdownWithAppUrl({\n attachments: opts.attachments,\n appUrl: opts.appUrl,\n });\n if (attachmentMd) parts.push(attachmentMd);\n }\n\n if (opts.quote) {\n const quotedLines = opts.quote.text.split('\\n').map((l) => `> ${l}`).join('\\n');\n const sourceLabel = opts.quote.sourceTitle\n ? `From \"${opts.quote.sourceTitle}\"`\n : opts.quote.sourceRole === 'assistant'\n ? 'Quoting assistant'\n : 'Quoting';\n parts.push(`${sourceLabel}:\\n${quotedLines}`);\n }\n\n const trimmed = opts.userText?.trim();\n if (trimmed) parts.push(trimmed);\n\n return parts.join('\\n\\n');\n}\n\n/**\n * The composed message a send delivers and the draft it came from: the same\n * attachments and quote around the editor's text as typed in one, and around\n * the editor's draft in the other (`ComposerSend`). `null` when there is\n * nothing to send.\n *\n * The quote and the attachment titles are text the person did not type in\n * the editor, and the message carries them as they are. The draft writes an\n * `&` in them that starts a character reference as `&`, as the composer's\n * draft does for typed text, so it reads back as the message and stays a draft\n * of the message's own text (`isComposerMarkdownOfText`, which agora applies\n * too): a quoted `<` would otherwise read as `<` in the draft and the\n * message would lose its composer markdown.\n */\nexport function buildComposedSend({\n attachments,\n quote,\n send,\n appUrl,\n}: {\n attachments?: UploadedAsset[];\n quote?: QuoteData | null;\n send: ComposerSend;\n appUrl?: string;\n}): ComposerSend | null {\n const text = buildComposedMessage({ attachments, quote, userText: send.text, appUrl });\n if (!text) return null;\n const draftMarkdown = buildComposedMessage({\n attachments: attachments?.map((attachment) => ({\n ...attachment,\n title: escapeCharacterReferences(attachment.title),\n })),\n quote: quote && {\n ...quote,\n text: escapeCharacterReferences(quote.text),\n ...(quote.sourceTitle !== undefined && {\n sourceTitle: escapeCharacterReferences(quote.sourceTitle),\n }),\n },\n userText: send.draftMarkdown,\n appUrl,\n });\n return { text, draftMarkdown };\n}\n\n/**\n * Holds a composed message in the chat outbox while sends are on hold (Athena can't be reached, or\n * earlier messages still wait): the uploaded attachments and the quote around the editor's text,\n * exactly as {@link buildComposedSend} would send them, so it goes with them once Athena is back.\n * The attachments are files already in Athena (an upload that finished before the drop); they are\n * named on the held message so the outbox asks Athena, right before it goes, that each can still\n * be opened. Cancel or Edit gives back the composed draft: the attachments as mentions in the\n * editor, the quote as quoted lines, nothing lost. `carried` are files already in Athena the\n * editor's own draft carries (mentions a held message gave back), named with the pills. `null`\n * when there is nothing to hold.\n */\nexport function holdComposedSend({\n outbox,\n attachments,\n carried = [],\n quote,\n send,\n appUrl,\n}: {\n outbox: ChatOutbox;\n attachments?: UploadedAsset[];\n carried?: readonly ChatOutboxAttachment[];\n quote?: QuoteData | null;\n send: ComposerSend;\n appUrl?: string;\n}): ChatOutboxEntry | null {\n const composed = buildComposedSend({ attachments, quote, send, appUrl });\n if (!composed) return null;\n const named = new Map<string, ChatOutboxAttachment>();\n for (const attachment of attachments ?? []) {\n named.set(attachment.id, {\n assetId: attachment.id,\n title: attachment.title,\n ...(attachment.mediaType && { mediaType: attachment.mediaType }),\n });\n }\n for (const attachment of carried) {\n if (!named.has(attachment.assetId)) named.set(attachment.assetId, attachment);\n }\n return outbox.hold({\n text: composed.text,\n composerMarkdown: composed.draftMarkdown,\n metadata: withDeepAgentComposerMarkdown({\n
|
|
1
|
+
{"version":3,"file":"build-composed-message.js","sources":["../../src/composer/build-composed-message.ts"],"sourcesContent":["import {\n type ChatOutbox,\n type ChatOutboxAttachment,\n type ChatOutboxEntry,\n withDeepAgentComposerMarkdown,\n} from '@athenaintel/agent-runtime';\nimport {\n type AttachableReference,\n withAttachedReferences,\n} from '@athenaintel/references/attachable';\nimport type { UploadedAsset } from './useFileUpload';\nimport type { QuoteData } from './QuoteContext';\nimport { buildAttachmentMarkdownWithAppUrl } from './AttachmentContext';\nimport {\n type ComposerSend,\n escapeCharacterReferences,\n} from '../chat-ui/composer/composer-message';\n\n/**\n * Assembles a composed message from attachments, a quote, and user text.\n * Used by both the TipTap Enter-key submit and the send-button click handler\n * to avoid duplicating the message-assembly logic.\n *\n * Returns an empty string if all inputs are empty.\n */\nexport function buildComposedMessage(opts: {\n attachments?: UploadedAsset[];\n quote?: QuoteData | null;\n userText?: string;\n appUrl?: string;\n}): string {\n const parts: string[] = [];\n\n if (opts.attachments && opts.attachments.length > 0) {\n const attachmentMd = buildAttachmentMarkdownWithAppUrl({\n attachments: opts.attachments,\n appUrl: opts.appUrl,\n });\n if (attachmentMd) parts.push(attachmentMd);\n }\n\n if (opts.quote) {\n const quotedLines = opts.quote.text.split('\\n').map((l) => `> ${l}`).join('\\n');\n const sourceLabel = opts.quote.sourceTitle\n ? `From \"${opts.quote.sourceTitle}\"`\n : opts.quote.sourceRole === 'assistant'\n ? 'Quoting assistant'\n : 'Quoting';\n parts.push(`${sourceLabel}:\\n${quotedLines}`);\n }\n\n const trimmed = opts.userText?.trim();\n if (trimmed) parts.push(trimmed);\n\n return parts.join('\\n\\n');\n}\n\n/**\n * The composed message a send delivers and the draft it came from: the same\n * attachments and quote around the editor's text as typed in one, and around\n * the editor's draft in the other (`ComposerSend`). `null` when there is\n * nothing to send.\n *\n * The quote and the attachment titles are text the person did not type in\n * the editor, and the message carries them as they are. The draft writes an\n * `&` in them that starts a character reference as `&`, as the composer's\n * draft does for typed text, so it reads back as the message and stays a draft\n * of the message's own text (`isComposerMarkdownOfText`, which agora applies\n * too): a quoted `<` would otherwise read as `<` in the draft and the\n * message would lose its composer markdown.\n */\nexport function buildComposedSend({\n attachments,\n quote,\n send,\n appUrl,\n}: {\n attachments?: UploadedAsset[];\n quote?: QuoteData | null;\n send: ComposerSend;\n appUrl?: string;\n}): ComposerSend | null {\n const text = buildComposedMessage({ attachments, quote, userText: send.text, appUrl });\n if (!text) return null;\n const draftMarkdown = buildComposedMessage({\n attachments: attachments?.map((attachment) => ({\n ...attachment,\n title: escapeCharacterReferences(attachment.title),\n })),\n quote: quote && {\n ...quote,\n text: escapeCharacterReferences(quote.text),\n ...(quote.sourceTitle !== undefined && {\n sourceTitle: escapeCharacterReferences(quote.sourceTitle),\n }),\n },\n userText: send.draftMarkdown,\n appUrl,\n });\n return { text, draftMarkdown };\n}\n\n/**\n * Holds a composed message in the chat outbox while sends are on hold (Athena can't be reached, or\n * earlier messages still wait): the uploaded attachments and the quote around the editor's text,\n * exactly as {@link buildComposedSend} would send them, so it goes with them once Athena is back.\n * The attachments are files already in Athena (an upload that finished before the drop); they are\n * named on the held message so the outbox asks Athena, right before it goes, that each can still\n * be opened. Cancel or Edit gives back the composed draft: the attachments as mentions in the\n * editor, the quote as quoted lines, nothing lost. `carried` are files already in Athena the\n * editor's own draft carries (mentions a held message gave back), named with the pills. `null`\n * when there is nothing to hold.\n */\nexport function holdComposedSend({\n outbox,\n attachments,\n carried = [],\n quote,\n send,\n appUrl,\n addressedAgents,\n attachedReferences = [],\n}: {\n outbox: ChatOutbox;\n attachments?: UploadedAsset[];\n carried?: readonly ChatOutboxAttachment[];\n quote?: QuoteData | null;\n send: ComposerSend;\n appUrl?: string;\n /** The agents the message names (`message.metadata.addressedAgents`). */\n addressedAgents?: readonly string[];\n /** The references attached to the message (`message.metadata.attachedReferences`). */\n attachedReferences?: readonly AttachableReference[];\n}): ChatOutboxEntry | null {\n const composed = buildComposedSend({ attachments, quote, send, appUrl });\n if (!composed) return null;\n const named = new Map<string, ChatOutboxAttachment>();\n for (const attachment of attachments ?? []) {\n named.set(attachment.id, {\n assetId: attachment.id,\n title: attachment.title,\n ...(attachment.mediaType && { mediaType: attachment.mediaType }),\n });\n }\n for (const attachment of carried) {\n if (!named.has(attachment.assetId)) named.set(attachment.assetId, attachment);\n }\n return outbox.hold({\n text: composed.text,\n composerMarkdown: composed.draftMarkdown,\n metadata: withAttachedReferences(\n withDeepAgentComposerMarkdown({\n metadata: undefined,\n text: composed.text,\n markdown: composed.draftMarkdown,\n }),\n attachedReferences,\n ),\n attachments: [...named.values()],\n ...(addressedAgents && { addressedAgents }),\n });\n}\n"],"names":[],"mappings":";;;;AAyBO,SAAS,qBAAqB,MAK1B;;AACT,QAAM,QAAkB,CAAA;AAExB,MAAI,KAAK,eAAe,KAAK,YAAY,SAAS,GAAG;AACnD,UAAM,eAAe,kCAAkC;AAAA,MACrD,aAAa,KAAK;AAAA,MAClB,QAAQ,KAAK;AAAA,IAAA,CACd;AACD,QAAI,aAAc,OAAM,KAAK,YAAY;AAAA,EAC3C;AAEA,MAAI,KAAK,OAAO;AACd,UAAM,cAAc,KAAK,MAAM,KAAK,MAAM,IAAI,EAAE,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI;AAC9E,UAAM,cAAc,KAAK,MAAM,cAC3B,SAAS,KAAK,MAAM,WAAW,MAC/B,KAAK,MAAM,eAAe,cACxB,sBACA;AACN,UAAM,KAAK,GAAG,WAAW;AAAA,EAAM,WAAW,EAAE;AAAA,EAC9C;AAEA,QAAM,WAAU,UAAK,aAAL,mBAAe;AAC/B,MAAI,QAAS,OAAM,KAAK,OAAO;AAE/B,SAAO,MAAM,KAAK,MAAM;AAC1B;AAgBO,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAKwB;AACtB,QAAM,OAAO,qBAAqB,EAAE,aAAa,OAAO,UAAU,KAAK,MAAM,QAAQ;AACrF,MAAI,CAAC,KAAM,QAAO;AAClB,QAAM,gBAAgB,qBAAqB;AAAA,IACzC,aAAa,2CAAa,IAAI,CAAC,gBAAgB;AAAA,MAC7C,GAAG;AAAA,MACH,OAAO,0BAA0B,WAAW,KAAK;AAAA,IAAA;AAAA,IAEnD,OAAO,SAAS;AAAA,MACd,GAAG;AAAA,MACH,MAAM,0BAA0B,MAAM,IAAI;AAAA,MAC1C,GAAI,MAAM,gBAAgB,UAAa;AAAA,QACrC,aAAa,0BAA0B,MAAM,WAAW;AAAA,MAAA;AAAA,IAC1D;AAAA,IAEF,UAAU,KAAK;AAAA,IACf;AAAA,EAAA,CACD;AACD,SAAO,EAAE,MAAM,cAAA;AACjB;AAaO,SAAS,iBAAiB;AAAA,EAC/B;AAAA,EACA;AAAA,EACA,UAAU,CAAA;AAAA,EACV;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,qBAAqB,CAAA;AACvB,GAW2B;AACzB,QAAM,WAAW,kBAAkB,EAAE,aAAa,OAAO,MAAM,QAAQ;AACvE,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,4BAAY,IAAA;AAClB,aAAW,cAAc,eAAe,IAAI;AAC1C,UAAM,IAAI,WAAW,IAAI;AAAA,MACvB,SAAS,WAAW;AAAA,MACpB,OAAO,WAAW;AAAA,MAClB,GAAI,WAAW,aAAa,EAAE,WAAW,WAAW,UAAA;AAAA,IAAU,CAC/D;AAAA,EACH;AACA,aAAW,cAAc,SAAS;AAChC,QAAI,CAAC,MAAM,IAAI,WAAW,OAAO,EAAG,OAAM,IAAI,WAAW,SAAS,UAAU;AAAA,EAC9E;AACA,SAAO,OAAO,KAAK;AAAA,IACjB,MAAM,SAAS;AAAA,IACf,kBAAkB,SAAS;AAAA,IAC3B,UAAU;AAAA,MACR,8BAA8B;AAAA,QAC5B,UAAU;AAAA,QACV,MAAM,SAAS;AAAA,QACf,UAAU,SAAS;AAAA,MAAA,CACpB;AAAA,MACD;AAAA,IAAA;AAAA,IAEF,aAAa,CAAC,GAAG,MAAM,QAAQ;AAAA,IAC/B,GAAI,mBAAmB,EAAE,gBAAA;AAAA,EAAgB,CAC1C;AACH;"}
|
|
@@ -6,6 +6,7 @@ const athenaDiagnostics = require("../diagnostics/athena-diagnostics.cjs");
|
|
|
6
6
|
const errors = require("../diagnostics/errors.cjs");
|
|
7
7
|
const statewireSessionLane = require("../runtime/statewire-session-lane.cjs");
|
|
8
8
|
const statewireThreadList = require("../threads/statewire-thread-list.cjs");
|
|
9
|
+
const runSend = require("../agent-runtime/src/run-send.cjs");
|
|
9
10
|
function createComposerHandoffStore() {
|
|
10
11
|
return {
|
|
11
12
|
pending: [],
|
|
@@ -76,7 +77,7 @@ function applyComposerWrite({
|
|
|
76
77
|
store,
|
|
77
78
|
write
|
|
78
79
|
}) {
|
|
79
|
-
var _a;
|
|
80
|
+
var _a, _b;
|
|
80
81
|
const current = target.composer.getState().text ?? "";
|
|
81
82
|
const next = mergeComposerDraft({ current, write });
|
|
82
83
|
target.composer.setText(next);
|
|
@@ -89,7 +90,10 @@ function applyComposerWrite({
|
|
|
89
90
|
data: { phase: "applied", send: write.send, focus: write.focus, chars: next.length }
|
|
90
91
|
});
|
|
91
92
|
if (write.send) {
|
|
92
|
-
|
|
93
|
+
const isRunning = ((_b = target.thread) == null ? void 0 : _b.call(target).getState().isRunning) ?? false;
|
|
94
|
+
return Promise.resolve(target.composer.send(runSend.autoComposerSendOptions(isRunning))).then(
|
|
95
|
+
() => void 0
|
|
96
|
+
);
|
|
93
97
|
}
|
|
94
98
|
return void 0;
|
|
95
99
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"composer-handoff.cjs","sources":["../../src/composer/composer-handoff.ts"],"sourcesContent":["/**\n * Composer handoff: writes to the chat composer from host UI that lives\n * outside `<AthenaChat>` (a sidebar, an agenda card, a workflow button).\n *\n * Two problems it solves for `useAppendToComposer` / `useSendMessage`:\n *\n * 1. A write before the chat is ready is lost. While the thread list is still\n * resolving the active thread, or the thread's history is still loading,\n * the composer the hooks write to belongs to a mount that is about to be\n * replaced (thread-list mode keys the statewire subtree by thread), and\n * the draft goes with it. The store below lives ABOVE that mount, so a\n * write made too early waits here and the ready mount drains it.\n * 2. A prefilled draft should put the caret after the text so the user can\n * keep typing or dictating. The Tiptap editor mirrors runtime text on a\n * later tick; the `focusOnNextMirror` flag asks it to focus at the end\n * right after that mirror lands, instead of the host guessing a delay.\n *\n * Every queued write is bound to the statewire thread it was made for and\n * drains only into that thread's mount; a thread switch, an identity change\n * or a provider unmount drops what waits with a `composer_write_dropped`\n * error, never into another user's or another thread's composer.\n */\nimport { createContext, useCallback, useContext } from 'react';\nimport { useAuiState } from '@assistant-ui/react';\nimport type { ChatOutboxAttachment } from '@athenaintel/agent-runtime';\nimport { athenaDiagnostics } from '../diagnostics/athena-diagnostics';\nimport { AthenaSdkError } from '../diagnostics/errors';\nimport { useStatewireSessionLanePending } from '../runtime/statewire-session-lane';\nimport { useAthenaStatewireThreadList } from '../threads/statewire-thread-list';\n\n/** The slice of the assistant-ui client the handoff writes to. */\nexport interface ComposerTarget {\n composer: {\n getState: () => { text: string };\n setText: (text: string) => void;\n send: (options?: { steer?: boolean }) => unknown;\n };\n}\n\nexport interface ComposerWrite {\n text: string;\n /** Replace the draft instead of appending on a new line. */\n replace: boolean;\n /** Submit right after writing. */\n send: boolean;\n /** Put the caret at the end of the draft once the editor shows it. */\n focus: boolean;\n /** The statewire thread the write was made for; it drains only into that thread's mount. */\n threadId: string | null;\n /** Settled once the write has been applied (and, for `send`, with the send's outcome). */\n resolve?: (outcome: Promise<void> | void) => void;\n /** Settled with `composer_write_dropped` when the write can no longer land. */\n reject?: (error: AthenaSdkError) => void;\n}\n\nexport interface ComposerHandoffStore {\n /** Writes waiting for a ready composer, oldest first. Adjacent plain appends fold together. */\n pending: ComposerWrite[];\n /** Set by a `focus` write; the editor consumes it after mirroring the draft. */\n focusOnNextMirror: boolean;\n /** Registered by the mounted editor: place the caret at the end of the draft. */\n focusEnd: (() => void) | null;\n /** Set by `useFocusComposer` before the editor mounted; the editor consumes it when it does. */\n focusOnMount: boolean;\n /**\n * Per thread, the attachments of messages the chat outbox gave back to the composer (Cancel, or\n * Edit on one that couldn't be sent): files already in Athena, back in the draft as mentions. A\n * message held again from that draft names those still in it, so the outbox asks Athena about\n * them again before it goes ({@link rememberRestoredAttachments}, {@link takeRestoredAttachments}).\n */\n restoredAttachments?: Map<string, ChatOutboxAttachment[]>;\n}\n\nexport function createComposerHandoffStore(): ComposerHandoffStore {\n return {\n pending: [],\n focusOnNextMirror: false,\n focusEnd: null,\n focusOnMount: false,\n restoredAttachments: new Map(),\n };\n}\n\n/** A held message given back to `threadId`'s composer: remember the attachments it carried. */\nexport function rememberRestoredAttachments({\n store,\n threadId,\n attachments,\n}: {\n store: ComposerHandoffStore;\n threadId: string;\n attachments: readonly ChatOutboxAttachment[];\n}): void {\n if (attachments.length === 0) return;\n store.restoredAttachments ??= new Map();\n const kept = store.restoredAttachments.get(threadId) ?? [];\n const known = new Set(kept.map((attachment) => attachment.assetId));\n store.restoredAttachments.set(threadId, [\n ...kept,\n ...attachments.filter((attachment) => !known.has(attachment.assetId)),\n ]);\n}\n\n/**\n * The remembered attachments of `threadId`'s draft whose mentions it still holds, for the message\n * leaving it now; the composer forgets them all (sent, held again, or removed from the draft).\n */\nexport function takeRestoredAttachments({\n store,\n threadId,\n assetIdsInDraft,\n}: {\n store: ComposerHandoffStore | null;\n threadId: string;\n assetIdsInDraft: ReadonlySet<string>;\n}): ChatOutboxAttachment[] {\n const kept = store?.restoredAttachments?.get(threadId);\n if (!kept) return [];\n store?.restoredAttachments?.delete(threadId);\n return kept.filter((attachment) => assetIdsInDraft.has(attachment.assetId));\n}\n\nexport const ComposerHandoffContext = createContext<ComposerHandoffStore | null>(null);\n\n/** The provider's handoff store, or null outside `AthenaProvider`. */\nexport function useComposerHandoffStore(): ComposerHandoffStore | null {\n return useContext(ComposerHandoffContext);\n}\n\n/**\n * Puts the caret at the end of the composer's draft and leaves the draft as it is; asked before the\n * editor has mounted, it focuses the editor as it mounts. For a host that shows the chat again and\n * wants typing to land in it (a launcher window a shortcut brings back).\n */\nexport function useFocusComposer(): () => void {\n const store = useComposerHandoffStore();\n return useCallback(() => {\n if (store) focusComposer({ store });\n }, [store]);\n}\n\n/** The caret to the end of the draft now, or, with no editor mounted yet, as one mounts. */\nexport function focusComposer({ store }: { store: ComposerHandoffStore }): void {\n if (store.focusEnd) store.focusEnd();\n else store.focusOnMount = true;\n}\n\n/**\n * Whether a composer write lands now: in thread-list mode the list has\n * resolved which thread is active, that thread's history has loaded, and the\n * chat's session lane is known (the sign-in provider above has resolved who is\n * signed in; see `StatewireSessionLane`). Until then the composer the hooks\n * write to is the one of a mount that is about to be replaced, and the draft\n * goes with it, or a send would go into a parked lane that refuses it unsent.\n *\n * Deliberately not the socket status: a never-started chat sits in\n * `standby` until its first send and must still take a prefill.\n */\nexport function useComposerReady(): boolean {\n const list = useAthenaStatewireThreadList();\n const threadLoading = useAuiState((s) => s.optional.thread?.isLoading ?? false);\n const lanePending = useStatewireSessionLanePending();\n return !(list?.isLoading ?? false) && !threadLoading && !lanePending;\n}\n\n/** The draft after `write`: `replace` (or an empty draft) takes the text as is. */\nexport function mergeComposerDraft({\n current,\n write,\n}: {\n current: string;\n write: Pick<ComposerWrite, 'text' | 'replace'>;\n}): string {\n if (write.replace || !current) return write.text;\n return `${current}\\n${write.text}`;\n}\n\n/**\n * Write into the live composer. Returns the send's outcome for a `send`\n * write so callers can await it.\n */\nexport function applyComposerWrite({\n target,\n store,\n write,\n}: {\n target: ComposerTarget;\n store: ComposerHandoffStore | null;\n write: ComposerWrite;\n}): Promise<void> | void {\n const current = target.composer.getState().text ?? '';\n const next = mergeComposerDraft({ current, write });\n target.composer.setText(next);\n if (write.focus && store) {\n // An unchanged draft never re-mirrors, so focus at once; otherwise the\n // editor focuses itself right after it has shown the new text.\n if (next === current) store.focusEnd?.();\n else store.focusOnNextMirror = true;\n }\n athenaDiagnostics.emit('composer.handoff', {\n level: 'debug',\n data: { phase: 'applied', send: write.send, focus: write.focus, chars: next.length },\n });\n if (write.send) {\n return Promise.resolve(target.composer.send({ steer: false })).then(() => undefined);\n }\n return undefined;\n}\n\n/**\n * Hold a write until the composer is ready. Writes keep their order; a plain\n * append folds into a directly preceding plain append for the same thread\n * (one draft, not two), while a replace or a send is kept as its own step so\n * no message is lost and every send settles on its own.\n */\nexport function queueComposerWrite({\n store,\n write,\n}: {\n store: ComposerHandoffStore;\n write: ComposerWrite;\n}): void {\n const last = store.pending[store.pending.length - 1];\n const foldable =\n last !== undefined &&\n !last.send &&\n !write.send &&\n !write.replace &&\n last.threadId === write.threadId &&\n last.resolve === undefined &&\n write.resolve === undefined;\n if (foldable) {\n last.text = mergeComposerDraft({ current: last.text, write });\n last.focus = last.focus || write.focus;\n } else {\n store.pending.push(write);\n }\n athenaDiagnostics.emit('composer.handoff', {\n level: 'debug',\n data: { phase: 'deferred', send: write.send, focus: write.focus, queued: store.pending.length },\n });\n}\n\nfunction dropWrite({ write, reason }: { write: ComposerWrite; reason: string }): void {\n const error = new AthenaSdkError({\n code: 'composer_write_dropped',\n message: `A composer ${write.send ? 'send' : 'draft'} queued before the chat was ready was dropped: ${reason}.`,\n hint: 'Make the write again from the chat that is active now.',\n context: { threadId: write.threadId, send: write.send },\n });\n athenaDiagnostics.emit('composer.handoff', {\n level: 'warn',\n error,\n data: { phase: 'dropped', send: write.send, reason, threadId: write.threadId },\n });\n write.reject?.(error);\n}\n\n/**\n * Deliver the pending writes, in order, into a now-ready composer. A write\n * made for another thread is dropped (rejected), never applied here.\n */\nexport function drainComposerHandoff({\n store,\n target,\n threadId,\n}: {\n store: ComposerHandoffStore;\n target: ComposerTarget;\n /** The statewire thread of the mount that is draining. */\n threadId: string | null;\n}): void {\n const writes = store.pending;\n if (writes.length === 0) return;\n store.pending = [];\n for (const write of writes) {\n if (write.threadId !== null && threadId !== null && write.threadId !== threadId) {\n dropWrite({ write, reason: `it was made for thread ${write.threadId}, thread ${threadId} is active` });\n continue;\n }\n const outcome = applyComposerWrite({ target, store, write });\n write.resolve?.(outcome);\n }\n}\n\n/** Drop every pending write (identity changed, provider unmounted). */\nexport function clearComposerHandoff({\n store,\n reason,\n}: {\n store: ComposerHandoffStore;\n reason: string;\n}): void {\n // Another identity, or no provider: the attachments given back belong to drafts that are gone.\n store.restoredAttachments?.clear();\n const writes = store.pending;\n if (writes.length === 0) return;\n store.pending = [];\n for (const write of writes) dropWrite({ write, reason });\n}\n"],"names":["createContext","useContext","useCallback","useAthenaStatewireThreadList","useAuiState","useStatewireSessionLanePending","athenaDiagnostics","AthenaSdkError"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"composer-handoff.cjs","sources":["../../src/composer/composer-handoff.ts"],"sourcesContent":["/**\n * Composer handoff: writes to the chat composer from host UI that lives\n * outside `<AthenaChat>` (a sidebar, an agenda card, a workflow button).\n *\n * Two problems it solves for `useAppendToComposer` / `useSendMessage`:\n *\n * 1. A write before the chat is ready is lost. While the thread list is still\n * resolving the active thread, or the thread's history is still loading,\n * the composer the hooks write to belongs to a mount that is about to be\n * replaced (thread-list mode keys the statewire subtree by thread), and\n * the draft goes with it. The store below lives ABOVE that mount, so a\n * write made too early waits here and the ready mount drains it.\n * 2. A prefilled draft should put the caret after the text so the user can\n * keep typing or dictating. The Tiptap editor mirrors runtime text on a\n * later tick; the `focusOnNextMirror` flag asks it to focus at the end\n * right after that mirror lands, instead of the host guessing a delay.\n *\n * Every queued write is bound to the statewire thread it was made for and\n * drains only into that thread's mount; a thread switch, an identity change\n * or a provider unmount drops what waits with a `composer_write_dropped`\n * error, never into another user's or another thread's composer.\n */\nimport { createContext, useCallback, useContext } from 'react';\nimport { useAuiState } from '@assistant-ui/react';\nimport { autoComposerSendOptions, type ChatOutboxAttachment } from '@athenaintel/agent-runtime';\nimport { athenaDiagnostics } from '../diagnostics/athena-diagnostics';\nimport { AthenaSdkError } from '../diagnostics/errors';\nimport { useStatewireSessionLanePending } from '../runtime/statewire-session-lane';\nimport { useAthenaStatewireThreadList } from '../threads/statewire-thread-list';\n\n/** The slice of the assistant-ui client the handoff writes to. */\nexport interface ComposerTarget {\n composer: {\n getState: () => { text: string };\n setText: (text: string) => void;\n send: (options?: { steer?: boolean }) => unknown;\n };\n /** The thread the composer sends into; its running state picks the `auto` send. */\n thread?: () => { getState: () => { isRunning: boolean } };\n}\n\nexport interface ComposerWrite {\n text: string;\n /** Replace the draft instead of appending on a new line. */\n replace: boolean;\n /** Submit right after writing. */\n send: boolean;\n /** Put the caret at the end of the draft once the editor shows it. */\n focus: boolean;\n /** The statewire thread the write was made for; it drains only into that thread's mount. */\n threadId: string | null;\n /** Settled once the write has been applied (and, for `send`, with the send's outcome). */\n resolve?: (outcome: Promise<void> | void) => void;\n /** Settled with `composer_write_dropped` when the write can no longer land. */\n reject?: (error: AthenaSdkError) => void;\n}\n\nexport interface ComposerHandoffStore {\n /** Writes waiting for a ready composer, oldest first. Adjacent plain appends fold together. */\n pending: ComposerWrite[];\n /** Set by a `focus` write; the editor consumes it after mirroring the draft. */\n focusOnNextMirror: boolean;\n /** Registered by the mounted editor: place the caret at the end of the draft. */\n focusEnd: (() => void) | null;\n /** Set by `useFocusComposer` before the editor mounted; the editor consumes it when it does. */\n focusOnMount: boolean;\n /**\n * Per thread, the attachments of messages the chat outbox gave back to the composer (Cancel, or\n * Edit on one that couldn't be sent): files already in Athena, back in the draft as mentions. A\n * message held again from that draft names those still in it, so the outbox asks Athena about\n * them again before it goes ({@link rememberRestoredAttachments}, {@link takeRestoredAttachments}).\n */\n restoredAttachments?: Map<string, ChatOutboxAttachment[]>;\n}\n\nexport function createComposerHandoffStore(): ComposerHandoffStore {\n return {\n pending: [],\n focusOnNextMirror: false,\n focusEnd: null,\n focusOnMount: false,\n restoredAttachments: new Map(),\n };\n}\n\n/** A held message given back to `threadId`'s composer: remember the attachments it carried. */\nexport function rememberRestoredAttachments({\n store,\n threadId,\n attachments,\n}: {\n store: ComposerHandoffStore;\n threadId: string;\n attachments: readonly ChatOutboxAttachment[];\n}): void {\n if (attachments.length === 0) return;\n store.restoredAttachments ??= new Map();\n const kept = store.restoredAttachments.get(threadId) ?? [];\n const known = new Set(kept.map((attachment) => attachment.assetId));\n store.restoredAttachments.set(threadId, [\n ...kept,\n ...attachments.filter((attachment) => !known.has(attachment.assetId)),\n ]);\n}\n\n/**\n * The remembered attachments of `threadId`'s draft whose mentions it still holds, for the message\n * leaving it now; the composer forgets them all (sent, held again, or removed from the draft).\n */\nexport function takeRestoredAttachments({\n store,\n threadId,\n assetIdsInDraft,\n}: {\n store: ComposerHandoffStore | null;\n threadId: string;\n assetIdsInDraft: ReadonlySet<string>;\n}): ChatOutboxAttachment[] {\n const kept = store?.restoredAttachments?.get(threadId);\n if (!kept) return [];\n store?.restoredAttachments?.delete(threadId);\n return kept.filter((attachment) => assetIdsInDraft.has(attachment.assetId));\n}\n\nexport const ComposerHandoffContext = createContext<ComposerHandoffStore | null>(null);\n\n/** The provider's handoff store, or null outside `AthenaProvider`. */\nexport function useComposerHandoffStore(): ComposerHandoffStore | null {\n return useContext(ComposerHandoffContext);\n}\n\n/**\n * Puts the caret at the end of the composer's draft and leaves the draft as it is; asked before the\n * editor has mounted, it focuses the editor as it mounts. For a host that shows the chat again and\n * wants typing to land in it (a launcher window a shortcut brings back).\n */\nexport function useFocusComposer(): () => void {\n const store = useComposerHandoffStore();\n return useCallback(() => {\n if (store) focusComposer({ store });\n }, [store]);\n}\n\n/** The caret to the end of the draft now, or, with no editor mounted yet, as one mounts. */\nexport function focusComposer({ store }: { store: ComposerHandoffStore }): void {\n if (store.focusEnd) store.focusEnd();\n else store.focusOnMount = true;\n}\n\n/**\n * Whether a composer write lands now: in thread-list mode the list has\n * resolved which thread is active, that thread's history has loaded, and the\n * chat's session lane is known (the sign-in provider above has resolved who is\n * signed in; see `StatewireSessionLane`). Until then the composer the hooks\n * write to is the one of a mount that is about to be replaced, and the draft\n * goes with it, or a send would go into a parked lane that refuses it unsent.\n *\n * Deliberately not the socket status: a never-started chat sits in\n * `standby` until its first send and must still take a prefill.\n */\nexport function useComposerReady(): boolean {\n const list = useAthenaStatewireThreadList();\n const threadLoading = useAuiState((s) => s.optional.thread?.isLoading ?? false);\n const lanePending = useStatewireSessionLanePending();\n return !(list?.isLoading ?? false) && !threadLoading && !lanePending;\n}\n\n/** The draft after `write`: `replace` (or an empty draft) takes the text as is. */\nexport function mergeComposerDraft({\n current,\n write,\n}: {\n current: string;\n write: Pick<ComposerWrite, 'text' | 'replace'>;\n}): string {\n if (write.replace || !current) return write.text;\n return `${current}\\n${write.text}`;\n}\n\n/**\n * Write into the live composer. Returns the send's outcome for a `send`\n * write so callers can await it.\n */\nexport function applyComposerWrite({\n target,\n store,\n write,\n}: {\n target: ComposerTarget;\n store: ComposerHandoffStore | null;\n write: ComposerWrite;\n}): Promise<void> | void {\n const current = target.composer.getState().text ?? '';\n const next = mergeComposerDraft({ current, write });\n target.composer.setText(next);\n if (write.focus && store) {\n // An unchanged draft never re-mirrors, so focus at once; otherwise the\n // editor focuses itself right after it has shown the new text.\n if (next === current) store.focusEnd?.();\n else store.focusOnNextMirror = true;\n }\n athenaDiagnostics.emit('composer.handoff', {\n level: 'debug',\n data: { phase: 'applied', send: write.send, focus: write.focus, chars: next.length },\n });\n if (write.send) {\n const isRunning = target.thread?.().getState().isRunning ?? false;\n return Promise.resolve(target.composer.send(autoComposerSendOptions(isRunning))).then(\n () => undefined,\n );\n }\n return undefined;\n}\n\n/**\n * Hold a write until the composer is ready. Writes keep their order; a plain\n * append folds into a directly preceding plain append for the same thread\n * (one draft, not two), while a replace or a send is kept as its own step so\n * no message is lost and every send settles on its own.\n */\nexport function queueComposerWrite({\n store,\n write,\n}: {\n store: ComposerHandoffStore;\n write: ComposerWrite;\n}): void {\n const last = store.pending[store.pending.length - 1];\n const foldable =\n last !== undefined &&\n !last.send &&\n !write.send &&\n !write.replace &&\n last.threadId === write.threadId &&\n last.resolve === undefined &&\n write.resolve === undefined;\n if (foldable) {\n last.text = mergeComposerDraft({ current: last.text, write });\n last.focus = last.focus || write.focus;\n } else {\n store.pending.push(write);\n }\n athenaDiagnostics.emit('composer.handoff', {\n level: 'debug',\n data: { phase: 'deferred', send: write.send, focus: write.focus, queued: store.pending.length },\n });\n}\n\nfunction dropWrite({ write, reason }: { write: ComposerWrite; reason: string }): void {\n const error = new AthenaSdkError({\n code: 'composer_write_dropped',\n message: `A composer ${write.send ? 'send' : 'draft'} queued before the chat was ready was dropped: ${reason}.`,\n hint: 'Make the write again from the chat that is active now.',\n context: { threadId: write.threadId, send: write.send },\n });\n athenaDiagnostics.emit('composer.handoff', {\n level: 'warn',\n error,\n data: { phase: 'dropped', send: write.send, reason, threadId: write.threadId },\n });\n write.reject?.(error);\n}\n\n/**\n * Deliver the pending writes, in order, into a now-ready composer. A write\n * made for another thread is dropped (rejected), never applied here.\n */\nexport function drainComposerHandoff({\n store,\n target,\n threadId,\n}: {\n store: ComposerHandoffStore;\n target: ComposerTarget;\n /** The statewire thread of the mount that is draining. */\n threadId: string | null;\n}): void {\n const writes = store.pending;\n if (writes.length === 0) return;\n store.pending = [];\n for (const write of writes) {\n if (write.threadId !== null && threadId !== null && write.threadId !== threadId) {\n dropWrite({ write, reason: `it was made for thread ${write.threadId}, thread ${threadId} is active` });\n continue;\n }\n const outcome = applyComposerWrite({ target, store, write });\n write.resolve?.(outcome);\n }\n}\n\n/** Drop every pending write (identity changed, provider unmounted). */\nexport function clearComposerHandoff({\n store,\n reason,\n}: {\n store: ComposerHandoffStore;\n reason: string;\n}): void {\n // Another identity, or no provider: the attachments given back belong to drafts that are gone.\n store.restoredAttachments?.clear();\n const writes = store.pending;\n if (writes.length === 0) return;\n store.pending = [];\n for (const write of writes) dropWrite({ write, reason });\n}\n"],"names":["createContext","useContext","useCallback","useAthenaStatewireThreadList","useAuiState","useStatewireSessionLanePending","athenaDiagnostics","autoComposerSendOptions","AthenaSdkError"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type ChatOutboxAttachment } from '../agent-runtime/src/index';
|
|
2
2
|
import { AthenaSdkError } from '../diagnostics/errors';
|
|
3
3
|
/** The slice of the assistant-ui client the handoff writes to. */
|
|
4
4
|
export interface ComposerTarget {
|
|
@@ -11,6 +11,12 @@ export interface ComposerTarget {
|
|
|
11
11
|
steer?: boolean;
|
|
12
12
|
}) => unknown;
|
|
13
13
|
};
|
|
14
|
+
/** The thread the composer sends into; its running state picks the `auto` send. */
|
|
15
|
+
thread?: () => {
|
|
16
|
+
getState: () => {
|
|
17
|
+
isRunning: boolean;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
14
20
|
}
|
|
15
21
|
export interface ComposerWrite {
|
|
16
22
|
text: string;
|
|
@@ -4,6 +4,7 @@ import { athenaDiagnostics } from "../diagnostics/athena-diagnostics.js";
|
|
|
4
4
|
import { AthenaSdkError } from "../diagnostics/errors.js";
|
|
5
5
|
import { useStatewireSessionLanePending } from "../runtime/statewire-session-lane.js";
|
|
6
6
|
import { useAthenaStatewireThreadList } from "../threads/statewire-thread-list.js";
|
|
7
|
+
import { autoComposerSendOptions } from "../agent-runtime/src/run-send.js";
|
|
7
8
|
function createComposerHandoffStore() {
|
|
8
9
|
return {
|
|
9
10
|
pending: [],
|
|
@@ -74,7 +75,7 @@ function applyComposerWrite({
|
|
|
74
75
|
store,
|
|
75
76
|
write
|
|
76
77
|
}) {
|
|
77
|
-
var _a;
|
|
78
|
+
var _a, _b;
|
|
78
79
|
const current = target.composer.getState().text ?? "";
|
|
79
80
|
const next = mergeComposerDraft({ current, write });
|
|
80
81
|
target.composer.setText(next);
|
|
@@ -87,7 +88,10 @@ function applyComposerWrite({
|
|
|
87
88
|
data: { phase: "applied", send: write.send, focus: write.focus, chars: next.length }
|
|
88
89
|
});
|
|
89
90
|
if (write.send) {
|
|
90
|
-
|
|
91
|
+
const isRunning = ((_b = target.thread) == null ? void 0 : _b.call(target).getState().isRunning) ?? false;
|
|
92
|
+
return Promise.resolve(target.composer.send(autoComposerSendOptions(isRunning))).then(
|
|
93
|
+
() => void 0
|
|
94
|
+
);
|
|
91
95
|
}
|
|
92
96
|
return void 0;
|
|
93
97
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"composer-handoff.js","sources":["../../src/composer/composer-handoff.ts"],"sourcesContent":["/**\n * Composer handoff: writes to the chat composer from host UI that lives\n * outside `<AthenaChat>` (a sidebar, an agenda card, a workflow button).\n *\n * Two problems it solves for `useAppendToComposer` / `useSendMessage`:\n *\n * 1. A write before the chat is ready is lost. While the thread list is still\n * resolving the active thread, or the thread's history is still loading,\n * the composer the hooks write to belongs to a mount that is about to be\n * replaced (thread-list mode keys the statewire subtree by thread), and\n * the draft goes with it. The store below lives ABOVE that mount, so a\n * write made too early waits here and the ready mount drains it.\n * 2. A prefilled draft should put the caret after the text so the user can\n * keep typing or dictating. The Tiptap editor mirrors runtime text on a\n * later tick; the `focusOnNextMirror` flag asks it to focus at the end\n * right after that mirror lands, instead of the host guessing a delay.\n *\n * Every queued write is bound to the statewire thread it was made for and\n * drains only into that thread's mount; a thread switch, an identity change\n * or a provider unmount drops what waits with a `composer_write_dropped`\n * error, never into another user's or another thread's composer.\n */\nimport { createContext, useCallback, useContext } from 'react';\nimport { useAuiState } from '@assistant-ui/react';\nimport type { ChatOutboxAttachment } from '@athenaintel/agent-runtime';\nimport { athenaDiagnostics } from '../diagnostics/athena-diagnostics';\nimport { AthenaSdkError } from '../diagnostics/errors';\nimport { useStatewireSessionLanePending } from '../runtime/statewire-session-lane';\nimport { useAthenaStatewireThreadList } from '../threads/statewire-thread-list';\n\n/** The slice of the assistant-ui client the handoff writes to. */\nexport interface ComposerTarget {\n composer: {\n getState: () => { text: string };\n setText: (text: string) => void;\n send: (options?: { steer?: boolean }) => unknown;\n };\n}\n\nexport interface ComposerWrite {\n text: string;\n /** Replace the draft instead of appending on a new line. */\n replace: boolean;\n /** Submit right after writing. */\n send: boolean;\n /** Put the caret at the end of the draft once the editor shows it. */\n focus: boolean;\n /** The statewire thread the write was made for; it drains only into that thread's mount. */\n threadId: string | null;\n /** Settled once the write has been applied (and, for `send`, with the send's outcome). */\n resolve?: (outcome: Promise<void> | void) => void;\n /** Settled with `composer_write_dropped` when the write can no longer land. */\n reject?: (error: AthenaSdkError) => void;\n}\n\nexport interface ComposerHandoffStore {\n /** Writes waiting for a ready composer, oldest first. Adjacent plain appends fold together. */\n pending: ComposerWrite[];\n /** Set by a `focus` write; the editor consumes it after mirroring the draft. */\n focusOnNextMirror: boolean;\n /** Registered by the mounted editor: place the caret at the end of the draft. */\n focusEnd: (() => void) | null;\n /** Set by `useFocusComposer` before the editor mounted; the editor consumes it when it does. */\n focusOnMount: boolean;\n /**\n * Per thread, the attachments of messages the chat outbox gave back to the composer (Cancel, or\n * Edit on one that couldn't be sent): files already in Athena, back in the draft as mentions. A\n * message held again from that draft names those still in it, so the outbox asks Athena about\n * them again before it goes ({@link rememberRestoredAttachments}, {@link takeRestoredAttachments}).\n */\n restoredAttachments?: Map<string, ChatOutboxAttachment[]>;\n}\n\nexport function createComposerHandoffStore(): ComposerHandoffStore {\n return {\n pending: [],\n focusOnNextMirror: false,\n focusEnd: null,\n focusOnMount: false,\n restoredAttachments: new Map(),\n };\n}\n\n/** A held message given back to `threadId`'s composer: remember the attachments it carried. */\nexport function rememberRestoredAttachments({\n store,\n threadId,\n attachments,\n}: {\n store: ComposerHandoffStore;\n threadId: string;\n attachments: readonly ChatOutboxAttachment[];\n}): void {\n if (attachments.length === 0) return;\n store.restoredAttachments ??= new Map();\n const kept = store.restoredAttachments.get(threadId) ?? [];\n const known = new Set(kept.map((attachment) => attachment.assetId));\n store.restoredAttachments.set(threadId, [\n ...kept,\n ...attachments.filter((attachment) => !known.has(attachment.assetId)),\n ]);\n}\n\n/**\n * The remembered attachments of `threadId`'s draft whose mentions it still holds, for the message\n * leaving it now; the composer forgets them all (sent, held again, or removed from the draft).\n */\nexport function takeRestoredAttachments({\n store,\n threadId,\n assetIdsInDraft,\n}: {\n store: ComposerHandoffStore | null;\n threadId: string;\n assetIdsInDraft: ReadonlySet<string>;\n}): ChatOutboxAttachment[] {\n const kept = store?.restoredAttachments?.get(threadId);\n if (!kept) return [];\n store?.restoredAttachments?.delete(threadId);\n return kept.filter((attachment) => assetIdsInDraft.has(attachment.assetId));\n}\n\nexport const ComposerHandoffContext = createContext<ComposerHandoffStore | null>(null);\n\n/** The provider's handoff store, or null outside `AthenaProvider`. */\nexport function useComposerHandoffStore(): ComposerHandoffStore | null {\n return useContext(ComposerHandoffContext);\n}\n\n/**\n * Puts the caret at the end of the composer's draft and leaves the draft as it is; asked before the\n * editor has mounted, it focuses the editor as it mounts. For a host that shows the chat again and\n * wants typing to land in it (a launcher window a shortcut brings back).\n */\nexport function useFocusComposer(): () => void {\n const store = useComposerHandoffStore();\n return useCallback(() => {\n if (store) focusComposer({ store });\n }, [store]);\n}\n\n/** The caret to the end of the draft now, or, with no editor mounted yet, as one mounts. */\nexport function focusComposer({ store }: { store: ComposerHandoffStore }): void {\n if (store.focusEnd) store.focusEnd();\n else store.focusOnMount = true;\n}\n\n/**\n * Whether a composer write lands now: in thread-list mode the list has\n * resolved which thread is active, that thread's history has loaded, and the\n * chat's session lane is known (the sign-in provider above has resolved who is\n * signed in; see `StatewireSessionLane`). Until then the composer the hooks\n * write to is the one of a mount that is about to be replaced, and the draft\n * goes with it, or a send would go into a parked lane that refuses it unsent.\n *\n * Deliberately not the socket status: a never-started chat sits in\n * `standby` until its first send and must still take a prefill.\n */\nexport function useComposerReady(): boolean {\n const list = useAthenaStatewireThreadList();\n const threadLoading = useAuiState((s) => s.optional.thread?.isLoading ?? false);\n const lanePending = useStatewireSessionLanePending();\n return !(list?.isLoading ?? false) && !threadLoading && !lanePending;\n}\n\n/** The draft after `write`: `replace` (or an empty draft) takes the text as is. */\nexport function mergeComposerDraft({\n current,\n write,\n}: {\n current: string;\n write: Pick<ComposerWrite, 'text' | 'replace'>;\n}): string {\n if (write.replace || !current) return write.text;\n return `${current}\\n${write.text}`;\n}\n\n/**\n * Write into the live composer. Returns the send's outcome for a `send`\n * write so callers can await it.\n */\nexport function applyComposerWrite({\n target,\n store,\n write,\n}: {\n target: ComposerTarget;\n store: ComposerHandoffStore | null;\n write: ComposerWrite;\n}): Promise<void> | void {\n const current = target.composer.getState().text ?? '';\n const next = mergeComposerDraft({ current, write });\n target.composer.setText(next);\n if (write.focus && store) {\n // An unchanged draft never re-mirrors, so focus at once; otherwise the\n // editor focuses itself right after it has shown the new text.\n if (next === current) store.focusEnd?.();\n else store.focusOnNextMirror = true;\n }\n athenaDiagnostics.emit('composer.handoff', {\n level: 'debug',\n data: { phase: 'applied', send: write.send, focus: write.focus, chars: next.length },\n });\n if (write.send) {\n return Promise.resolve(target.composer.send({ steer: false })).then(() => undefined);\n }\n return undefined;\n}\n\n/**\n * Hold a write until the composer is ready. Writes keep their order; a plain\n * append folds into a directly preceding plain append for the same thread\n * (one draft, not two), while a replace or a send is kept as its own step so\n * no message is lost and every send settles on its own.\n */\nexport function queueComposerWrite({\n store,\n write,\n}: {\n store: ComposerHandoffStore;\n write: ComposerWrite;\n}): void {\n const last = store.pending[store.pending.length - 1];\n const foldable =\n last !== undefined &&\n !last.send &&\n !write.send &&\n !write.replace &&\n last.threadId === write.threadId &&\n last.resolve === undefined &&\n write.resolve === undefined;\n if (foldable) {\n last.text = mergeComposerDraft({ current: last.text, write });\n last.focus = last.focus || write.focus;\n } else {\n store.pending.push(write);\n }\n athenaDiagnostics.emit('composer.handoff', {\n level: 'debug',\n data: { phase: 'deferred', send: write.send, focus: write.focus, queued: store.pending.length },\n });\n}\n\nfunction dropWrite({ write, reason }: { write: ComposerWrite; reason: string }): void {\n const error = new AthenaSdkError({\n code: 'composer_write_dropped',\n message: `A composer ${write.send ? 'send' : 'draft'} queued before the chat was ready was dropped: ${reason}.`,\n hint: 'Make the write again from the chat that is active now.',\n context: { threadId: write.threadId, send: write.send },\n });\n athenaDiagnostics.emit('composer.handoff', {\n level: 'warn',\n error,\n data: { phase: 'dropped', send: write.send, reason, threadId: write.threadId },\n });\n write.reject?.(error);\n}\n\n/**\n * Deliver the pending writes, in order, into a now-ready composer. A write\n * made for another thread is dropped (rejected), never applied here.\n */\nexport function drainComposerHandoff({\n store,\n target,\n threadId,\n}: {\n store: ComposerHandoffStore;\n target: ComposerTarget;\n /** The statewire thread of the mount that is draining. */\n threadId: string | null;\n}): void {\n const writes = store.pending;\n if (writes.length === 0) return;\n store.pending = [];\n for (const write of writes) {\n if (write.threadId !== null && threadId !== null && write.threadId !== threadId) {\n dropWrite({ write, reason: `it was made for thread ${write.threadId}, thread ${threadId} is active` });\n continue;\n }\n const outcome = applyComposerWrite({ target, store, write });\n write.resolve?.(outcome);\n }\n}\n\n/** Drop every pending write (identity changed, provider unmounted). */\nexport function clearComposerHandoff({\n store,\n reason,\n}: {\n store: ComposerHandoffStore;\n reason: string;\n}): void {\n // Another identity, or no provider: the attachments given back belong to drafts that are gone.\n store.restoredAttachments?.clear();\n const writes = store.pending;\n if (writes.length === 0) return;\n store.pending = [];\n for (const write of writes) dropWrite({ write, reason });\n}\n"],"names":[],"mappings":";;;;;;AAyEO,SAAS,6BAAmD;AACjE,SAAO;AAAA,IACL,SAAS,CAAA;AAAA,IACT,mBAAmB;AAAA,IACnB,UAAU;AAAA,IACV,cAAc;AAAA,IACd,yCAAyB,IAAA;AAAA,EAAI;AAEjC;AAGO,SAAS,4BAA4B;AAAA,EAC1C;AAAA,EACA;AAAA,EACA;AACF,GAIS;AACP,MAAI,YAAY,WAAW,EAAG;AAC9B,QAAM,wBAAN,MAAM,0CAA4B,IAAA;AAClC,QAAM,OAAO,MAAM,oBAAoB,IAAI,QAAQ,KAAK,CAAA;AACxD,QAAM,QAAQ,IAAI,IAAI,KAAK,IAAI,CAAC,eAAe,WAAW,OAAO,CAAC;AAClE,QAAM,oBAAoB,IAAI,UAAU;AAAA,IACtC,GAAG;AAAA,IACH,GAAG,YAAY,OAAO,CAAC,eAAe,CAAC,MAAM,IAAI,WAAW,OAAO,CAAC;AAAA,EAAA,CACrE;AACH;AAMO,SAAS,wBAAwB;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AACF,GAI2B;;AACzB,QAAM,QAAO,oCAAO,wBAAP,mBAA4B,IAAI;AAC7C,MAAI,CAAC,KAAM,QAAO,CAAA;AAClB,uCAAO,wBAAP,mBAA4B,OAAO;AACnC,SAAO,KAAK,OAAO,CAAC,eAAe,gBAAgB,IAAI,WAAW,OAAO,CAAC;AAC5E;AAEO,MAAM,yBAAyB,cAA2C,IAAI;AAG9E,SAAS,0BAAuD;AACrE,SAAO,WAAW,sBAAsB;AAC1C;AAOO,SAAS,mBAA+B;AAC7C,QAAM,QAAQ,wBAAA;AACd,SAAO,YAAY,MAAM;AACvB,QAAI,MAAO,eAAc,EAAE,OAAO;AAAA,EACpC,GAAG,CAAC,KAAK,CAAC;AACZ;AAGO,SAAS,cAAc,EAAE,SAAgD;AAC9E,MAAI,MAAM,SAAU,OAAM,SAAA;AAAA,aACf,eAAe;AAC5B;AAaO,SAAS,mBAA4B;AAC1C,QAAM,OAAO,6BAAA;AACb,QAAM,gBAAgB,YAAY,CAAC,MAAA;;AAAM,oBAAE,SAAS,WAAX,mBAAmB,cAAa;AAAA,GAAK;AAC9E,QAAM,cAAc,+BAAA;AACpB,SAAO,GAAE,6BAAM,cAAa,UAAU,CAAC,iBAAiB,CAAC;AAC3D;AAGO,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AACF,GAGW;AACT,MAAI,MAAM,WAAW,CAAC,gBAAgB,MAAM;AAC5C,SAAO,GAAG,OAAO;AAAA,EAAK,MAAM,IAAI;AAClC;AAMO,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AAAA,EACA;AACF,GAIyB;;AACvB,QAAM,UAAU,OAAO,SAAS,SAAA,EAAW,QAAQ;AACnD,QAAM,OAAO,mBAAmB,EAAE,SAAS,OAAO;AAClD,SAAO,SAAS,QAAQ,IAAI;AAC5B,MAAI,MAAM,SAAS,OAAO;AAGxB,QAAI,SAAS,QAAS,aAAM,aAAN;AAAA,eACX,oBAAoB;AAAA,EACjC;AACA,oBAAkB,KAAK,oBAAoB;AAAA,IACzC,OAAO;AAAA,IACP,MAAM,EAAE,OAAO,WAAW,MAAM,MAAM,MAAM,OAAO,MAAM,OAAO,OAAO,KAAK,OAAA;AAAA,EAAO,CACpF;AACD,MAAI,MAAM,MAAM;AACd,WAAO,QAAQ,QAAQ,OAAO,SAAS,KAAK,EAAE,OAAO,MAAA,CAAO,CAAC,EAAE,KAAK,MAAM,MAAS;AAAA,EACrF;AACA,SAAO;AACT;AAQO,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AACF,GAGS;AACP,QAAM,OAAO,MAAM,QAAQ,MAAM,QAAQ,SAAS,CAAC;AACnD,QAAM,WACJ,SAAS,UACT,CAAC,KAAK,QACN,CAAC,MAAM,QACP,CAAC,MAAM,WACP,KAAK,aAAa,MAAM,YACxB,KAAK,YAAY,UACjB,MAAM,YAAY;AACpB,MAAI,UAAU;AACZ,SAAK,OAAO,mBAAmB,EAAE,SAAS,KAAK,MAAM,OAAO;AAC5D,SAAK,QAAQ,KAAK,SAAS,MAAM;AAAA,EACnC,OAAO;AACL,UAAM,QAAQ,KAAK,KAAK;AAAA,EAC1B;AACA,oBAAkB,KAAK,oBAAoB;AAAA,IACzC,OAAO;AAAA,IACP,MAAM,EAAE,OAAO,YAAY,MAAM,MAAM,MAAM,OAAO,MAAM,OAAO,QAAQ,MAAM,QAAQ,OAAA;AAAA,EAAO,CAC/F;AACH;AAEA,SAAS,UAAU,EAAE,OAAO,UAA0D;;AACpF,QAAM,QAAQ,IAAI,eAAe;AAAA,IAC/B,MAAM;AAAA,IACN,SAAS,cAAc,MAAM,OAAO,SAAS,OAAO,kDAAkD,MAAM;AAAA,IAC5G,MAAM;AAAA,IACN,SAAS,EAAE,UAAU,MAAM,UAAU,MAAM,MAAM,KAAA;AAAA,EAAK,CACvD;AACD,oBAAkB,KAAK,oBAAoB;AAAA,IACzC,OAAO;AAAA,IACP;AAAA,IACA,MAAM,EAAE,OAAO,WAAW,MAAM,MAAM,MAAM,QAAQ,UAAU,MAAM,SAAA;AAAA,EAAS,CAC9E;AACD,cAAM,WAAN,+BAAe;AACjB;AAMO,SAAS,qBAAqB;AAAA,EACnC;AAAA,EACA;AAAA,EACA;AACF,GAKS;;AACP,QAAM,SAAS,MAAM;AACrB,MAAI,OAAO,WAAW,EAAG;AACzB,QAAM,UAAU,CAAA;AAChB,aAAW,SAAS,QAAQ;AAC1B,QAAI,MAAM,aAAa,QAAQ,aAAa,QAAQ,MAAM,aAAa,UAAU;AAC/E,gBAAU,EAAE,OAAO,QAAQ,0BAA0B,MAAM,QAAQ,YAAY,QAAQ,aAAA,CAAc;AACrG;AAAA,IACF;AACA,UAAM,UAAU,mBAAmB,EAAE,QAAQ,OAAO,OAAO;AAC3D,gBAAM,YAAN,+BAAgB;AAAA,EAClB;AACF;AAGO,SAAS,qBAAqB;AAAA,EACnC;AAAA,EACA;AACF,GAGS;;AAEP,cAAM,wBAAN,mBAA2B;AAC3B,QAAM,SAAS,MAAM;AACrB,MAAI,OAAO,WAAW,EAAG;AACzB,QAAM,UAAU,CAAA;AAChB,aAAW,SAAS,OAAQ,WAAU,EAAE,OAAO,QAAQ;AACzD;"}
|
|
1
|
+
{"version":3,"file":"composer-handoff.js","sources":["../../src/composer/composer-handoff.ts"],"sourcesContent":["/**\n * Composer handoff: writes to the chat composer from host UI that lives\n * outside `<AthenaChat>` (a sidebar, an agenda card, a workflow button).\n *\n * Two problems it solves for `useAppendToComposer` / `useSendMessage`:\n *\n * 1. A write before the chat is ready is lost. While the thread list is still\n * resolving the active thread, or the thread's history is still loading,\n * the composer the hooks write to belongs to a mount that is about to be\n * replaced (thread-list mode keys the statewire subtree by thread), and\n * the draft goes with it. The store below lives ABOVE that mount, so a\n * write made too early waits here and the ready mount drains it.\n * 2. A prefilled draft should put the caret after the text so the user can\n * keep typing or dictating. The Tiptap editor mirrors runtime text on a\n * later tick; the `focusOnNextMirror` flag asks it to focus at the end\n * right after that mirror lands, instead of the host guessing a delay.\n *\n * Every queued write is bound to the statewire thread it was made for and\n * drains only into that thread's mount; a thread switch, an identity change\n * or a provider unmount drops what waits with a `composer_write_dropped`\n * error, never into another user's or another thread's composer.\n */\nimport { createContext, useCallback, useContext } from 'react';\nimport { useAuiState } from '@assistant-ui/react';\nimport { autoComposerSendOptions, type ChatOutboxAttachment } from '@athenaintel/agent-runtime';\nimport { athenaDiagnostics } from '../diagnostics/athena-diagnostics';\nimport { AthenaSdkError } from '../diagnostics/errors';\nimport { useStatewireSessionLanePending } from '../runtime/statewire-session-lane';\nimport { useAthenaStatewireThreadList } from '../threads/statewire-thread-list';\n\n/** The slice of the assistant-ui client the handoff writes to. */\nexport interface ComposerTarget {\n composer: {\n getState: () => { text: string };\n setText: (text: string) => void;\n send: (options?: { steer?: boolean }) => unknown;\n };\n /** The thread the composer sends into; its running state picks the `auto` send. */\n thread?: () => { getState: () => { isRunning: boolean } };\n}\n\nexport interface ComposerWrite {\n text: string;\n /** Replace the draft instead of appending on a new line. */\n replace: boolean;\n /** Submit right after writing. */\n send: boolean;\n /** Put the caret at the end of the draft once the editor shows it. */\n focus: boolean;\n /** The statewire thread the write was made for; it drains only into that thread's mount. */\n threadId: string | null;\n /** Settled once the write has been applied (and, for `send`, with the send's outcome). */\n resolve?: (outcome: Promise<void> | void) => void;\n /** Settled with `composer_write_dropped` when the write can no longer land. */\n reject?: (error: AthenaSdkError) => void;\n}\n\nexport interface ComposerHandoffStore {\n /** Writes waiting for a ready composer, oldest first. Adjacent plain appends fold together. */\n pending: ComposerWrite[];\n /** Set by a `focus` write; the editor consumes it after mirroring the draft. */\n focusOnNextMirror: boolean;\n /** Registered by the mounted editor: place the caret at the end of the draft. */\n focusEnd: (() => void) | null;\n /** Set by `useFocusComposer` before the editor mounted; the editor consumes it when it does. */\n focusOnMount: boolean;\n /**\n * Per thread, the attachments of messages the chat outbox gave back to the composer (Cancel, or\n * Edit on one that couldn't be sent): files already in Athena, back in the draft as mentions. A\n * message held again from that draft names those still in it, so the outbox asks Athena about\n * them again before it goes ({@link rememberRestoredAttachments}, {@link takeRestoredAttachments}).\n */\n restoredAttachments?: Map<string, ChatOutboxAttachment[]>;\n}\n\nexport function createComposerHandoffStore(): ComposerHandoffStore {\n return {\n pending: [],\n focusOnNextMirror: false,\n focusEnd: null,\n focusOnMount: false,\n restoredAttachments: new Map(),\n };\n}\n\n/** A held message given back to `threadId`'s composer: remember the attachments it carried. */\nexport function rememberRestoredAttachments({\n store,\n threadId,\n attachments,\n}: {\n store: ComposerHandoffStore;\n threadId: string;\n attachments: readonly ChatOutboxAttachment[];\n}): void {\n if (attachments.length === 0) return;\n store.restoredAttachments ??= new Map();\n const kept = store.restoredAttachments.get(threadId) ?? [];\n const known = new Set(kept.map((attachment) => attachment.assetId));\n store.restoredAttachments.set(threadId, [\n ...kept,\n ...attachments.filter((attachment) => !known.has(attachment.assetId)),\n ]);\n}\n\n/**\n * The remembered attachments of `threadId`'s draft whose mentions it still holds, for the message\n * leaving it now; the composer forgets them all (sent, held again, or removed from the draft).\n */\nexport function takeRestoredAttachments({\n store,\n threadId,\n assetIdsInDraft,\n}: {\n store: ComposerHandoffStore | null;\n threadId: string;\n assetIdsInDraft: ReadonlySet<string>;\n}): ChatOutboxAttachment[] {\n const kept = store?.restoredAttachments?.get(threadId);\n if (!kept) return [];\n store?.restoredAttachments?.delete(threadId);\n return kept.filter((attachment) => assetIdsInDraft.has(attachment.assetId));\n}\n\nexport const ComposerHandoffContext = createContext<ComposerHandoffStore | null>(null);\n\n/** The provider's handoff store, or null outside `AthenaProvider`. */\nexport function useComposerHandoffStore(): ComposerHandoffStore | null {\n return useContext(ComposerHandoffContext);\n}\n\n/**\n * Puts the caret at the end of the composer's draft and leaves the draft as it is; asked before the\n * editor has mounted, it focuses the editor as it mounts. For a host that shows the chat again and\n * wants typing to land in it (a launcher window a shortcut brings back).\n */\nexport function useFocusComposer(): () => void {\n const store = useComposerHandoffStore();\n return useCallback(() => {\n if (store) focusComposer({ store });\n }, [store]);\n}\n\n/** The caret to the end of the draft now, or, with no editor mounted yet, as one mounts. */\nexport function focusComposer({ store }: { store: ComposerHandoffStore }): void {\n if (store.focusEnd) store.focusEnd();\n else store.focusOnMount = true;\n}\n\n/**\n * Whether a composer write lands now: in thread-list mode the list has\n * resolved which thread is active, that thread's history has loaded, and the\n * chat's session lane is known (the sign-in provider above has resolved who is\n * signed in; see `StatewireSessionLane`). Until then the composer the hooks\n * write to is the one of a mount that is about to be replaced, and the draft\n * goes with it, or a send would go into a parked lane that refuses it unsent.\n *\n * Deliberately not the socket status: a never-started chat sits in\n * `standby` until its first send and must still take a prefill.\n */\nexport function useComposerReady(): boolean {\n const list = useAthenaStatewireThreadList();\n const threadLoading = useAuiState((s) => s.optional.thread?.isLoading ?? false);\n const lanePending = useStatewireSessionLanePending();\n return !(list?.isLoading ?? false) && !threadLoading && !lanePending;\n}\n\n/** The draft after `write`: `replace` (or an empty draft) takes the text as is. */\nexport function mergeComposerDraft({\n current,\n write,\n}: {\n current: string;\n write: Pick<ComposerWrite, 'text' | 'replace'>;\n}): string {\n if (write.replace || !current) return write.text;\n return `${current}\\n${write.text}`;\n}\n\n/**\n * Write into the live composer. Returns the send's outcome for a `send`\n * write so callers can await it.\n */\nexport function applyComposerWrite({\n target,\n store,\n write,\n}: {\n target: ComposerTarget;\n store: ComposerHandoffStore | null;\n write: ComposerWrite;\n}): Promise<void> | void {\n const current = target.composer.getState().text ?? '';\n const next = mergeComposerDraft({ current, write });\n target.composer.setText(next);\n if (write.focus && store) {\n // An unchanged draft never re-mirrors, so focus at once; otherwise the\n // editor focuses itself right after it has shown the new text.\n if (next === current) store.focusEnd?.();\n else store.focusOnNextMirror = true;\n }\n athenaDiagnostics.emit('composer.handoff', {\n level: 'debug',\n data: { phase: 'applied', send: write.send, focus: write.focus, chars: next.length },\n });\n if (write.send) {\n const isRunning = target.thread?.().getState().isRunning ?? false;\n return Promise.resolve(target.composer.send(autoComposerSendOptions(isRunning))).then(\n () => undefined,\n );\n }\n return undefined;\n}\n\n/**\n * Hold a write until the composer is ready. Writes keep their order; a plain\n * append folds into a directly preceding plain append for the same thread\n * (one draft, not two), while a replace or a send is kept as its own step so\n * no message is lost and every send settles on its own.\n */\nexport function queueComposerWrite({\n store,\n write,\n}: {\n store: ComposerHandoffStore;\n write: ComposerWrite;\n}): void {\n const last = store.pending[store.pending.length - 1];\n const foldable =\n last !== undefined &&\n !last.send &&\n !write.send &&\n !write.replace &&\n last.threadId === write.threadId &&\n last.resolve === undefined &&\n write.resolve === undefined;\n if (foldable) {\n last.text = mergeComposerDraft({ current: last.text, write });\n last.focus = last.focus || write.focus;\n } else {\n store.pending.push(write);\n }\n athenaDiagnostics.emit('composer.handoff', {\n level: 'debug',\n data: { phase: 'deferred', send: write.send, focus: write.focus, queued: store.pending.length },\n });\n}\n\nfunction dropWrite({ write, reason }: { write: ComposerWrite; reason: string }): void {\n const error = new AthenaSdkError({\n code: 'composer_write_dropped',\n message: `A composer ${write.send ? 'send' : 'draft'} queued before the chat was ready was dropped: ${reason}.`,\n hint: 'Make the write again from the chat that is active now.',\n context: { threadId: write.threadId, send: write.send },\n });\n athenaDiagnostics.emit('composer.handoff', {\n level: 'warn',\n error,\n data: { phase: 'dropped', send: write.send, reason, threadId: write.threadId },\n });\n write.reject?.(error);\n}\n\n/**\n * Deliver the pending writes, in order, into a now-ready composer. A write\n * made for another thread is dropped (rejected), never applied here.\n */\nexport function drainComposerHandoff({\n store,\n target,\n threadId,\n}: {\n store: ComposerHandoffStore;\n target: ComposerTarget;\n /** The statewire thread of the mount that is draining. */\n threadId: string | null;\n}): void {\n const writes = store.pending;\n if (writes.length === 0) return;\n store.pending = [];\n for (const write of writes) {\n if (write.threadId !== null && threadId !== null && write.threadId !== threadId) {\n dropWrite({ write, reason: `it was made for thread ${write.threadId}, thread ${threadId} is active` });\n continue;\n }\n const outcome = applyComposerWrite({ target, store, write });\n write.resolve?.(outcome);\n }\n}\n\n/** Drop every pending write (identity changed, provider unmounted). */\nexport function clearComposerHandoff({\n store,\n reason,\n}: {\n store: ComposerHandoffStore;\n reason: string;\n}): void {\n // Another identity, or no provider: the attachments given back belong to drafts that are gone.\n store.restoredAttachments?.clear();\n const writes = store.pending;\n if (writes.length === 0) return;\n store.pending = [];\n for (const write of writes) dropWrite({ write, reason });\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const apiClient = require("../chat-ui/mentions/suggestions/data/api-client.cjs");
|
|
4
|
+
const FOLDER_UPLOAD_PATH = "/api/upload/async";
|
|
5
|
+
const FOLDER_UPLOAD_DEADLINE_MS = 15 * 60 * 1e3;
|
|
6
|
+
const FOLDER_UPLOAD_POLL_MIN_MS = 250;
|
|
7
|
+
const FOLDER_UPLOAD_POLL_MAX_MS = 2e3;
|
|
8
|
+
const ASYNC_UPLOAD_TASK_QUERY = `
|
|
9
|
+
query AthenaAsyncUploadTask($taskId: String!) {
|
|
10
|
+
asyncUploadTask(taskId: $taskId) {
|
|
11
|
+
taskId
|
|
12
|
+
status
|
|
13
|
+
requestedCount
|
|
14
|
+
processedCount
|
|
15
|
+
uploadedCount
|
|
16
|
+
failedCount
|
|
17
|
+
message
|
|
18
|
+
results {
|
|
19
|
+
fileIndex
|
|
20
|
+
filename
|
|
21
|
+
status
|
|
22
|
+
message
|
|
23
|
+
assetId
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
`;
|
|
28
|
+
const ENDED = /* @__PURE__ */ new Set(["completed", "failed", "cancelled"]);
|
|
29
|
+
function folderUploadPollDelayMs(attempt) {
|
|
30
|
+
return Math.min(FOLDER_UPLOAD_POLL_MIN_MS * 2 ** attempt, FOLDER_UPLOAD_POLL_MAX_MS);
|
|
31
|
+
}
|
|
32
|
+
function folderUploadForm({
|
|
33
|
+
files,
|
|
34
|
+
parentFolderId
|
|
35
|
+
}) {
|
|
36
|
+
const form = new FormData();
|
|
37
|
+
for (const file of files) form.append("files", file, file.name);
|
|
38
|
+
form.append("parent_folder_id", parentFolderId);
|
|
39
|
+
return form;
|
|
40
|
+
}
|
|
41
|
+
function taskIdOf(body) {
|
|
42
|
+
const camel = Reflect.get(Object(body), "taskId");
|
|
43
|
+
if (typeof camel === "string" && camel) return camel;
|
|
44
|
+
const snake = Reflect.get(Object(body), "task_id");
|
|
45
|
+
return typeof snake === "string" && snake ? snake : null;
|
|
46
|
+
}
|
|
47
|
+
async function refusalDetail(response) {
|
|
48
|
+
const body = await response.json().catch(() => null);
|
|
49
|
+
const detail = Reflect.get(Object(body), "detail");
|
|
50
|
+
return typeof detail === "string" && detail ? detail : null;
|
|
51
|
+
}
|
|
52
|
+
function folderUploadResultOf({
|
|
53
|
+
task,
|
|
54
|
+
files
|
|
55
|
+
}) {
|
|
56
|
+
const uploaded = [];
|
|
57
|
+
const failed = [];
|
|
58
|
+
const answered = /* @__PURE__ */ new Set();
|
|
59
|
+
for (const result of task.results) {
|
|
60
|
+
answered.add(result.fileIndex);
|
|
61
|
+
const file = files[result.fileIndex];
|
|
62
|
+
if (result.status === "uploaded" && result.assetId) {
|
|
63
|
+
uploaded.push({
|
|
64
|
+
id: result.assetId,
|
|
65
|
+
title: result.filename,
|
|
66
|
+
fileName: result.filename,
|
|
67
|
+
fileSize: (file == null ? void 0 : file.size) ?? 0,
|
|
68
|
+
mediaType: (file == null ? void 0 : file.type) || "application/octet-stream",
|
|
69
|
+
fileIndex: result.fileIndex
|
|
70
|
+
});
|
|
71
|
+
} else {
|
|
72
|
+
failed.push({ fileName: result.filename, error: result.message || "Upload failed" });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
files.forEach((file, index) => {
|
|
76
|
+
if (answered.has(index)) return;
|
|
77
|
+
failed.push({ fileName: file.name, error: task.message || `Upload ${task.status}` });
|
|
78
|
+
});
|
|
79
|
+
return { uploaded, failed };
|
|
80
|
+
}
|
|
81
|
+
function wait(ms, signal) {
|
|
82
|
+
return new Promise((resolve, reject) => {
|
|
83
|
+
if (signal == null ? void 0 : signal.aborted) {
|
|
84
|
+
reject(new DOMException("Upload cancelled", "AbortError"));
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const timer = setTimeout(() => {
|
|
88
|
+
signal == null ? void 0 : signal.removeEventListener("abort", onAbort);
|
|
89
|
+
resolve();
|
|
90
|
+
}, ms);
|
|
91
|
+
const onAbort = () => {
|
|
92
|
+
clearTimeout(timer);
|
|
93
|
+
reject(new DOMException("Upload cancelled", "AbortError"));
|
|
94
|
+
};
|
|
95
|
+
signal == null ? void 0 : signal.addEventListener("abort", onAbort, { once: true });
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
async function waitForFolderUploadTask({
|
|
99
|
+
auth,
|
|
100
|
+
taskId,
|
|
101
|
+
signal,
|
|
102
|
+
deadlineMs = FOLDER_UPLOAD_DEADLINE_MS,
|
|
103
|
+
now = Date.now,
|
|
104
|
+
sleep = (ms) => wait(ms, signal)
|
|
105
|
+
}) {
|
|
106
|
+
const startedAt = now();
|
|
107
|
+
for (let attempt = 0; ; attempt += 1) {
|
|
108
|
+
const data = await apiClient.fetchGraphQL(
|
|
109
|
+
auth,
|
|
110
|
+
ASYNC_UPLOAD_TASK_QUERY,
|
|
111
|
+
{ taskId },
|
|
112
|
+
{ signal }
|
|
113
|
+
);
|
|
114
|
+
const task = data.asyncUploadTask;
|
|
115
|
+
if (!task) throw new Error("Athena no longer knows this upload.");
|
|
116
|
+
if (ENDED.has(task.status)) return task;
|
|
117
|
+
if (now() - startedAt >= deadlineMs) {
|
|
118
|
+
throw new Error("The upload is taking too long; it may still finish in Athena.");
|
|
119
|
+
}
|
|
120
|
+
await sleep(folderUploadPollDelayMs(attempt));
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
async function startFolderUpload({
|
|
124
|
+
send,
|
|
125
|
+
files,
|
|
126
|
+
parentFolderId
|
|
127
|
+
}) {
|
|
128
|
+
const response = await send(folderUploadForm({ files, parentFolderId }));
|
|
129
|
+
if (!response.ok) {
|
|
130
|
+
const detail = await refusalDetail(response);
|
|
131
|
+
if (response.status === 401 || response.status === 403) {
|
|
132
|
+
throw new Error(detail ?? "You can’t add files to this folder.");
|
|
133
|
+
}
|
|
134
|
+
if (response.status === 404) throw new Error(detail ?? "That folder is no longer there.");
|
|
135
|
+
throw new Error(detail ?? `Upload failed with status ${response.status}`);
|
|
136
|
+
}
|
|
137
|
+
const taskId = taskIdOf(await response.json().catch(() => null));
|
|
138
|
+
if (!taskId) throw new Error("Athena did not start the upload.");
|
|
139
|
+
return taskId;
|
|
140
|
+
}
|
|
141
|
+
exports.ASYNC_UPLOAD_TASK_QUERY = ASYNC_UPLOAD_TASK_QUERY;
|
|
142
|
+
exports.FOLDER_UPLOAD_DEADLINE_MS = FOLDER_UPLOAD_DEADLINE_MS;
|
|
143
|
+
exports.FOLDER_UPLOAD_PATH = FOLDER_UPLOAD_PATH;
|
|
144
|
+
exports.folderUploadForm = folderUploadForm;
|
|
145
|
+
exports.folderUploadPollDelayMs = folderUploadPollDelayMs;
|
|
146
|
+
exports.folderUploadResultOf = folderUploadResultOf;
|
|
147
|
+
exports.startFolderUpload = startFolderUpload;
|
|
148
|
+
exports.waitForFolderUploadTask = waitForFolderUploadTask;
|
|
149
|
+
//# sourceMappingURL=folder-upload.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"folder-upload.cjs","sources":["../../src/composer/folder-upload.ts"],"sourcesContent":["/**\n * Uploading files into a folder. agora's quick upload (`POST /api/upload/`) files what it takes at\n * the workspace's root; its async upload (`POST /api/upload/async`) takes a destination,\n * `parent_folder_id`, and authorizes EDIT on that folder before it stages a byte\n * (`_require_upload_destination`: the folder's permission check, then its ABAC edit gate), so a\n * folder the person may only view, or may not open, refuses the whole upload. The task it starts is\n * then read through GraphQL (`asyncUploadTask`, answered only for the caller's current workspace)\n * until it ends, at most `FOLDER_UPLOAD_DEADLINE_MS`.\n */\nimport {\n fetchGraphQL,\n type MentionAuthContext,\n} from '../chat-ui/mentions/suggestions/data/api-client';\nimport type { UploadedAsset } from './useFileUpload';\n\n/** agora's async upload route, under the API base. */\nexport const FOLDER_UPLOAD_PATH = '/api/upload/async';\n\n/** How long an upload's task is read before the upload gives up on it (it may still finish). */\nexport const FOLDER_UPLOAD_DEADLINE_MS = 15 * 60 * 1000;\n/** The first wait before the task is read again, doubling to `FOLDER_UPLOAD_POLL_MAX_MS`. */\nconst FOLDER_UPLOAD_POLL_MIN_MS = 250;\nconst FOLDER_UPLOAD_POLL_MAX_MS = 2_000;\n\nexport const ASYNC_UPLOAD_TASK_QUERY = `\n query AthenaAsyncUploadTask($taskId: String!) {\n asyncUploadTask(taskId: $taskId) {\n taskId\n status\n requestedCount\n processedCount\n uploadedCount\n failedCount\n message\n results {\n fileIndex\n filename\n status\n message\n assetId\n }\n }\n }\n`;\n\n/** The states an upload task ends in. */\nconst ENDED: ReadonlySet<string> = new Set(['completed', 'failed', 'cancelled']);\n\nexport interface FolderUploadTask {\n taskId: string;\n status: string;\n requestedCount: number;\n processedCount: number;\n uploadedCount: number;\n failedCount: number;\n message: string | null;\n results: Array<{\n fileIndex: number;\n filename: string;\n status: string;\n message: string;\n assetId: string | null;\n }>;\n}\n\n/** What an upload into a folder made, and what it could not. */\nexport interface FolderUploadResult {\n uploaded: UploadedAsset[];\n failed: Array<{ fileName: string; error: string }>;\n}\n\n/** The wait before the `attempt`th read of the task (0-indexed), doubling to its cap. */\nexport function folderUploadPollDelayMs(attempt: number): number {\n return Math.min(FOLDER_UPLOAD_POLL_MIN_MS * 2 ** attempt, FOLDER_UPLOAD_POLL_MAX_MS);\n}\n\n/** The upload's form: every file, and the folder they go into. */\nexport function folderUploadForm({\n files,\n parentFolderId,\n}: {\n files: readonly File[];\n parentFolderId: string;\n}): FormData {\n const form = new FormData();\n for (const file of files) form.append('files', file, file.name);\n form.append('parent_folder_id', parentFolderId);\n return form;\n}\n\n/** The task id agora's answer names (`taskId`; `task_id` from an agora that answers snake_case). */\nfunction taskIdOf(body: unknown): string | null {\n const camel: unknown = Reflect.get(Object(body), 'taskId');\n if (typeof camel === 'string' && camel) return camel;\n const snake: unknown = Reflect.get(Object(body), 'task_id');\n return typeof snake === 'string' && snake ? snake : null;\n}\n\n/** agora's `detail` for a refused upload, when it gave one. */\nasync function refusalDetail(response: Response): Promise<string | null> {\n const body: unknown = await response.json().catch(() => null);\n const detail: unknown = Reflect.get(Object(body), 'detail');\n return typeof detail === 'string' && detail ? detail : null;\n}\n\n/**\n * What the task made, file by file: each uploaded file as the asset it became (named and sized\n * from the file sent), each failed one with agora's reason, and a task that ended without a result\n * for a file (cancelled, or failed as a whole) with the task's message.\n */\nexport function folderUploadResultOf({\n task,\n files,\n}: {\n task: FolderUploadTask;\n files: readonly File[];\n}): FolderUploadResult {\n const uploaded: UploadedAsset[] = [];\n const failed: FolderUploadResult['failed'] = [];\n const answered = new Set<number>();\n for (const result of task.results) {\n answered.add(result.fileIndex);\n const file = files[result.fileIndex];\n if (result.status === 'uploaded' && result.assetId) {\n uploaded.push({\n id: result.assetId,\n title: result.filename,\n fileName: result.filename,\n fileSize: file?.size ?? 0,\n mediaType: file?.type || 'application/octet-stream',\n fileIndex: result.fileIndex,\n });\n } else {\n failed.push({ fileName: result.filename, error: result.message || 'Upload failed' });\n }\n }\n files.forEach((file, index) => {\n if (answered.has(index)) return;\n failed.push({ fileName: file.name, error: task.message || `Upload ${task.status}` });\n });\n return { uploaded, failed };\n}\n\n/** Waits `ms`, or rejects at once when `signal` aborts. */\nfunction wait(ms: number, signal: AbortSignal | undefined): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(new DOMException('Upload cancelled', 'AbortError'));\n return;\n }\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n reject(new DOMException('Upload cancelled', 'AbortError'));\n };\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n\n/**\n * Reads the task until it ends: at once, then after waits that double from 250 ms to 2 s. A task\n * agora no longer names (another workspace, or gone) and one that has not ended by the deadline\n * fail the upload; what the task did by then stays done.\n */\nexport async function waitForFolderUploadTask({\n auth,\n taskId,\n signal,\n deadlineMs = FOLDER_UPLOAD_DEADLINE_MS,\n now = Date.now,\n sleep = (ms) => wait(ms, signal),\n}: {\n auth: MentionAuthContext;\n taskId: string;\n signal?: AbortSignal;\n deadlineMs?: number;\n now?: () => number;\n sleep?: (ms: number) => Promise<void>;\n}): Promise<FolderUploadTask> {\n const startedAt = now();\n for (let attempt = 0; ; attempt += 1) {\n const data = await fetchGraphQL<{ asyncUploadTask: FolderUploadTask | null }>(\n auth,\n ASYNC_UPLOAD_TASK_QUERY,\n { taskId },\n { signal },\n );\n const task = data.asyncUploadTask;\n if (!task) throw new Error('Athena no longer knows this upload.');\n if (ENDED.has(task.status)) return task;\n if (now() - startedAt >= deadlineMs) {\n throw new Error('The upload is taking too long; it may still finish in Athena.');\n }\n await sleep(folderUploadPollDelayMs(attempt));\n }\n}\n\n/**\n * Starts an upload of `files` into `parentFolderId` (agora's async upload, which refuses a folder\n * the caller may not edit before it takes any file), as `send` posts it, and answers its task id.\n */\nexport async function startFolderUpload({\n send,\n files,\n parentFolderId,\n}: {\n /** Posts the form to `FOLDER_UPLOAD_PATH` with the credential (and the byte progress). */\n send: (form: FormData) => Promise<Response>;\n files: readonly File[];\n parentFolderId: string;\n}): Promise<string> {\n const response = await send(folderUploadForm({ files, parentFolderId }));\n if (!response.ok) {\n const detail = await refusalDetail(response);\n if (response.status === 401 || response.status === 403) {\n throw new Error(detail ?? 'You can’t add files to this folder.');\n }\n if (response.status === 404) throw new Error(detail ?? 'That folder is no longer there.');\n throw new Error(detail ?? `Upload failed with status ${response.status}`);\n }\n const taskId = taskIdOf(await response.json().catch(() => null));\n if (!taskId) throw new Error('Athena did not start the upload.');\n return taskId;\n}\n"],"names":["fetchGraphQL"],"mappings":"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"}
|