@athenaintel/react 0.42.2 → 0.48.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 +225 -3
- package/dist/agent-runtime/src/answer-label.cjs +137 -0
- package/dist/agent-runtime/src/answer-label.cjs.map +1 -0
- package/dist/agent-runtime/src/answer-label.d.ts +104 -0
- package/dist/agent-runtime/src/answer-label.js +137 -0
- package/dist/agent-runtime/src/answer-label.js.map +1 -0
- package/dist/agent-runtime/src/answer-rows.cjs +180 -0
- package/dist/agent-runtime/src/answer-rows.cjs.map +1 -0
- package/dist/agent-runtime/src/answer-rows.d.ts +86 -0
- package/dist/agent-runtime/src/answer-rows.js +180 -0
- package/dist/agent-runtime/src/answer-rows.js.map +1 -0
- package/dist/agent-runtime/src/client-tool-bridge.cjs +15 -15
- package/dist/agent-runtime/src/client-tool-bridge.cjs.map +1 -1
- package/dist/agent-runtime/src/conversation-index.cjs +8 -8
- package/dist/agent-runtime/src/conversation-index.cjs.map +1 -1
- package/dist/agent-runtime/src/conversation-list-groups.d.ts +74 -0
- package/dist/agent-runtime/src/decision-checks.cjs +207 -0
- package/dist/agent-runtime/src/decision-checks.cjs.map +1 -0
- package/dist/agent-runtime/src/decision-checks.d.ts +142 -0
- package/dist/agent-runtime/src/decision-checks.js +207 -0
- package/dist/agent-runtime/src/decision-checks.js.map +1 -0
- package/dist/agent-runtime/src/desktop-handoff.d.ts +12 -0
- package/dist/agent-runtime/src/errors.cjs +18 -0
- package/dist/agent-runtime/src/errors.cjs.map +1 -1
- package/dist/agent-runtime/src/errors.d.ts +7 -0
- package/dist/agent-runtime/src/errors.js +18 -0
- package/dist/agent-runtime/src/errors.js.map +1 -1
- package/dist/agent-runtime/src/generated/runconfig-contract.cjs +12 -0
- package/dist/agent-runtime/src/generated/runconfig-contract.cjs.map +1 -1
- package/dist/agent-runtime/src/generated/runconfig-contract.d.ts +6 -6
- package/dist/agent-runtime/src/generated/runconfig-contract.js +12 -0
- package/dist/agent-runtime/src/generated/runconfig-contract.js.map +1 -1
- package/dist/agent-runtime/src/handoff-arrival.cjs +60 -0
- package/dist/agent-runtime/src/handoff-arrival.cjs.map +1 -0
- package/dist/agent-runtime/src/handoff-arrival.d.ts +46 -0
- package/dist/agent-runtime/src/handoff-arrival.js +60 -0
- package/dist/agent-runtime/src/handoff-arrival.js.map +1 -0
- package/dist/agent-runtime/src/index.d.ts +15 -8
- package/dist/agent-runtime/src/interrupts.cjs +43 -18
- package/dist/agent-runtime/src/interrupts.cjs.map +1 -1
- package/dist/agent-runtime/src/interrupts.d.ts +19 -2
- package/dist/agent-runtime/src/interrupts.js +28 -3
- package/dist/agent-runtime/src/interrupts.js.map +1 -1
- package/dist/agent-runtime/src/lane-history.cjs +8 -8
- package/dist/agent-runtime/src/lane-history.cjs.map +1 -1
- package/dist/agent-runtime/src/messages.cjs +43 -8
- package/dist/agent-runtime/src/messages.cjs.map +1 -1
- package/dist/agent-runtime/src/messages.d.ts +25 -3
- package/dist/agent-runtime/src/messages.js +43 -8
- package/dist/agent-runtime/src/messages.js.map +1 -1
- package/dist/agent-runtime/src/offline-status.cjs +36 -0
- package/dist/agent-runtime/src/offline-status.cjs.map +1 -0
- package/dist/agent-runtime/src/offline-status.d.ts +118 -3
- package/dist/agent-runtime/src/offline-status.js +36 -0
- package/dist/agent-runtime/src/offline-status.js.map +1 -0
- package/dist/agent-runtime/src/queue.cjs +0 -9
- package/dist/agent-runtime/src/queue.cjs.map +1 -1
- package/dist/agent-runtime/src/queue.js +0 -9
- package/dist/agent-runtime/src/queue.js.map +1 -1
- package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs +9 -9
- package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs.map +1 -1
- package/dist/agent-runtime/src/runtime-catalog.cjs +42 -0
- package/dist/agent-runtime/src/runtime-catalog.cjs.map +1 -0
- package/dist/agent-runtime/src/runtime-catalog.d.ts +35 -0
- package/dist/agent-runtime/src/runtime-catalog.js +42 -0
- package/dist/agent-runtime/src/runtime-catalog.js.map +1 -0
- package/dist/agent-runtime/src/runtime-messages.cjs.map +1 -1
- package/dist/agent-runtime/src/runtime-messages.d.ts +1 -1
- package/dist/agent-runtime/src/runtime-messages.js.map +1 -1
- package/dist/agent-runtime/src/runtime.d.ts +40 -0
- package/dist/agent-runtime/src/statewire-suspended.cjs +3 -3
- package/dist/agent-runtime/src/statewire-suspended.cjs.map +1 -1
- package/dist/agent-runtime/src/subagents.cjs +32 -2
- package/dist/agent-runtime/src/subagents.cjs.map +1 -1
- package/dist/agent-runtime/src/subagents.d.ts +9 -0
- package/dist/agent-runtime/src/subagents.js +30 -0
- package/dist/agent-runtime/src/subagents.js.map +1 -1
- package/dist/agent-runtime/src/thread-driver.cjs +67 -0
- package/dist/agent-runtime/src/thread-driver.cjs.map +1 -0
- package/dist/agent-runtime/src/thread-driver.d.ts +49 -0
- package/dist/agent-runtime/src/thread-driver.js +67 -0
- package/dist/agent-runtime/src/thread-driver.js.map +1 -0
- package/dist/agent-runtime/src/thread-handoff-flow-machine.d.ts +172 -0
- package/dist/agent-runtime/src/thread-handoff-protocol.d.ts +756 -0
- package/dist/agent-runtime/src/thread-handoff-qr.d.ts +11 -0
- package/dist/agent-runtime/src/thread-handoff.d.ts +3 -364
- package/dist/agent-runtime/src/thread-status.cjs +3 -3
- package/dist/agent-runtime/src/thread-status.cjs.map +1 -1
- package/dist/agent-runtime/src/tool-metadata.cjs +210 -33
- package/dist/agent-runtime/src/tool-metadata.cjs.map +1 -1
- package/dist/agent-runtime/src/tool-metadata.d.ts +12 -0
- package/dist/agent-runtime/src/tool-metadata.js +210 -33
- package/dist/agent-runtime/src/tool-metadata.js.map +1 -1
- package/dist/agent-runtime/src/tool-names.cjs +2 -0
- package/dist/agent-runtime/src/tool-names.cjs.map +1 -1
- package/dist/agent-runtime/src/tool-names.d.ts +2 -0
- package/dist/agent-runtime/src/tool-names.js +2 -0
- package/dist/agent-runtime/src/tool-names.js.map +1 -1
- package/dist/agent-runtime/src/types.d.ts +10 -2
- package/dist/agent-runtime/src/use-conversation-list.cjs +11 -11
- package/dist/agent-runtime/src/use-conversation-list.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.cjs +24 -19
- 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 +2 -1
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.js +6 -1
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.js.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-config.cjs +14 -14
- package/dist/agent-runtime/src/use-deep-agent-config.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-edit-submit.cjs +6 -6
- package/dist/agent-runtime/src/use-deep-agent-edit-submit.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-runtime.cjs +16 -16
- package/dist/agent-runtime/src/use-deep-agent-runtime.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-thread.cjs +45 -45
- package/dist/agent-runtime/src/use-deep-agent-thread.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-voice.cjs +572 -134
- package/dist/agent-runtime/src/use-deep-agent-voice.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-voice.d.ts +137 -10
- package/dist/agent-runtime/src/use-deep-agent-voice.js +514 -76
- package/dist/agent-runtime/src/use-deep-agent-voice.js.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-window-sync.cjs +26 -26
- package/dist/agent-runtime/src/use-deep-agent-window-sync.cjs.map +1 -1
- package/dist/agent-runtime/src/use-historical-edit-attachments.cjs +4 -4
- package/dist/agent-runtime/src/use-historical-edit-attachments.cjs.map +1 -1
- package/dist/agent-runtime/src/use-thread-handoff-flow.d.ts +28 -26
- package/dist/agent-runtime/src/voice-media.cjs +117 -0
- package/dist/agent-runtime/src/voice-media.cjs.map +1 -0
- package/dist/agent-runtime/src/voice-media.d.ts +49 -0
- package/dist/agent-runtime/src/voice-media.js +117 -0
- package/dist/agent-runtime/src/voice-media.js.map +1 -0
- package/dist/agent-runtime/src/voice-wire-types.d.ts +32 -0
- package/dist/assets/AssetPanel.cjs +11 -11
- package/dist/assets/AssetPanel.cjs.map +1 -1
- package/dist/assets/AthenaAssetEmbed.cjs +11 -9
- package/dist/assets/AthenaAssetEmbed.cjs.map +1 -1
- package/dist/assets/AthenaAssetEmbed.d.ts +7 -0
- package/dist/assets/AthenaAssetEmbed.js +4 -2
- package/dist/assets/AthenaAssetEmbed.js.map +1 -1
- package/dist/assets/AthenaLayout.cjs +16 -16
- package/dist/assets/AthenaLayout.cjs.map +1 -1
- package/dist/assets/use-asset-content.cjs +4 -4
- package/dist/assets/use-asset-content.cjs.map +1 -1
- package/dist/assets/use-asset-embed.cjs +14 -7
- package/dist/assets/use-asset-embed.cjs.map +1 -1
- package/dist/assets/use-asset-embed.d.ts +11 -1
- package/dist/assets/use-asset-embed.js +10 -3
- package/dist/assets/use-asset-embed.js.map +1 -1
- package/dist/auth/AthenaAuthContext.cjs +3 -3
- package/dist/auth/AthenaAuthContext.cjs.map +1 -1
- package/dist/auth/AthenaAuthProvider.cjs +8 -8
- package/dist/auth/AthenaAuthProvider.cjs.map +1 -1
- package/dist/auth/AthenaCredentialSourceContext.cjs +5 -5
- package/dist/auth/AthenaCredentialSourceContext.cjs.map +1 -1
- package/dist/auth/AthenaSSOProvider.cjs +14 -14
- package/dist/auth/AthenaSSOProvider.cjs.map +1 -1
- package/dist/auth/credential-source.cjs +26 -13
- package/dist/auth/credential-source.cjs.map +1 -1
- package/dist/auth/credential-source.d.ts +8 -0
- package/dist/auth/credential-source.js +26 -13
- package/dist/auth/credential-source.js.map +1 -1
- package/dist/catalog/agent-model-options.cjs +25 -17
- package/dist/catalog/agent-model-options.cjs.map +1 -1
- package/dist/catalog/agent-model-options.d.ts +38 -5
- package/dist/catalog/agent-model-options.js +25 -17
- package/dist/catalog/agent-model-options.js.map +1 -1
- package/dist/catalog/channel-refusal.cjs +36 -0
- package/dist/catalog/channel-refusal.cjs.map +1 -0
- package/dist/catalog/channel-refusal.d.ts +29 -0
- package/dist/catalog/channel-refusal.js +36 -0
- package/dist/catalog/channel-refusal.js.map +1 -0
- package/dist/catalog/chat-pickers.cjs +60 -24
- package/dist/catalog/chat-pickers.cjs.map +1 -1
- package/dist/catalog/chat-pickers.d.ts +12 -2
- package/dist/catalog/chat-pickers.js +56 -20
- package/dist/catalog/chat-pickers.js.map +1 -1
- package/dist/catalog/runtime-catalog.cjs +89 -23
- package/dist/catalog/runtime-catalog.cjs.map +1 -1
- package/dist/catalog/runtime-catalog.d.ts +8 -2
- package/dist/catalog/runtime-catalog.js +83 -17
- package/dist/catalog/runtime-catalog.js.map +1 -1
- package/dist/catalog/use-athena-chat-mode.cjs +12 -12
- package/dist/catalog/use-athena-chat-mode.cjs.map +1 -1
- package/dist/chat/AthenaChat.cjs +155 -67
- package/dist/chat/AthenaChat.cjs.map +1 -1
- package/dist/chat/AthenaChat.d.ts +42 -2
- package/dist/chat/AthenaChat.js +106 -18
- package/dist/chat/AthenaChat.js.map +1 -1
- package/dist/chat/AthenaChatErrorBoundary.cjs +3 -3
- package/dist/chat/AthenaChatErrorBoundary.cjs.map +1 -1
- package/dist/chat/DrivingOnChip.cjs +23 -0
- package/dist/chat/DrivingOnChip.cjs.map +1 -0
- package/dist/chat/DrivingOnChip.d.ts +17 -0
- package/dist/chat/DrivingOnChip.js +23 -0
- package/dist/chat/DrivingOnChip.js.map +1 -0
- package/dist/chat/StatewireApprovalCard.cjs +125 -31
- package/dist/chat/StatewireApprovalCard.cjs.map +1 -1
- package/dist/chat/StatewireApprovalCard.d.ts +73 -1
- package/dist/chat/StatewireApprovalCard.js +115 -21
- package/dist/chat/StatewireApprovalCard.js.map +1 -1
- package/dist/chat/StatewireClientToolBridge.cjs +2 -2
- package/dist/chat/StatewireClientToolBridge.cjs.map +1 -1
- package/dist/chat/StatewireQueuedMessages.cjs +25 -63
- package/dist/chat/StatewireQueuedMessages.cjs.map +1 -1
- package/dist/chat/StatewireQueuedMessages.d.ts +11 -13
- package/dist/chat/StatewireQueuedMessages.js +16 -54
- package/dist/chat/StatewireQueuedMessages.js.map +1 -1
- package/dist/chat/WaitingOnYouBanner.cjs +3 -3
- package/dist/chat/WaitingOnYouBanner.cjs.map +1 -1
- package/dist/chat/athena-chat-welcome.cjs +2 -2
- package/dist/chat/athena-chat-welcome.cjs.map +1 -1
- package/dist/chat/athena-citation-links.cjs +5 -5
- package/dist/chat/athena-citation-links.cjs.map +1 -1
- package/dist/chat/athena-composer-controls.cjs +26 -16
- package/dist/chat/athena-composer-controls.cjs.map +1 -1
- package/dist/chat/athena-composer-controls.d.ts +6 -0
- package/dist/chat/athena-composer-controls.js +26 -16
- package/dist/chat/athena-composer-controls.js.map +1 -1
- package/dist/chat/athena-turn-end-status.cjs +42 -0
- package/dist/chat/athena-turn-end-status.cjs.map +1 -0
- package/dist/chat/athena-turn-end-status.d.ts +24 -0
- package/dist/chat/athena-turn-end-status.js +42 -0
- package/dist/chat/athena-turn-end-status.js.map +1 -0
- package/dist/chat/browser-decision-check.cjs +131 -0
- package/dist/chat/browser-decision-check.cjs.map +1 -0
- package/dist/chat/browser-decision-check.d.ts +61 -0
- package/dist/chat/browser-decision-check.js +131 -0
- package/dist/chat/browser-decision-check.js.map +1 -0
- package/dist/chat/chat-outbox-rows.cjs +3 -3
- package/dist/chat/chat-outbox-rows.cjs.map +1 -1
- package/dist/chat/chat-voice-controls.cjs +93 -28
- package/dist/chat/chat-voice-controls.cjs.map +1 -1
- package/dist/chat/chat-voice-controls.d.ts +36 -2
- package/dist/chat/chat-voice-controls.js +89 -24
- package/dist/chat/chat-voice-controls.js.map +1 -1
- package/dist/chat/composer-keyboard-hint.cjs +5 -5
- package/dist/chat/composer-keyboard-hint.cjs.map +1 -1
- package/dist/chat/device-operation.cjs +29 -0
- package/dist/chat/device-operation.cjs.map +1 -0
- package/dist/chat/device-operation.d.ts +34 -0
- package/dist/chat/device-operation.js +29 -0
- package/dist/chat/device-operation.js.map +1 -0
- package/dist/chat/super-grouping/CollapsibleGroup.cjs +14 -14
- package/dist/chat/super-grouping/CollapsibleGroup.cjs.map +1 -1
- package/dist/chat/super-grouping/GroupedMessageParts.cjs +4 -4
- package/dist/chat/super-grouping/GroupedMessageParts.cjs.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingCard.cjs +60 -38
- package/dist/chat/super-grouping/SuperGroupingCard.cjs.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingCard.d.ts +24 -4
- package/dist/chat/super-grouping/SuperGroupingCard.js +37 -15
- package/dist/chat/super-grouping/SuperGroupingCard.js.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingTranscript.cjs +32 -32
- package/dist/chat/super-grouping/SuperGroupingTranscript.cjs.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingTranscript.js +3 -3
- package/dist/chat/super-grouping/SuperGroupingTranscript.js.map +1 -1
- package/dist/chat/super-grouping/ToolTimeline.cjs +97 -37
- package/dist/chat/super-grouping/ToolTimeline.cjs.map +1 -1
- package/dist/chat/super-grouping/ToolTimeline.d.ts +14 -2
- package/dist/chat/super-grouping/ToolTimeline.js +94 -34
- package/dist/chat/super-grouping/ToolTimeline.js.map +1 -1
- package/dist/chat/super-grouping/activity-timeline.cjs +47 -12
- package/dist/chat/super-grouping/activity-timeline.cjs.map +1 -1
- package/dist/chat/super-grouping/activity-timeline.d.ts +21 -0
- package/dist/chat/super-grouping/activity-timeline.js +47 -12
- package/dist/chat/super-grouping/activity-timeline.js.map +1 -1
- package/dist/chat/super-grouping/grouping-function.cjs +4 -0
- package/dist/chat/super-grouping/grouping-function.cjs.map +1 -1
- package/dist/chat/super-grouping/grouping-function.d.ts +7 -0
- package/dist/chat/super-grouping/grouping-function.js +5 -1
- package/dist/chat/super-grouping/grouping-function.js.map +1 -1
- package/dist/chat/super-grouping/index.cjs +6 -0
- package/dist/chat/super-grouping/index.cjs.map +1 -1
- package/dist/chat/super-grouping/index.d.ts +6 -2
- package/dist/chat/super-grouping/index.js +7 -1
- package/dist/chat/super-grouping/index.js.map +1 -1
- package/dist/chat/super-grouping/timeline-step.cjs +61 -2
- package/dist/chat/super-grouping/timeline-step.cjs.map +1 -1
- package/dist/chat/super-grouping/timeline-step.d.ts +13 -1
- package/dist/chat/super-grouping/timeline-step.js +61 -2
- package/dist/chat/super-grouping/timeline-step.js.map +1 -1
- package/dist/chat/super-grouping/tool-part-placement.cjs +17 -0
- package/dist/chat/super-grouping/tool-part-placement.cjs.map +1 -0
- package/dist/chat/super-grouping/tool-part-placement.d.ts +22 -0
- package/dist/chat/super-grouping/tool-part-placement.js +17 -0
- package/dist/chat/super-grouping/tool-part-placement.js.map +1 -0
- package/dist/chat/thread-scroll-to-bottom.cjs +2 -2
- package/dist/chat/thread-scroll-to-bottom.cjs.map +1 -1
- package/dist/chat/thread-scroll-to-bottom.d.ts +10 -7
- package/dist/chat/thread-scroll-to-bottom.js +2 -2
- package/dist/chat/thread-scroll-to-bottom.js.map +1 -1
- package/dist/chat/tooltip-icon-button.cjs +2 -2
- package/dist/chat/tooltip-icon-button.cjs.map +1 -1
- package/dist/chat/use-athena-voice-live.cjs +11 -0
- package/dist/chat/use-athena-voice-live.cjs.map +1 -0
- package/dist/chat/use-athena-voice-live.d.ts +11 -0
- package/dist/chat/use-athena-voice-live.js +11 -0
- package/dist/chat/use-athena-voice-live.js.map +1 -0
- package/dist/chat/use-statewire-approval-request.cjs +56 -24
- package/dist/chat/use-statewire-approval-request.cjs.map +1 -1
- package/dist/chat/use-statewire-approval-request.d.ts +33 -4
- package/dist/chat/use-statewire-approval-request.js +41 -9
- package/dist/chat/use-statewire-approval-request.js.map +1 -1
- package/dist/chat-ui/auth/sign-in-card.cjs +2 -2
- package/dist/chat-ui/auth/sign-in-card.cjs.map +1 -1
- package/dist/chat-ui/composer/tiptap-composer.cjs +138 -107
- package/dist/chat-ui/composer/tiptap-composer.cjs.map +1 -1
- package/dist/chat-ui/composer/tiptap-composer.d.ts +20 -4
- package/dist/chat-ui/composer/tiptap-composer.js +85 -54
- package/dist/chat-ui/composer/tiptap-composer.js.map +1 -1
- package/dist/chat-ui/header/conversation-history-panel.cjs +49 -23
- package/dist/chat-ui/header/conversation-history-panel.cjs.map +1 -1
- package/dist/chat-ui/header/conversation-history-panel.d.ts +12 -1
- package/dist/chat-ui/header/conversation-history-panel.js +38 -12
- package/dist/chat-ui/header/conversation-history-panel.js.map +1 -1
- package/dist/chat-ui/index.cjs +18 -0
- package/dist/chat-ui/index.cjs.map +1 -1
- package/dist/chat-ui/index.d.ts +7 -1
- package/dist/chat-ui/index.js +18 -0
- package/dist/chat-ui/index.js.map +1 -1
- package/dist/chat-ui/mentions/mention-chip.cjs +147 -38
- package/dist/chat-ui/mentions/mention-chip.cjs.map +1 -1
- package/dist/chat-ui/mentions/mention-chip.d.ts +17 -1
- package/dist/chat-ui/mentions/mention-chip.js +146 -37
- package/dist/chat-ui/mentions/mention-chip.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.cjs +10 -9
- package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.js +3 -2
- package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-popup.cjs +2 -2
- package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-popup.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/menu-list.cjs +29 -6
- package/dist/chat-ui/mentions/suggestions/components/menu-list.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/menu-list.d.ts +7 -1
- package/dist/chat-ui/mentions/suggestions/components/menu-list.js +25 -2
- package/dist/chat-ui/mentions/suggestions/components/menu-list.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/use-keyboard-navigation.cjs +2 -2
- package/dist/chat-ui/mentions/suggestions/components/use-keyboard-navigation.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/use-menu-navigation.cjs +2 -2
- package/dist/chat-ui/mentions/suggestions/components/use-menu-navigation.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/api-client.cjs +3 -3
- package/dist/chat-ui/mentions/suggestions/data/api-client.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/orchestrator.cjs +56 -2
- package/dist/chat-ui/mentions/suggestions/data/orchestrator.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/orchestrator.d.ts +12 -0
- package/dist/chat-ui/mentions/suggestions/data/orchestrator.js +56 -2
- package/dist/chat-ui/mentions/suggestions/data/orchestrator.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs +24 -3
- package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/sources/index.d.ts +7 -0
- package/dist/chat-ui/mentions/suggestions/data/sources/index.js +24 -3
- package/dist/chat-ui/mentions/suggestions/data/sources/index.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.cjs +35 -13
- 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 +15 -1
- package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.js +28 -6
- package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/use-menu-items.cjs +9 -6
- package/dist/chat-ui/mentions/suggestions/data/use-menu-items.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/use-menu-items.d.ts +3 -0
- package/dist/chat-ui/mentions/suggestions/data/use-menu-items.js +5 -2
- package/dist/chat-ui/mentions/suggestions/data/use-menu-items.js.map +1 -1
- package/dist/chat-ui/mentions/use-account-workspace-id.cjs +45 -10
- package/dist/chat-ui/mentions/use-account-workspace-id.cjs.map +1 -1
- package/dist/chat-ui/mentions/use-account-workspace-id.d.ts +24 -1
- package/dist/chat-ui/mentions/use-account-workspace-id.js +46 -11
- package/dist/chat-ui/mentions/use-account-workspace-id.js.map +1 -1
- package/dist/chat-ui/mentions/use-member-avatar.cjs +4 -4
- package/dist/chat-ui/mentions/use-member-avatar.cjs.map +1 -1
- package/dist/chat-ui/mentions/use-mention-asset.cjs +140 -0
- package/dist/chat-ui/mentions/use-mention-asset.cjs.map +1 -0
- package/dist/chat-ui/mentions/use-mention-asset.d.ts +16 -0
- package/dist/chat-ui/mentions/use-mention-asset.js +140 -0
- package/dist/chat-ui/mentions/use-mention-asset.js.map +1 -0
- package/dist/chat-ui/messages/answer-label.cjs +42 -0
- package/dist/chat-ui/messages/answer-label.cjs.map +1 -0
- package/dist/chat-ui/messages/answer-label.d.ts +33 -0
- package/dist/chat-ui/messages/answer-label.js +42 -0
- package/dist/chat-ui/messages/answer-label.js.map +1 -0
- package/dist/chat-ui/messages/arrival-animation.cjs +13 -0
- package/dist/chat-ui/messages/arrival-animation.cjs.map +1 -0
- package/dist/chat-ui/messages/arrival-animation.d.ts +14 -0
- package/dist/chat-ui/messages/arrival-animation.js +13 -0
- package/dist/chat-ui/messages/arrival-animation.js.map +1 -0
- package/dist/chat-ui/messages/continue-pill.cjs +5 -5
- package/dist/chat-ui/messages/continue-pill.cjs.map +1 -1
- package/dist/chat-ui/messages/handoff-arrival-divider.cjs +44 -0
- package/dist/chat-ui/messages/handoff-arrival-divider.cjs.map +1 -0
- package/dist/chat-ui/messages/handoff-arrival-divider.d.ts +17 -0
- package/dist/chat-ui/messages/handoff-arrival-divider.js +44 -0
- package/dist/chat-ui/messages/handoff-arrival-divider.js.map +1 -0
- package/dist/chat-ui/messages/message-actions-config.cjs +3 -3
- package/dist/chat-ui/messages/message-actions-config.cjs.map +1 -1
- package/dist/chat-ui/messages/message-components.cjs +8 -4
- package/dist/chat-ui/messages/message-components.cjs.map +1 -1
- package/dist/chat-ui/messages/message-components.js +5 -1
- package/dist/chat-ui/messages/message-components.js.map +1 -1
- package/dist/chat-ui/messages/message-images.cjs +66 -0
- package/dist/chat-ui/messages/message-images.cjs.map +1 -0
- package/dist/chat-ui/messages/message-images.d.ts +16 -0
- package/dist/chat-ui/messages/message-images.js +66 -0
- package/dist/chat-ui/messages/message-images.js.map +1 -0
- package/dist/chat-ui/messages/user-edit-composer.cjs +2 -2
- package/dist/chat-ui/messages/user-edit-composer.cjs.map +1 -1
- package/dist/chat-ui/messages/wake-marker.cjs +3 -3
- package/dist/chat-ui/messages/wake-marker.cjs.map +1 -1
- package/dist/chat-ui/rich-text/chat-link.cjs +7 -6
- package/dist/chat-ui/rich-text/chat-link.cjs.map +1 -1
- package/dist/chat-ui/rich-text/chat-link.d.ts +2 -3
- package/dist/chat-ui/rich-text/chat-link.js +6 -5
- package/dist/chat-ui/rich-text/chat-link.js.map +1 -1
- package/dist/chat-ui/rich-text/chat-message-body.cjs +8 -8
- package/dist/chat-ui/rich-text/chat-message-body.cjs.map +1 -1
- package/dist/chat-ui/rich-text/chat-node-views.cjs +7 -6
- package/dist/chat-ui/rich-text/chat-node-views.cjs.map +1 -1
- package/dist/chat-ui/rich-text/chat-node-views.js +1 -0
- package/dist/chat-ui/rich-text/chat-node-views.js.map +1 -1
- package/dist/chat-ui/rich-text/dom-output-spec.cjs +2 -2
- package/dist/chat-ui/rich-text/dom-output-spec.cjs.map +1 -1
- package/dist/chat-ui/statewire.cjs +3 -0
- package/dist/chat-ui/statewire.cjs.map +1 -1
- package/dist/chat-ui/statewire.d.ts +2 -1
- package/dist/chat-ui/statewire.js +3 -0
- package/dist/chat-ui/statewire.js.map +1 -1
- package/dist/chat-ui/thread/chat-thread-shell.cjs +43 -14
- package/dist/chat-ui/thread/chat-thread-shell.cjs.map +1 -1
- package/dist/chat-ui/thread/chat-thread-shell.d.ts +16 -2
- package/dist/chat-ui/thread/chat-thread-shell.js +35 -6
- package/dist/chat-ui/thread/chat-thread-shell.js.map +1 -1
- package/dist/chat-ui/thread/composer-send-or-stop.cjs +30 -20
- package/dist/chat-ui/thread/composer-send-or-stop.cjs.map +1 -1
- package/dist/chat-ui/thread/composer-send-or-stop.d.ts +8 -0
- package/dist/chat-ui/thread/composer-send-or-stop.js +29 -19
- package/dist/chat-ui/thread/composer-send-or-stop.js.map +1 -1
- package/dist/chat-ui/thread/statewire-history-edge.cjs +20 -21
- package/dist/chat-ui/thread/statewire-history-edge.cjs.map +1 -1
- package/dist/chat-ui/thread/statewire-history-edge.js +3 -4
- package/dist/chat-ui/thread/statewire-history-edge.js.map +1 -1
- package/dist/chat-ui/thread/thread-loading-overlay.cjs +5 -5
- package/dist/chat-ui/thread/thread-loading-overlay.cjs.map +1 -1
- package/dist/collab/client.cjs +40 -3
- package/dist/collab/client.cjs.map +1 -1
- package/dist/collab/client.d.ts +25 -0
- package/dist/collab/client.js +40 -3
- package/dist/collab/client.js.map +1 -1
- package/dist/collab/document-status.cjs +150 -0
- package/dist/collab/document-status.cjs.map +1 -0
- package/dist/collab/document-status.d.ts +68 -0
- package/dist/collab/document-status.js +150 -0
- package/dist/collab/document-status.js.map +1 -0
- package/dist/collab/index.cjs +7 -0
- package/dist/collab/index.cjs.map +1 -1
- package/dist/collab/index.d.ts +6 -1
- package/dist/collab/index.js +7 -0
- package/dist/collab/index.js.map +1 -1
- package/dist/collab/presence-react.cjs +11 -11
- package/dist/collab/presence-react.cjs.map +1 -1
- package/dist/collab/react.cjs +6 -6
- package/dist/collab/react.cjs.map +1 -1
- package/dist/composer/AttachmentContext.cjs +24 -11
- package/dist/composer/AttachmentContext.cjs.map +1 -1
- package/dist/composer/AttachmentContext.js +18 -5
- package/dist/composer/AttachmentContext.js.map +1 -1
- package/dist/composer/ComposerAttachmentPreview.cjs +78 -23
- package/dist/composer/ComposerAttachmentPreview.cjs.map +1 -1
- package/dist/composer/ComposerAttachmentPreview.d.ts +5 -3
- package/dist/composer/ComposerAttachmentPreview.js +79 -24
- package/dist/composer/ComposerAttachmentPreview.js.map +1 -1
- package/dist/composer/ComposerDropZone.cjs +7 -7
- package/dist/composer/ComposerDropZone.cjs.map +1 -1
- package/dist/composer/FileUploadButton.cjs +37 -22
- package/dist/composer/FileUploadButton.cjs.map +1 -1
- package/dist/composer/FileUploadButton.d.ts +6 -0
- package/dist/composer/FileUploadButton.js +34 -19
- package/dist/composer/FileUploadButton.js.map +1 -1
- package/dist/composer/QuoteContext.cjs +8 -8
- package/dist/composer/QuoteContext.cjs.map +1 -1
- package/dist/composer/composer-handoff.cjs +4 -4
- package/dist/composer/composer-handoff.cjs.map +1 -1
- package/dist/composer/useAppendToComposer.cjs +4 -4
- package/dist/composer/useAppendToComposer.cjs.map +1 -1
- package/dist/composer/useAttachFiles.cjs +23 -6
- package/dist/composer/useAttachFiles.cjs.map +1 -1
- package/dist/composer/useAttachFiles.d.ts +15 -7
- package/dist/composer/useAttachFiles.js +22 -5
- package/dist/composer/useAttachFiles.js.map +1 -1
- package/dist/composer/useComposerAttachment.cjs +4 -4
- package/dist/composer/useComposerAttachment.cjs.map +1 -1
- package/dist/composer/useFileUpload.cjs +21 -16
- package/dist/composer/useFileUpload.cjs.map +1 -1
- package/dist/composer/useFileUpload.d.ts +12 -0
- package/dist/composer/useFileUpload.js +12 -7
- package/dist/composer/useFileUpload.js.map +1 -1
- package/dist/composer/useReadComposerDraft.cjs +2 -2
- package/dist/composer/useReadComposerDraft.cjs.map +1 -1
- package/dist/composer/useSendMessage.cjs +4 -4
- package/dist/composer/useSendMessage.cjs.map +1 -1
- package/dist/diagnostics/useAthenaDiagnostics.cjs +4 -4
- package/dist/diagnostics/useAthenaDiagnostics.cjs.map +1 -1
- package/dist/dictation/audio-level-history.cjs +3 -3
- package/dist/dictation/audio-level-history.cjs.map +1 -1
- package/dist/dictation/dictation-controls.cjs +24 -20
- package/dist/dictation/dictation-controls.cjs.map +1 -1
- package/dist/dictation/dictation-controls.d.ts +6 -1
- package/dist/dictation/dictation-controls.js +24 -20
- package/dist/dictation/dictation-controls.js.map +1 -1
- package/dist/dictation/use-athena-dictation-engine.cjs +3 -3
- package/dist/dictation/use-athena-dictation-engine.cjs.map +1 -1
- package/dist/dictation/use-dictation.cjs +22 -22
- package/dist/dictation/use-dictation.cjs.map +1 -1
- package/dist/index.cjs +26 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +15 -3
- package/dist/index.js +26 -2
- package/dist/index.js.map +1 -1
- package/dist/keryx-http/src/receive-only-socket.cjs +40 -0
- package/dist/keryx-http/src/receive-only-socket.cjs.map +1 -0
- package/dist/keryx-http/src/receive-only-socket.d.ts +27 -0
- package/dist/keryx-http/src/receive-only-socket.js +40 -0
- package/dist/keryx-http/src/receive-only-socket.js.map +1 -0
- package/dist/keryx-http/src/update-attributions.cjs +111 -0
- package/dist/keryx-http/src/update-attributions.cjs.map +1 -0
- package/dist/keryx-http/src/update-attributions.d.ts +75 -0
- package/dist/keryx-http/src/update-attributions.js +111 -0
- package/dist/keryx-http/src/update-attributions.js.map +1 -0
- package/dist/lib/owner-document.cjs +6 -6
- package/dist/lib/owner-document.cjs.map +1 -1
- package/dist/lib/use-athena-rest-query.cjs +4 -4
- package/dist/lib/use-athena-rest-query.cjs.map +1 -1
- package/dist/lib/use-document-active.cjs +4 -4
- package/dist/lib/use-document-active.cjs.map +1 -1
- package/dist/lib/use-prefers-reduced-motion.cjs +2 -2
- package/dist/lib/use-prefers-reduced-motion.cjs.map +1 -1
- package/dist/offline/offline-history.cjs +7 -7
- package/dist/offline/offline-history.cjs.map +1 -1
- package/dist/provider/AthenaContext.cjs +3 -3
- package/dist/provider/AthenaContext.cjs.map +1 -1
- package/dist/provider/AthenaProvider.cjs +116 -79
- package/dist/provider/AthenaProvider.cjs.map +1 -1
- package/dist/provider/AthenaProvider.js +40 -3
- package/dist/provider/AthenaProvider.js.map +1 -1
- package/dist/provider/PostHogProvider.cjs +2 -2
- package/dist/provider/PostHogProvider.cjs.map +1 -1
- package/dist/provider/agent-selection-context.cjs +2 -2
- package/dist/provider/agent-selection-context.cjs.map +1 -1
- package/dist/provider/chat-mode-context.cjs +2 -2
- package/dist/provider/chat-mode-context.cjs.map +1 -1
- package/dist/provider/session-persistence-context.cjs +10 -0
- package/dist/provider/session-persistence-context.cjs.map +1 -0
- package/dist/provider/session-persistence-context.d.ts +15 -0
- package/dist/provider/session-persistence-context.js +10 -0
- package/dist/provider/session-persistence-context.js.map +1 -0
- package/dist/provider/statewire-history-context.cjs +4 -4
- package/dist/provider/statewire-history-context.cjs.map +1 -1
- package/dist/provider/statewire-lifecycle-context.cjs +3 -3
- package/dist/provider/statewire-lifecycle-context.cjs.map +1 -1
- package/dist/provider/statewire-window-context.cjs +3 -3
- package/dist/provider/statewire-window-context.cjs.map +1 -1
- package/dist/provider/theme-style-context.cjs +3 -3
- package/dist/provider/theme-style-context.cjs.map +1 -1
- package/dist/react/package.json.cjs +1 -1
- package/dist/react/package.json.js +1 -1
- package/dist/references/src/tool-option-schemas.d.ts +0 -34
- package/dist/runtime/StatewireThreadConfigLaneSync.cjs +10 -10
- package/dist/runtime/StatewireThreadConfigLaneSync.cjs.map +1 -1
- package/dist/runtime/auth-refusal-restart.cjs +7 -7
- package/dist/runtime/auth-refusal-restart.cjs.map +1 -1
- package/dist/runtime/auth.cjs +13 -13
- package/dist/runtime/auth.cjs.map +1 -1
- package/dist/runtime/statewire-lifecycle.cjs +1 -0
- package/dist/runtime/statewire-lifecycle.cjs.map +1 -1
- package/dist/runtime/statewire-lifecycle.d.ts +3 -1
- package/dist/runtime/statewire-lifecycle.js +2 -1
- package/dist/runtime/statewire-lifecycle.js.map +1 -1
- package/dist/runtime/statewire-server-lane-context.cjs +2 -2
- package/dist/runtime/statewire-server-lane-context.cjs.map +1 -1
- package/dist/runtime/statewire-session-lane.cjs +4 -4
- package/dist/runtime/statewire-session-lane.cjs.map +1 -1
- package/dist/runtime/useAthenaStatewireRuntime.cjs +10 -8
- package/dist/runtime/useAthenaStatewireRuntime.cjs.map +1 -1
- package/dist/runtime/useAthenaStatewireRuntime.d.ts +2 -0
- package/dist/runtime/useAthenaStatewireRuntime.js +2 -0
- package/dist/runtime/useAthenaStatewireRuntime.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/threads/Inbox.cjs +8 -8
- package/dist/threads/Inbox.cjs.map +1 -1
- package/dist/threads/SessionList.cjs +9 -9
- package/dist/threads/SessionList.cjs.map +1 -1
- package/dist/threads/SessionsPage.cjs +11 -11
- package/dist/threads/SessionsPage.cjs.map +1 -1
- package/dist/threads/index-triggered-refresh.cjs +10 -10
- package/dist/threads/index-triggered-refresh.cjs.map +1 -1
- package/dist/threads/mark-viewed-thread-read.cjs +12 -12
- package/dist/threads/mark-viewed-thread-read.cjs.map +1 -1
- package/dist/threads/offline-session-list.cjs +3 -3
- package/dist/threads/offline-session-list.cjs.map +1 -1
- package/dist/threads/session-list-tab-share.cjs +5 -5
- package/dist/threads/session-list-tab-share.cjs.map +1 -1
- package/dist/threads/statewire-thread-list.cjs +55 -51
- package/dist/threads/statewire-thread-list.cjs.map +1 -1
- package/dist/threads/statewire-thread-list.js +6 -2
- package/dist/threads/statewire-thread-list.js.map +1 -1
- package/dist/threads/thread-id-context.cjs +5 -5
- package/dist/threads/thread-id-context.cjs.map +1 -1
- package/dist/threads/use-athena-session-attention.cjs +2 -2
- package/dist/threads/use-athena-session-attention.cjs.map +1 -1
- package/dist/threads/use-athena-sessions.cjs +10 -10
- package/dist/threads/use-athena-sessions.cjs.map +1 -1
- package/dist/threads/use-athena-thread-model.cjs +3 -3
- package/dist/threads/use-athena-thread-model.cjs.map +1 -1
- package/dist/threads/use-rest-conversation-history.cjs +3 -3
- package/dist/threads/use-rest-conversation-history.cjs.map +1 -1
- package/dist/threads/use-statewire-conversation-history.cjs +8 -8
- package/dist/threads/use-statewire-conversation-history.cjs.map +1 -1
- package/dist/threads/use-thread-archive.cjs +9 -9
- package/dist/threads/use-thread-archive.cjs.map +1 -1
- package/dist/threads/use-thread-favorite.cjs +2 -2
- package/dist/threads/use-thread-favorite.cjs.map +1 -1
- package/dist/threads/use-thread-field-override.cjs +20 -20
- package/dist/threads/use-thread-field-override.cjs.map +1 -1
- package/dist/threads/use-thread-read-state.cjs +4 -4
- package/dist/threads/use-thread-read-state.cjs.map +1 -1
- package/dist/threads/use-thread-rename.cjs +2 -2
- package/dist/threads/use-thread-rename.cjs.map +1 -1
- package/dist/threads/useAthenaThreadManager.cjs +2 -2
- package/dist/threads/useAthenaThreadManager.cjs.map +1 -1
- package/dist/tools/NestedPtcMessages.cjs +6 -6
- package/dist/tools/NestedPtcMessages.cjs.map +1 -1
- package/dist/tools/append-document-tool-ui.cjs +7 -7
- package/dist/tools/append-document-tool-ui.cjs.map +1 -1
- package/dist/tools/file-tool-uis.cjs +2 -2
- package/dist/tools/file-tool-uis.cjs.map +1 -1
- package/dist/tools/misc-tool-uis.cjs +2 -2
- package/dist/tools/misc-tool-uis.cjs.map +1 -1
- package/dist/tools/primitives.cjs +6 -6
- package/dist/tools/primitives.cjs.map +1 -1
- package/dist/tools/read-asset-tool-ui.cjs +6 -6
- package/dist/tools/read-asset-tool-ui.cjs.map +1 -1
- package/dist/tools/subagent-task-tool-ui.cjs +21 -21
- package/dist/tools/subagent-task-tool-ui.cjs.map +1 -1
- package/dist/tools/test-recording-tool-uis.cjs +16 -16
- package/dist/tools/test-recording-tool-uis.cjs.map +1 -1
- package/dist/tools/todo-plan-store.cjs +4 -4
- package/dist/tools/todo-plan-store.cjs.map +1 -1
- package/dist/tools/tool-appearance.cjs +3 -3
- package/dist/tools/tool-appearance.cjs.map +1 -1
- package/dist/tools/tool-fallback.cjs +14 -14
- package/dist/tools/tool-fallback.cjs.map +1 -1
- package/dist/tools/tool-summary.cjs +0 -2
- package/dist/tools/tool-summary.cjs.map +1 -1
- package/dist/tools/tool-summary.js +0 -2
- package/dist/tools/tool-summary.js.map +1 -1
- package/dist/tools/tool-uis.cjs +74 -74
- package/dist/tools/tool-uis.cjs.map +1 -1
- package/dist/tools/use-elapsed-seconds.cjs +3 -3
- package/dist/tools/use-elapsed-seconds.cjs.map +1 -1
- package/dist/tools/write-todos-tool-ui.cjs +9 -9
- package/dist/tools/write-todos-tool-ui.cjs.map +1 -1
- package/dist/ui/image-viewer.cjs +382 -0
- package/dist/ui/image-viewer.cjs.map +1 -0
- package/dist/ui/image-viewer.d.ts +50 -0
- package/dist/ui/image-viewer.js +382 -0
- package/dist/ui/image-viewer.js.map +1 -0
- package/dist/voice/chat.cjs +6 -0
- package/dist/voice/chat.cjs.map +1 -1
- package/dist/voice/chat.d.ts +1 -1
- package/dist/voice/chat.js +8 -2
- package/dist/voice/livekit-join.cjs +52 -101
- package/dist/voice/livekit-join.cjs.map +1 -1
- package/dist/voice/livekit-join.d.ts +1 -6
- package/dist/voice/livekit-join.js +52 -101
- package/dist/voice/livekit-join.js.map +1 -1
- package/dist/voice/livekit.cjs.map +1 -1
- package/dist/voice/livekit.d.ts +11 -1
- package/dist/voice/livekit.js.map +1 -1
- package/dist/voice/use-athena-voice-session.cjs +34 -34
- package/dist/voice/use-athena-voice-session.cjs.map +1 -1
- package/dist/workbench/ComputerLiveDesktop.cjs +13 -13
- package/dist/workbench/ComputerLiveDesktop.cjs.map +1 -1
- package/dist/workbench/SessionWorkbench.cjs +22 -22
- package/dist/workbench/SessionWorkbench.cjs.map +1 -1
- package/dist/workbench/session-workbench-context.cjs +3 -3
- package/dist/workbench/session-workbench-context.cjs.map +1 -1
- package/dist/workbench/session-workbench-panes.cjs +8 -8
- package/dist/workbench/session-workbench-panes.cjs.map +1 -1
- package/dist/workbench/workbench-layout-context.cjs +3 -3
- package/dist/workbench/workbench-layout-context.cjs.map +1 -1
- package/package.json +2 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
|
-
const
|
|
4
|
+
const require$$0 = require("react");
|
|
5
5
|
const AttachmentContext = require("./AttachmentContext.cjs");
|
|
6
6
|
const useAttachFiles = require("./useAttachFiles.cjs");
|
|
7
7
|
const cnfast = require("cnfast");
|
|
@@ -11,23 +11,23 @@ const ComposerDropZone = ({
|
|
|
11
11
|
onUpload,
|
|
12
12
|
onDragActiveChange
|
|
13
13
|
}) => {
|
|
14
|
-
const [isDragOver, setIsDragOver] =
|
|
14
|
+
const [isDragOver, setIsDragOver] = require$$0.useState(false);
|
|
15
15
|
const { attachFiles } = useAttachFiles.useAttachFiles();
|
|
16
16
|
const { isUploading } = AttachmentContext.useAttachments();
|
|
17
|
-
const onDragActiveChangeRef =
|
|
17
|
+
const onDragActiveChangeRef = require$$0.useRef(onDragActiveChange);
|
|
18
18
|
onDragActiveChangeRef.current = onDragActiveChange;
|
|
19
|
-
|
|
19
|
+
require$$0.useEffect(() => {
|
|
20
20
|
var _a;
|
|
21
21
|
(_a = onDragActiveChangeRef.current) == null ? void 0 : _a.call(onDragActiveChangeRef, isDragOver);
|
|
22
22
|
}, [isDragOver]);
|
|
23
|
-
const handleDragOver =
|
|
23
|
+
const handleDragOver = require$$0.useCallback((e) => {
|
|
24
24
|
e.preventDefault();
|
|
25
25
|
e.stopPropagation();
|
|
26
26
|
if (e.dataTransfer.types.includes("Files")) {
|
|
27
27
|
setIsDragOver(true);
|
|
28
28
|
}
|
|
29
29
|
}, []);
|
|
30
|
-
const handleDragLeave =
|
|
30
|
+
const handleDragLeave = require$$0.useCallback((e) => {
|
|
31
31
|
e.preventDefault();
|
|
32
32
|
e.stopPropagation();
|
|
33
33
|
const rect = e.currentTarget.getBoundingClientRect();
|
|
@@ -36,7 +36,7 @@ const ComposerDropZone = ({
|
|
|
36
36
|
setIsDragOver(false);
|
|
37
37
|
}
|
|
38
38
|
}, []);
|
|
39
|
-
const handleDrop =
|
|
39
|
+
const handleDrop = require$$0.useCallback(
|
|
40
40
|
async (e) => {
|
|
41
41
|
e.preventDefault();
|
|
42
42
|
e.stopPropagation();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComposerDropZone.cjs","sources":["../../src/composer/ComposerDropZone.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useRef,\n useState,\n type DragEvent,\n type FC,\n type ReactNode,\n} from 'react';\nimport { useAttachments } from './AttachmentContext';\nimport { useAttachFiles } from './useAttachFiles';\nimport type { UploadedAsset } from './useFileUpload';\nimport { cn } from '../lib/utils';\n\nexport interface ComposerDropZoneProps {\n children: ReactNode;\n className?: string;\n /** Called after files are uploaded via drag-and-drop. */\n onUpload?: (assets: UploadedAsset[]) => void;\n /**\n * Reports whether files are being dragged over the zone, so the composer\n * surface inside can tint itself (`ChatComposerDock dragActive`). Called\n * with `false` on mount and again on every change.\n */\n onDragActiveChange?: (active: boolean) => void;\n}\n\n/**\n * Wraps the composer area with drag-and-drop file upload support.\n * Shows a visual drop indicator when files are dragged over.\n */\nexport const ComposerDropZone: FC<ComposerDropZoneProps> = ({\n children,\n className,\n onUpload,\n onDragActiveChange,\n}) => {\n const [isDragOver, setIsDragOver] = useState(false);\n const { attachFiles } = useAttachFiles();\n const { isUploading } = useAttachments();\n\n const onDragActiveChangeRef = useRef(onDragActiveChange);\n onDragActiveChangeRef.current = onDragActiveChange;\n useEffect(() => {\n onDragActiveChangeRef.current?.(isDragOver);\n }, [isDragOver]);\n\n const handleDragOver = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n if (e.dataTransfer.types.includes('Files')) {\n setIsDragOver(true);\n }\n }, []);\n\n const handleDragLeave = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();\n const { clientX, clientY } = e;\n if (\n clientX < rect.left ||\n clientX > rect.right ||\n clientY < rect.top ||\n clientY > rect.bottom\n ) {\n setIsDragOver(false);\n }\n }, []);\n\n const handleDrop = useCallback(\n async (e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragOver(false);\n\n const files = Array.from(e.dataTransfer.files);\n if (files.length === 0) return;\n\n const assets = await attachFiles(files, 'drop');\n if (assets.length > 0) {\n onUpload?.(assets);\n }\n },\n [attachFiles, onUpload],\n );\n\n return (\n <div\n className={cn('relative', className)}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n >\n {children}\n {isDragOver && !isUploading && (\n <div className=\"aui-drop-overlay pointer-events-none absolute inset-0 z-20 flex items-center justify-center rounded-2xl border-2 border-dashed border-primary/50 bg-primary/5\">\n <span className=\"text-sm font-medium text-primary\">Drop files to upload</span>\n </div>\n )}\n </div>\n );\n};\n"],"names":["useState","useAttachFiles","useAttachments","useRef","useEffect","useCallback","jsxs","cn","jsx"],"mappings":";;;;;;;AA+BO,MAAM,mBAA8C,CAAC;AAAA,EAC1D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,CAAC,YAAY,aAAa,IAAIA,
|
|
1
|
+
{"version":3,"file":"ComposerDropZone.cjs","sources":["../../src/composer/ComposerDropZone.tsx"],"sourcesContent":["import {\n useCallback,\n useEffect,\n useRef,\n useState,\n type DragEvent,\n type FC,\n type ReactNode,\n} from 'react';\nimport { useAttachments } from './AttachmentContext';\nimport { useAttachFiles } from './useAttachFiles';\nimport type { UploadedAsset } from './useFileUpload';\nimport { cn } from '../lib/utils';\n\nexport interface ComposerDropZoneProps {\n children: ReactNode;\n className?: string;\n /** Called after files are uploaded via drag-and-drop. */\n onUpload?: (assets: UploadedAsset[]) => void;\n /**\n * Reports whether files are being dragged over the zone, so the composer\n * surface inside can tint itself (`ChatComposerDock dragActive`). Called\n * with `false` on mount and again on every change.\n */\n onDragActiveChange?: (active: boolean) => void;\n}\n\n/**\n * Wraps the composer area with drag-and-drop file upload support.\n * Shows a visual drop indicator when files are dragged over.\n */\nexport const ComposerDropZone: FC<ComposerDropZoneProps> = ({\n children,\n className,\n onUpload,\n onDragActiveChange,\n}) => {\n const [isDragOver, setIsDragOver] = useState(false);\n const { attachFiles } = useAttachFiles();\n const { isUploading } = useAttachments();\n\n const onDragActiveChangeRef = useRef(onDragActiveChange);\n onDragActiveChangeRef.current = onDragActiveChange;\n useEffect(() => {\n onDragActiveChangeRef.current?.(isDragOver);\n }, [isDragOver]);\n\n const handleDragOver = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n if (e.dataTransfer.types.includes('Files')) {\n setIsDragOver(true);\n }\n }, []);\n\n const handleDragLeave = useCallback((e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n const rect = (e.currentTarget as HTMLElement).getBoundingClientRect();\n const { clientX, clientY } = e;\n if (\n clientX < rect.left ||\n clientX > rect.right ||\n clientY < rect.top ||\n clientY > rect.bottom\n ) {\n setIsDragOver(false);\n }\n }, []);\n\n const handleDrop = useCallback(\n async (e: DragEvent) => {\n e.preventDefault();\n e.stopPropagation();\n setIsDragOver(false);\n\n const files = Array.from(e.dataTransfer.files);\n if (files.length === 0) return;\n\n const assets = await attachFiles(files, 'drop');\n if (assets.length > 0) {\n onUpload?.(assets);\n }\n },\n [attachFiles, onUpload],\n );\n\n return (\n <div\n className={cn('relative', className)}\n onDragOver={handleDragOver}\n onDragLeave={handleDragLeave}\n onDrop={handleDrop}\n >\n {children}\n {isDragOver && !isUploading && (\n <div className=\"aui-drop-overlay pointer-events-none absolute inset-0 z-20 flex items-center justify-center rounded-2xl border-2 border-dashed border-primary/50 bg-primary/5\">\n <span className=\"text-sm font-medium text-primary\">Drop files to upload</span>\n </div>\n )}\n </div>\n );\n};\n"],"names":["useState","useAttachFiles","useAttachments","useRef","useEffect","useCallback","jsxs","cn","jsx"],"mappings":";;;;;;;AA+BO,MAAM,mBAA8C,CAAC;AAAA,EAC1D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;AACJ,QAAM,CAAC,YAAY,aAAa,IAAIA,WAAAA,SAAS,KAAK;AAClD,QAAM,EAAE,YAAA,IAAgBC,8BAAA;AACxB,QAAM,EAAE,YAAA,IAAgBC,iCAAA;AAExB,QAAM,wBAAwBC,WAAAA,OAAO,kBAAkB;AACvD,wBAAsB,UAAU;AAChCC,aAAAA,UAAU,MAAM;;AACd,gCAAsB,YAAtB,+CAAgC;AAAA,EAClC,GAAG,CAAC,UAAU,CAAC;AAEf,QAAM,iBAAiBC,uBAAY,CAAC,MAAiB;AACnD,MAAE,eAAA;AACF,MAAE,gBAAA;AACF,QAAI,EAAE,aAAa,MAAM,SAAS,OAAO,GAAG;AAC1C,oBAAc,IAAI;AAAA,IACpB;AAAA,EACF,GAAG,CAAA,CAAE;AAEL,QAAM,kBAAkBA,uBAAY,CAAC,MAAiB;AACpD,MAAE,eAAA;AACF,MAAE,gBAAA;AACF,UAAM,OAAQ,EAAE,cAA8B,sBAAA;AAC9C,UAAM,EAAE,SAAS,QAAA,IAAY;AAC7B,QACE,UAAU,KAAK,QACf,UAAU,KAAK,SACf,UAAU,KAAK,OACf,UAAU,KAAK,QACf;AACA,oBAAc,KAAK;AAAA,IACrB;AAAA,EACF,GAAG,CAAA,CAAE;AAEL,QAAM,aAAaA,WAAAA;AAAAA,IACjB,OAAO,MAAiB;AACtB,QAAE,eAAA;AACF,QAAE,gBAAA;AACF,oBAAc,KAAK;AAEnB,YAAM,QAAQ,MAAM,KAAK,EAAE,aAAa,KAAK;AAC7C,UAAI,MAAM,WAAW,EAAG;AAExB,YAAM,SAAS,MAAM,YAAY,OAAO,MAAM;AAC9C,UAAI,OAAO,SAAS,GAAG;AACrB,6CAAW;AAAA,MACb;AAAA,IACF;AAAA,IACA,CAAC,aAAa,QAAQ;AAAA,EAAA;AAGxB,SACEC,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,WAAWC,OAAAA,GAAG,YAAY,SAAS;AAAA,MACnC,YAAY;AAAA,MACZ,aAAa;AAAA,MACb,QAAQ;AAAA,MAEP,UAAA;AAAA,QAAA;AAAA,QACA,cAAc,CAAC,eACdC,2BAAAA,IAAC,OAAA,EAAI,WAAU,iKACb,UAAAA,2BAAAA,IAAC,QAAA,EAAK,WAAU,oCAAmC,UAAA,uBAAA,CAAoB,EAAA,CACzE;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAIR;;"}
|
|
@@ -2,22 +2,26 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
4
|
const lucideReact = require("lucide-react");
|
|
5
|
-
const
|
|
5
|
+
const require$$0 = require("react");
|
|
6
6
|
const useAttachFiles = require("./useAttachFiles.cjs");
|
|
7
|
+
const tooltip = require("../ui/tooltip.cjs");
|
|
7
8
|
const cnfast = require("cnfast");
|
|
8
9
|
const FileUploadButton = ({
|
|
9
10
|
className,
|
|
10
11
|
onUpload,
|
|
11
|
-
accept
|
|
12
|
+
accept,
|
|
13
|
+
disabledReason = null
|
|
12
14
|
}) => {
|
|
13
|
-
const inputRef =
|
|
15
|
+
const inputRef = require$$0.useRef(null);
|
|
14
16
|
const { attachFiles, isUploading, error, clearError } = useAttachFiles.useAttachFiles();
|
|
15
|
-
const
|
|
17
|
+
const unavailable = Boolean(disabledReason);
|
|
18
|
+
const handleClick = require$$0.useCallback(() => {
|
|
16
19
|
var _a;
|
|
20
|
+
if (unavailable) return;
|
|
17
21
|
clearError();
|
|
18
22
|
(_a = inputRef.current) == null ? void 0 : _a.click();
|
|
19
|
-
}, [clearError]);
|
|
20
|
-
const handleFiles =
|
|
23
|
+
}, [clearError, unavailable]);
|
|
24
|
+
const handleFiles = require$$0.useCallback(
|
|
21
25
|
async (files) => {
|
|
22
26
|
if (!files || files.length === 0) return;
|
|
23
27
|
const assets = await attachFiles(Array.from(files), "paperclip");
|
|
@@ -30,6 +34,25 @@ const FileUploadButton = ({
|
|
|
30
34
|
},
|
|
31
35
|
[attachFiles, onUpload]
|
|
32
36
|
);
|
|
37
|
+
const button = /* @__PURE__ */ jsxRuntime.jsx(
|
|
38
|
+
"button",
|
|
39
|
+
{
|
|
40
|
+
type: "button",
|
|
41
|
+
onClick: handleClick,
|
|
42
|
+
disabled: isUploading,
|
|
43
|
+
"aria-disabled": unavailable || void 0,
|
|
44
|
+
"data-unavailable": unavailable || void 0,
|
|
45
|
+
className: cnfast.cn(
|
|
46
|
+
"aui-file-upload-btn flex items-center justify-center rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-50 disabled:pointer-events-none",
|
|
47
|
+
error && "text-destructive",
|
|
48
|
+
className,
|
|
49
|
+
unavailable && "cursor-not-allowed opacity-30 hover:bg-transparent hover:text-muted-foreground"
|
|
50
|
+
),
|
|
51
|
+
title: unavailable ? void 0 : error ?? (isUploading ? "Uploading..." : "Attach files"),
|
|
52
|
+
"aria-label": isUploading ? "Uploading files" : "Attach files",
|
|
53
|
+
children: isUploading ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2Icon, { className: "size-4 animate-spin" }) : error ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircleIcon, { className: "size-4" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PaperclipIcon, { className: "size-4" })
|
|
54
|
+
}
|
|
55
|
+
);
|
|
33
56
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
34
57
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
35
58
|
"input",
|
|
@@ -43,22 +66,14 @@ const FileUploadButton = ({
|
|
|
43
66
|
"aria-label": "Upload files"
|
|
44
67
|
}
|
|
45
68
|
),
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
error && "text-destructive",
|
|
55
|
-
className
|
|
56
|
-
),
|
|
57
|
-
title: error ?? (isUploading ? "Uploading..." : "Attach files"),
|
|
58
|
-
"aria-label": isUploading ? "Uploading files" : "Attach files",
|
|
59
|
-
children: isUploading ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Loader2Icon, { className: "size-4 animate-spin" }) : error ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertCircleIcon, { className: "size-4" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.PaperclipIcon, { className: "size-4" })
|
|
60
|
-
}
|
|
61
|
-
)
|
|
69
|
+
unavailable ? (
|
|
70
|
+
// The reason in the SDK's tooltip, which opens on keyboard focus as well as on hover (a
|
|
71
|
+
// native title shows only to a pointer).
|
|
72
|
+
/* @__PURE__ */ jsxRuntime.jsxs(tooltip.Tooltip, { children: [
|
|
73
|
+
/* @__PURE__ */ jsxRuntime.jsx(tooltip.TooltipTrigger, { asChild: true, children: button }),
|
|
74
|
+
/* @__PURE__ */ jsxRuntime.jsx(tooltip.TooltipContent, { side: "bottom", children: disabledReason })
|
|
75
|
+
] })
|
|
76
|
+
) : button
|
|
62
77
|
] });
|
|
63
78
|
};
|
|
64
79
|
exports.FileUploadButton = FileUploadButton;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileUploadButton.cjs","sources":["../../src/composer/FileUploadButton.tsx"],"sourcesContent":["import { PaperclipIcon, Loader2Icon, AlertCircleIcon } from 'lucide-react';\nimport { useCallback, useRef, type FC } from 'react';\nimport { useAttachFiles } from './useAttachFiles';\nimport type { UploadedAsset } from './useFileUpload';\nimport { cn } from '../lib/utils';\n\nexport interface FileUploadButtonProps {\n className?: string;\n /** Called after files are uploaded successfully. Receives the created assets. */\n onUpload?: (assets: UploadedAsset[]) => void;\n /** Accepted file types (MIME pattern). Defaults to all files. */\n accept?: string;\n}\n\n/**\n * Paperclip button that opens a file picker and uploads selected files to Athena.\n * After upload, adds files to the attachment context so they appear as pills\n * above the composer and get included when the message is sent.\n */\nexport const FileUploadButton: FC<FileUploadButtonProps> = ({\n className,\n onUpload,\n accept,\n}) => {\n const inputRef = useRef<HTMLInputElement>(null);\n const { attachFiles, isUploading, error, clearError } = useAttachFiles();\n\n const handleClick = useCallback(() => {\n clearError();\n inputRef.current?.click();\n }, [clearError]);\n\n const handleFiles = useCallback(\n async (files: FileList | null) => {\n if (!files || files.length === 0) return;\n\n const assets = await attachFiles(Array.from(files), 'paperclip');\n if (assets.length > 0) {\n onUpload?.(assets);\n }\n\n // Reset input so the same file can be re-selected\n if (inputRef.current) {\n inputRef.current.value = '';\n }\n },\n [attachFiles, onUpload],\n );\n\n
|
|
1
|
+
{"version":3,"file":"FileUploadButton.cjs","sources":["../../src/composer/FileUploadButton.tsx"],"sourcesContent":["import { PaperclipIcon, Loader2Icon, AlertCircleIcon } from 'lucide-react';\nimport { useCallback, useRef, type FC } from 'react';\nimport { useAttachFiles } from './useAttachFiles';\nimport type { UploadedAsset } from './useFileUpload';\nimport { cn } from '../lib/utils';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip';\n\nexport interface FileUploadButtonProps {\n className?: string;\n /** Called after files are uploaded successfully. Receives the created assets. */\n onUpload?: (assets: UploadedAsset[]) => void;\n /** Accepted file types (MIME pattern). Defaults to all files. */\n accept?: string;\n /**\n * Why attaching is off right now, e.g. \"Needs a connection…\" while the host knows Athena can't be\n * reached: the button shows disabled with this in its tooltip and the file picker does not open.\n * It stays focusable, and the tooltip opens on keyboard focus as on hover. `null` or absent: on.\n */\n disabledReason?: string | null;\n}\n\n/**\n * Paperclip button that opens a file picker and uploads selected files to Athena.\n * After upload, adds files to the attachment context so they appear as pills\n * above the composer and get included when the message is sent.\n */\nexport const FileUploadButton: FC<FileUploadButtonProps> = ({\n className,\n onUpload,\n accept,\n disabledReason = null,\n}) => {\n const inputRef = useRef<HTMLInputElement>(null);\n const { attachFiles, isUploading, error, clearError } = useAttachFiles();\n const unavailable = Boolean(disabledReason);\n\n const handleClick = useCallback(() => {\n if (unavailable) return;\n clearError();\n inputRef.current?.click();\n }, [clearError, unavailable]);\n\n const handleFiles = useCallback(\n async (files: FileList | null) => {\n if (!files || files.length === 0) return;\n\n const assets = await attachFiles(Array.from(files), 'paperclip');\n if (assets.length > 0) {\n onUpload?.(assets);\n }\n\n // Reset input so the same file can be re-selected\n if (inputRef.current) {\n inputRef.current.value = '';\n }\n },\n [attachFiles, onUpload],\n );\n\n const button = (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={isUploading}\n // Off with a reason, it keeps its pointer and its focus: the reason has to be readable.\n aria-disabled={unavailable || undefined}\n data-unavailable={unavailable || undefined}\n className={cn(\n 'aui-file-upload-btn flex items-center justify-center rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-50 disabled:pointer-events-none',\n error && 'text-destructive',\n className,\n unavailable &&\n 'cursor-not-allowed opacity-30 hover:bg-transparent hover:text-muted-foreground',\n )}\n title={unavailable ? undefined : (error ?? (isUploading ? 'Uploading...' : 'Attach files'))}\n aria-label={isUploading ? 'Uploading files' : 'Attach files'}\n >\n {isUploading ? (\n <Loader2Icon className=\"size-4 animate-spin\" />\n ) : error ? (\n <AlertCircleIcon className=\"size-4\" />\n ) : (\n <PaperclipIcon className=\"size-4\" />\n )}\n </button>\n );\n\n return (\n <>\n <input\n ref={inputRef}\n type=\"file\"\n multiple\n accept={accept}\n className=\"hidden\"\n onChange={(e) => handleFiles(e.target.files)}\n aria-label=\"Upload files\"\n />\n {unavailable ? (\n // The reason in the SDK's tooltip, which opens on keyboard focus as well as on hover (a\n // native title shows only to a pointer).\n <Tooltip>\n <TooltipTrigger asChild>{button}</TooltipTrigger>\n <TooltipContent side=\"bottom\">{disabledReason}</TooltipContent>\n </Tooltip>\n ) : (\n button\n )}\n </>\n );\n};\n"],"names":["useRef","useAttachFiles","useCallback","jsx","cn","Loader2Icon","AlertCircleIcon","PaperclipIcon","jsxs","Fragment","Tooltip","TooltipTrigger","TooltipContent"],"mappings":";;;;;;;;AA0BO,MAAM,mBAA8C,CAAC;AAAA,EAC1D;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAiB;AACnB,MAAM;AACJ,QAAM,WAAWA,WAAAA,OAAyB,IAAI;AAC9C,QAAM,EAAE,aAAa,aAAa,OAAO,WAAA,IAAeC,eAAAA,eAAA;AACxD,QAAM,cAAc,QAAQ,cAAc;AAE1C,QAAM,cAAcC,WAAAA,YAAY,MAAM;;AACpC,QAAI,YAAa;AACjB,eAAA;AACA,mBAAS,YAAT,mBAAkB;AAAA,EACpB,GAAG,CAAC,YAAY,WAAW,CAAC;AAE5B,QAAM,cAAcA,WAAAA;AAAAA,IAClB,OAAO,UAA2B;AAChC,UAAI,CAAC,SAAS,MAAM,WAAW,EAAG;AAElC,YAAM,SAAS,MAAM,YAAY,MAAM,KAAK,KAAK,GAAG,WAAW;AAC/D,UAAI,OAAO,SAAS,GAAG;AACrB,6CAAW;AAAA,MACb;AAGA,UAAI,SAAS,SAAS;AACpB,iBAAS,QAAQ,QAAQ;AAAA,MAC3B;AAAA,IACF;AAAA,IACA,CAAC,aAAa,QAAQ;AAAA,EAAA;AAGxB,QAAM,SACJC,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,SAAS;AAAA,MACT,UAAU;AAAA,MAEV,iBAAe,eAAe;AAAA,MAC9B,oBAAkB,eAAe;AAAA,MACjC,WAAWC,OAAAA;AAAAA,QACT;AAAA,QACA,SAAS;AAAA,QACT;AAAA,QACA,eACE;AAAA,MAAA;AAAA,MAEJ,OAAO,cAAc,SAAa,UAAU,cAAc,iBAAiB;AAAA,MAC3E,cAAY,cAAc,oBAAoB;AAAA,MAE7C,UAAA,cACCD,2BAAAA,IAACE,YAAAA,aAAA,EAAY,WAAU,uBAAsB,IAC3C,QACFF,2BAAAA,IAACG,YAAAA,iBAAA,EAAgB,WAAU,UAAS,IAEpCH,2BAAAA,IAACI,2BAAA,EAAc,WAAU,SAAA,CAAS;AAAA,IAAA;AAAA,EAAA;AAKxC,SACEC,2BAAAA,KAAAC,qBAAA,EACE,UAAA;AAAA,IAAAN,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAK;AAAA,QACL,MAAK;AAAA,QACL,UAAQ;AAAA,QACR;AAAA,QACA,WAAU;AAAA,QACV,UAAU,CAAC,MAAM,YAAY,EAAE,OAAO,KAAK;AAAA,QAC3C,cAAW;AAAA,MAAA;AAAA,IAAA;AAAA,IAEZ;AAAA;AAAA;AAAA,sCAGEO,QAAAA,SAAA,EACC,UAAA;AAAA,QAAAP,2BAAAA,IAACQ,QAAAA,gBAAA,EAAe,SAAO,MAAE,UAAA,QAAO;AAAA,QAChCR,2BAAAA,IAACS,QAAAA,gBAAA,EAAe,MAAK,UAAU,UAAA,eAAA,CAAe;AAAA,MAAA,EAAA,CAChD;AAAA,QAEA;AAAA,EAAA,GAEJ;AAEJ;;"}
|
|
@@ -6,6 +6,12 @@ export interface FileUploadButtonProps {
|
|
|
6
6
|
onUpload?: (assets: UploadedAsset[]) => void;
|
|
7
7
|
/** Accepted file types (MIME pattern). Defaults to all files. */
|
|
8
8
|
accept?: string;
|
|
9
|
+
/**
|
|
10
|
+
* Why attaching is off right now, e.g. "Needs a connection…" while the host knows Athena can't be
|
|
11
|
+
* reached: the button shows disabled with this in its tooltip and the file picker does not open.
|
|
12
|
+
* It stays focusable, and the tooltip opens on keyboard focus as on hover. `null` or absent: on.
|
|
13
|
+
*/
|
|
14
|
+
disabledReason?: string | null;
|
|
9
15
|
}
|
|
10
16
|
/**
|
|
11
17
|
* Paperclip button that opens a file picker and uploads selected files to Athena.
|
|
@@ -1,20 +1,24 @@
|
|
|
1
|
-
import { jsxs, Fragment
|
|
1
|
+
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { Loader2Icon, AlertCircleIcon, PaperclipIcon } from "lucide-react";
|
|
3
3
|
import { useRef, useCallback } from "react";
|
|
4
4
|
import { useAttachFiles } from "./useAttachFiles.js";
|
|
5
|
+
import { Tooltip, TooltipTrigger, TooltipContent } from "../ui/tooltip.js";
|
|
5
6
|
import { cn } from "cnfast";
|
|
6
7
|
const FileUploadButton = ({
|
|
7
8
|
className,
|
|
8
9
|
onUpload,
|
|
9
|
-
accept
|
|
10
|
+
accept,
|
|
11
|
+
disabledReason = null
|
|
10
12
|
}) => {
|
|
11
13
|
const inputRef = useRef(null);
|
|
12
14
|
const { attachFiles, isUploading, error, clearError } = useAttachFiles();
|
|
15
|
+
const unavailable = Boolean(disabledReason);
|
|
13
16
|
const handleClick = useCallback(() => {
|
|
14
17
|
var _a;
|
|
18
|
+
if (unavailable) return;
|
|
15
19
|
clearError();
|
|
16
20
|
(_a = inputRef.current) == null ? void 0 : _a.click();
|
|
17
|
-
}, [clearError]);
|
|
21
|
+
}, [clearError, unavailable]);
|
|
18
22
|
const handleFiles = useCallback(
|
|
19
23
|
async (files) => {
|
|
20
24
|
if (!files || files.length === 0) return;
|
|
@@ -28,6 +32,25 @@ const FileUploadButton = ({
|
|
|
28
32
|
},
|
|
29
33
|
[attachFiles, onUpload]
|
|
30
34
|
);
|
|
35
|
+
const button = /* @__PURE__ */ jsx(
|
|
36
|
+
"button",
|
|
37
|
+
{
|
|
38
|
+
type: "button",
|
|
39
|
+
onClick: handleClick,
|
|
40
|
+
disabled: isUploading,
|
|
41
|
+
"aria-disabled": unavailable || void 0,
|
|
42
|
+
"data-unavailable": unavailable || void 0,
|
|
43
|
+
className: cn(
|
|
44
|
+
"aui-file-upload-btn flex items-center justify-center rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-50 disabled:pointer-events-none",
|
|
45
|
+
error && "text-destructive",
|
|
46
|
+
className,
|
|
47
|
+
unavailable && "cursor-not-allowed opacity-30 hover:bg-transparent hover:text-muted-foreground"
|
|
48
|
+
),
|
|
49
|
+
title: unavailable ? void 0 : error ?? (isUploading ? "Uploading..." : "Attach files"),
|
|
50
|
+
"aria-label": isUploading ? "Uploading files" : "Attach files",
|
|
51
|
+
children: isUploading ? /* @__PURE__ */ jsx(Loader2Icon, { className: "size-4 animate-spin" }) : error ? /* @__PURE__ */ jsx(AlertCircleIcon, { className: "size-4" }) : /* @__PURE__ */ jsx(PaperclipIcon, { className: "size-4" })
|
|
52
|
+
}
|
|
53
|
+
);
|
|
31
54
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
32
55
|
/* @__PURE__ */ jsx(
|
|
33
56
|
"input",
|
|
@@ -41,22 +64,14 @@ const FileUploadButton = ({
|
|
|
41
64
|
"aria-label": "Upload files"
|
|
42
65
|
}
|
|
43
66
|
),
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
error && "text-destructive",
|
|
53
|
-
className
|
|
54
|
-
),
|
|
55
|
-
title: error ?? (isUploading ? "Uploading..." : "Attach files"),
|
|
56
|
-
"aria-label": isUploading ? "Uploading files" : "Attach files",
|
|
57
|
-
children: isUploading ? /* @__PURE__ */ jsx(Loader2Icon, { className: "size-4 animate-spin" }) : error ? /* @__PURE__ */ jsx(AlertCircleIcon, { className: "size-4" }) : /* @__PURE__ */ jsx(PaperclipIcon, { className: "size-4" })
|
|
58
|
-
}
|
|
59
|
-
)
|
|
67
|
+
unavailable ? (
|
|
68
|
+
// The reason in the SDK's tooltip, which opens on keyboard focus as well as on hover (a
|
|
69
|
+
// native title shows only to a pointer).
|
|
70
|
+
/* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
71
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: button }),
|
|
72
|
+
/* @__PURE__ */ jsx(TooltipContent, { side: "bottom", children: disabledReason })
|
|
73
|
+
] })
|
|
74
|
+
) : button
|
|
60
75
|
] });
|
|
61
76
|
};
|
|
62
77
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FileUploadButton.js","sources":["../../src/composer/FileUploadButton.tsx"],"sourcesContent":["import { PaperclipIcon, Loader2Icon, AlertCircleIcon } from 'lucide-react';\nimport { useCallback, useRef, type FC } from 'react';\nimport { useAttachFiles } from './useAttachFiles';\nimport type { UploadedAsset } from './useFileUpload';\nimport { cn } from '../lib/utils';\n\nexport interface FileUploadButtonProps {\n className?: string;\n /** Called after files are uploaded successfully. Receives the created assets. */\n onUpload?: (assets: UploadedAsset[]) => void;\n /** Accepted file types (MIME pattern). Defaults to all files. */\n accept?: string;\n}\n\n/**\n * Paperclip button that opens a file picker and uploads selected files to Athena.\n * After upload, adds files to the attachment context so they appear as pills\n * above the composer and get included when the message is sent.\n */\nexport const FileUploadButton: FC<FileUploadButtonProps> = ({\n className,\n onUpload,\n accept,\n}) => {\n const inputRef = useRef<HTMLInputElement>(null);\n const { attachFiles, isUploading, error, clearError } = useAttachFiles();\n\n const handleClick = useCallback(() => {\n clearError();\n inputRef.current?.click();\n }, [clearError]);\n\n const handleFiles = useCallback(\n async (files: FileList | null) => {\n if (!files || files.length === 0) return;\n\n const assets = await attachFiles(Array.from(files), 'paperclip');\n if (assets.length > 0) {\n onUpload?.(assets);\n }\n\n // Reset input so the same file can be re-selected\n if (inputRef.current) {\n inputRef.current.value = '';\n }\n },\n [attachFiles, onUpload],\n );\n\n
|
|
1
|
+
{"version":3,"file":"FileUploadButton.js","sources":["../../src/composer/FileUploadButton.tsx"],"sourcesContent":["import { PaperclipIcon, Loader2Icon, AlertCircleIcon } from 'lucide-react';\nimport { useCallback, useRef, type FC } from 'react';\nimport { useAttachFiles } from './useAttachFiles';\nimport type { UploadedAsset } from './useFileUpload';\nimport { cn } from '../lib/utils';\nimport { Tooltip, TooltipContent, TooltipTrigger } from '../ui/tooltip';\n\nexport interface FileUploadButtonProps {\n className?: string;\n /** Called after files are uploaded successfully. Receives the created assets. */\n onUpload?: (assets: UploadedAsset[]) => void;\n /** Accepted file types (MIME pattern). Defaults to all files. */\n accept?: string;\n /**\n * Why attaching is off right now, e.g. \"Needs a connection…\" while the host knows Athena can't be\n * reached: the button shows disabled with this in its tooltip and the file picker does not open.\n * It stays focusable, and the tooltip opens on keyboard focus as on hover. `null` or absent: on.\n */\n disabledReason?: string | null;\n}\n\n/**\n * Paperclip button that opens a file picker and uploads selected files to Athena.\n * After upload, adds files to the attachment context so they appear as pills\n * above the composer and get included when the message is sent.\n */\nexport const FileUploadButton: FC<FileUploadButtonProps> = ({\n className,\n onUpload,\n accept,\n disabledReason = null,\n}) => {\n const inputRef = useRef<HTMLInputElement>(null);\n const { attachFiles, isUploading, error, clearError } = useAttachFiles();\n const unavailable = Boolean(disabledReason);\n\n const handleClick = useCallback(() => {\n if (unavailable) return;\n clearError();\n inputRef.current?.click();\n }, [clearError, unavailable]);\n\n const handleFiles = useCallback(\n async (files: FileList | null) => {\n if (!files || files.length === 0) return;\n\n const assets = await attachFiles(Array.from(files), 'paperclip');\n if (assets.length > 0) {\n onUpload?.(assets);\n }\n\n // Reset input so the same file can be re-selected\n if (inputRef.current) {\n inputRef.current.value = '';\n }\n },\n [attachFiles, onUpload],\n );\n\n const button = (\n <button\n type=\"button\"\n onClick={handleClick}\n disabled={isUploading}\n // Off with a reason, it keeps its pointer and its focus: the reason has to be readable.\n aria-disabled={unavailable || undefined}\n data-unavailable={unavailable || undefined}\n className={cn(\n 'aui-file-upload-btn flex items-center justify-center rounded-md p-1.5 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:opacity-50 disabled:pointer-events-none',\n error && 'text-destructive',\n className,\n unavailable &&\n 'cursor-not-allowed opacity-30 hover:bg-transparent hover:text-muted-foreground',\n )}\n title={unavailable ? undefined : (error ?? (isUploading ? 'Uploading...' : 'Attach files'))}\n aria-label={isUploading ? 'Uploading files' : 'Attach files'}\n >\n {isUploading ? (\n <Loader2Icon className=\"size-4 animate-spin\" />\n ) : error ? (\n <AlertCircleIcon className=\"size-4\" />\n ) : (\n <PaperclipIcon className=\"size-4\" />\n )}\n </button>\n );\n\n return (\n <>\n <input\n ref={inputRef}\n type=\"file\"\n multiple\n accept={accept}\n className=\"hidden\"\n onChange={(e) => handleFiles(e.target.files)}\n aria-label=\"Upload files\"\n />\n {unavailable ? (\n // The reason in the SDK's tooltip, which opens on keyboard focus as well as on hover (a\n // native title shows only to a pointer).\n <Tooltip>\n <TooltipTrigger asChild>{button}</TooltipTrigger>\n <TooltipContent side=\"bottom\">{disabledReason}</TooltipContent>\n </Tooltip>\n ) : (\n button\n )}\n </>\n );\n};\n"],"names":[],"mappings":";;;;;;AA0BO,MAAM,mBAA8C,CAAC;AAAA,EAC1D;AAAA,EACA;AAAA,EACA;AAAA,EACA,iBAAiB;AACnB,MAAM;AACJ,QAAM,WAAW,OAAyB,IAAI;AAC9C,QAAM,EAAE,aAAa,aAAa,OAAO,WAAA,IAAe,eAAA;AACxD,QAAM,cAAc,QAAQ,cAAc;AAE1C,QAAM,cAAc,YAAY,MAAM;;AACpC,QAAI,YAAa;AACjB,eAAA;AACA,mBAAS,YAAT,mBAAkB;AAAA,EACpB,GAAG,CAAC,YAAY,WAAW,CAAC;AAE5B,QAAM,cAAc;AAAA,IAClB,OAAO,UAA2B;AAChC,UAAI,CAAC,SAAS,MAAM,WAAW,EAAG;AAElC,YAAM,SAAS,MAAM,YAAY,MAAM,KAAK,KAAK,GAAG,WAAW;AAC/D,UAAI,OAAO,SAAS,GAAG;AACrB,6CAAW;AAAA,MACb;AAGA,UAAI,SAAS,SAAS;AACpB,iBAAS,QAAQ,QAAQ;AAAA,MAC3B;AAAA,IACF;AAAA,IACA,CAAC,aAAa,QAAQ;AAAA,EAAA;AAGxB,QAAM,SACJ;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,MAAK;AAAA,MACL,SAAS;AAAA,MACT,UAAU;AAAA,MAEV,iBAAe,eAAe;AAAA,MAC9B,oBAAkB,eAAe;AAAA,MACjC,WAAW;AAAA,QACT;AAAA,QACA,SAAS;AAAA,QACT;AAAA,QACA,eACE;AAAA,MAAA;AAAA,MAEJ,OAAO,cAAc,SAAa,UAAU,cAAc,iBAAiB;AAAA,MAC3E,cAAY,cAAc,oBAAoB;AAAA,MAE7C,UAAA,cACC,oBAAC,aAAA,EAAY,WAAU,uBAAsB,IAC3C,QACF,oBAAC,iBAAA,EAAgB,WAAU,UAAS,IAEpC,oBAAC,eAAA,EAAc,WAAU,SAAA,CAAS;AAAA,IAAA;AAAA,EAAA;AAKxC,SACE,qBAAA,UAAA,EACE,UAAA;AAAA,IAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAK;AAAA,QACL,MAAK;AAAA,QACL,UAAQ;AAAA,QACR;AAAA,QACA,WAAU;AAAA,QACV,UAAU,CAAC,MAAM,YAAY,EAAE,OAAO,KAAK;AAAA,QAC3C,cAAW;AAAA,MAAA;AAAA,IAAA;AAAA,IAEZ;AAAA;AAAA;AAAA,2BAGE,SAAA,EACC,UAAA;AAAA,QAAA,oBAAC,gBAAA,EAAe,SAAO,MAAE,UAAA,QAAO;AAAA,QAChC,oBAAC,gBAAA,EAAe,MAAK,UAAU,UAAA,eAAA,CAAe;AAAA,MAAA,EAAA,CAChD;AAAA,QAEA;AAAA,EAAA,GAEJ;AAEJ;"}
|
|
@@ -1,37 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
|
-
const
|
|
4
|
+
const require$$0 = require("react");
|
|
5
5
|
const zustand = require("zustand");
|
|
6
6
|
const vanilla = require("zustand/vanilla");
|
|
7
|
-
const QuoteCtx =
|
|
7
|
+
const QuoteCtx = require$$0.createContext(null);
|
|
8
8
|
function createQuoteStore() {
|
|
9
9
|
return vanilla.createStore(() => ({ quote: null }));
|
|
10
10
|
}
|
|
11
11
|
function QuoteProvider({ children, store }) {
|
|
12
|
-
const outer =
|
|
12
|
+
const outer = require$$0.useContext(QuoteCtx);
|
|
13
13
|
if (store) return /* @__PURE__ */ jsxRuntime.jsx(StoreQuoteProvider, { store, children });
|
|
14
14
|
if (outer) return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children });
|
|
15
15
|
return /* @__PURE__ */ jsxRuntime.jsx(OwnQuoteProvider, { children });
|
|
16
16
|
}
|
|
17
17
|
function OwnQuoteProvider({ children }) {
|
|
18
|
-
const [store] =
|
|
18
|
+
const [store] = require$$0.useState(createQuoteStore);
|
|
19
19
|
return /* @__PURE__ */ jsxRuntime.jsx(StoreQuoteProvider, { store, children });
|
|
20
20
|
}
|
|
21
21
|
function StoreQuoteProvider({ children, store }) {
|
|
22
22
|
const quote = zustand.useStore(store, (state) => state.quote);
|
|
23
|
-
const actions =
|
|
23
|
+
const actions = require$$0.useMemo(
|
|
24
24
|
() => ({
|
|
25
25
|
setQuote: (next) => store.setState({ quote: next }),
|
|
26
26
|
clearQuote: () => store.setState({ quote: null })
|
|
27
27
|
}),
|
|
28
28
|
[store]
|
|
29
29
|
);
|
|
30
|
-
const value =
|
|
30
|
+
const value = require$$0.useMemo(() => ({ quote, ...actions }), [quote, actions]);
|
|
31
31
|
return /* @__PURE__ */ jsxRuntime.jsx(QuoteCtx.Provider, { value, children });
|
|
32
32
|
}
|
|
33
33
|
function useQuote() {
|
|
34
|
-
const ctx =
|
|
34
|
+
const ctx = require$$0.useContext(QuoteCtx);
|
|
35
35
|
if (!ctx) {
|
|
36
36
|
throw new Error("[AthenaSDK] useQuote must be used within <QuoteProvider>");
|
|
37
37
|
}
|
|
@@ -56,7 +56,7 @@ function elementOf(node) {
|
|
|
56
56
|
}
|
|
57
57
|
function useQuoteFromPostMessage({ scope } = {}) {
|
|
58
58
|
const { setQuote } = useQuote();
|
|
59
|
-
|
|
59
|
+
require$$0.useEffect(() => {
|
|
60
60
|
var _a;
|
|
61
61
|
const doc = ((_a = scope == null ? void 0 : scope.current) == null ? void 0 : _a.ownerDocument) ?? document;
|
|
62
62
|
const win = doc.defaultView ?? window;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"QuoteContext.cjs","sources":["../../src/composer/QuoteContext.tsx"],"sourcesContent":["import {\n createContext,\n type RefObject,\n useContext,\n useEffect,\n useMemo,\n useState,\n type ReactNode,\n} from 'react';\nimport { useStore } from 'zustand';\nimport { createStore, type StoreApi } from 'zustand/vanilla';\n\nexport interface QuoteData {\n /** The selected/quoted text. */\n text: string;\n /** Title of the source (e.g., asset title, document name). */\n sourceTitle?: string;\n /** Asset ID of the source (for attribution). */\n sourceAssetId?: string;\n /** Message ID of the source message (when quoting from chat). */\n sourceMessageId?: string;\n /** Role of the source message ('assistant' | 'user'). */\n sourceRole?: string;\n}\n\ninterface QuoteContextValue {\n quote: QuoteData | null;\n setQuote: (quote: QuoteData | null) => void;\n clearQuote: () => void;\n}\n\nconst QuoteCtx = createContext<QuoteContextValue | null>(null);\n\ninterface QuoteStoreState {\n quote: QuoteData | null;\n}\n\n/**\n * A composer's pending quote, kept outside React (`createQuoteStore`), like\n * `AttachmentStore`: one per chat when a host shows several.\n */\nexport type QuoteStore = StoreApi<QuoteStoreState>;\n\n/** An empty `QuoteStore`, for `<QuoteProvider store>`. */\nexport function createQuoteStore(): QuoteStore {\n return createStore<QuoteStoreState>(() => ({ quote: null }));\n}\n\n/**\n * The composer's pending quote. Like \\`AttachmentProvider\\`, a `store` makes\n * it that store's, and without one it reuses a provider already mounted\n * above, so a host can keep the quote across a remounting \\`AthenaChat\\`.\n */\nexport function QuoteProvider({ children, store }: { children: ReactNode; store?: QuoteStore }) {\n const outer = useContext(QuoteCtx);\n if (store) return <StoreQuoteProvider store={store}>{children}</StoreQuoteProvider>;\n if (outer) return <>{children}</>;\n return <OwnQuoteProvider>{children}</OwnQuoteProvider>;\n}\n\nfunction OwnQuoteProvider({ children }: { children: ReactNode }) {\n const [store] = useState(createQuoteStore);\n return <StoreQuoteProvider store={store}>{children}</StoreQuoteProvider>;\n}\n\nfunction StoreQuoteProvider({ children, store }: { children: ReactNode; store: QuoteStore }) {\n const quote = useStore(store, (state) => state.quote);\n const actions = useMemo(\n () => ({\n setQuote: (next: QuoteData | null) => store.setState({ quote: next }),\n clearQuote: () => store.setState({ quote: null }),\n }),\n [store],\n );\n const value = useMemo(() => ({ quote, ...actions }), [quote, actions]);\n\n return (\n <QuoteCtx.Provider value={value}>\n {children}\n </QuoteCtx.Provider>\n );\n}\n\nexport function useQuote(): QuoteContextValue {\n const ctx = useContext(QuoteCtx);\n if (!ctx) {\n throw new Error('[AthenaSDK] useQuote must be used within <QuoteProvider>');\n }\n return ctx;\n}\n\n/**\n * Whether a message came from a frame embedded directly in this window, for\n * any origin: the window of one of this document's iframes (an identity\n * comparison, safe cross-origin), or, for a frame inside a shadow root, a\n * window whose `parent` is this window (`parent` is readable on a\n * cross-origin window). A message port, a worker, this window itself, a\n * grandchild frame or an unrelated window is refused. `win` is the window the\n * message came to (default: this one), e.g. a popped-out chat's.\n */\nexport function isDirectChildFrame(\n source: MessageEventSource | null,\n win: Window = window,\n): boolean {\n if (!source || source === win) return false;\n for (const frame of win.document.querySelectorAll('iframe')) {\n if (frame.contentWindow === source) return true;\n }\n try {\n return Reflect.get(source, 'parent') === win;\n } catch {\n return false;\n }\n}\n\n/** `AthenaChat`'s thread root: the chats `useQuoteFromPostMessage` tells apart. */\nconst CHAT_ROOT_SELECTOR = '.aui-thread-root';\n\n/**\n * The chat the person last focused in each window, which takes a quote that\n * names no chat (a selection outside every chat, an embedded frame's text)\n * when that window shows several. A focus, not data: no state of the chats\n * themselves.\n */\nconst lastFocusedChatRoots = new WeakMap<Document, Element>();\n\n/** The element a node is, or sits in; duck-typed, since a pop-out window's nodes are another realm's. */\nfunction elementOf(node: Node | null | undefined): Element | null {\n if (!node) return null;\n return node.nodeType === 1 ? (node as Element) : node.parentElement;\n}\n\nexport interface QuoteFromPostMessageOptions {\n /**\n * An element inside the chat this composer belongs to. With several chats in\n * one window, a ⌘L selection goes to the chat it was made in, and one made\n * outside every chat (or an embedded frame's text) to the chat the person\n * last focused; the keys and an embedded frame's messages are heard in this\n * element's own window, a pop-out included. Without it, every quote is this\n * composer's, as before.\n */\n scope?: RefObject<Element | null>;\n}\n\n/**\n * Listens for:\n * 1. Cmd+L / Ctrl+L keydown — grabs the current text selection and sets it as a quote.\n * `preventDefault` stops the browser from focusing the URL bar.\n * 2. PostMessage events from child iframes (asset panels, embedded content)\n * with type `athena-add-to-composer`, only from a frame embedded directly\n * in this window ({@link isDirectChildFrame}).\n *\n * Mount this once per composer inside AthenaProvider (`AthenaChat` does).\n */\nexport function useQuoteFromPostMessage({ scope }: QuoteFromPostMessageOptions = {}) {\n const { setQuote } = useQuote();\n\n useEffect(() => {\n const doc = scope?.current?.ownerDocument ?? document;\n const win = doc.defaultView ?? window;\n const chatRoot = () => scope?.current?.closest(CHAT_ROOT_SELECTOR) ?? null;\n // Whether this composer takes a quote made at `anchor` (null: one that names no chat).\n const takes = (anchor: Node | null) => {\n const mine = chatRoot();\n if (!mine) return true;\n const owner = elementOf(anchor)?.closest(CHAT_ROOT_SELECTOR) ?? null;\n if (owner) return owner === mine;\n const remembered = lastFocusedChatRoots.get(doc);\n const focused = remembered?.isConnected ? remembered : doc.querySelector(CHAT_ROOT_SELECTOR);\n return focused === mine;\n };\n\n const handleFocusIn = (event: FocusEvent) => {\n const mine = chatRoot();\n const target = event.target as Node | null;\n if (mine && target && typeof target.nodeType === 'number' && mine.contains(target)) {\n lastFocusedChatRoots.set(doc, mine);\n }\n };\n\n // ── Cmd+L / Ctrl+L keyboard handler ──────────────────────────────\n const handleKeydown = (e: KeyboardEvent) => {\n if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'l') {\n const sel = doc.getSelection();\n const selection = sel?.toString()?.trim();\n\n if (selection && selection.length > 0 && takes(sel?.anchorNode ?? null)) {\n e.preventDefault();\n\n // Walk up from the selection anchor to find the message container.\n // assistant-ui message roots have data-role=\"assistant\" or data-role=\"user\".\n let messageId: string | undefined;\n let role: string | undefined;\n let node = elementOf(sel?.anchorNode);\n while (node && node !== doc.body) {\n const dataRole = node.getAttribute('data-role');\n if (dataRole === 'assistant' || dataRole === 'user') {\n role = dataRole;\n // assistant-ui sets data-message-id on message roots\n messageId = node.getAttribute('data-message-id') ?? undefined;\n break;\n }\n node = node.parentElement;\n }\n\n setQuote({ text: selection, sourceRole: role, sourceMessageId: messageId });\n }\n }\n };\n\n // ── PostMessage handler (from iframes) ───────────────────────────\n // Accepts messages from any origin, but only from a frame embedded\n // directly in this window: the SDK consumer controls which iframes are\n // embedded, and that is the trust boundary. A popup, an opener or another\n // tab holding a reference to this window cannot stage composer text.\n const handleMessage = (event: MessageEvent) => {\n const data = event.data;\n if (\n data &&\n typeof data === 'object' &&\n data.type === 'athena-add-to-composer' &&\n typeof data.text === 'string' &&\n data.text.trim().length > 0 &&\n isDirectChildFrame(event.source, win) &&\n takes(null)\n ) {\n setQuote({\n text: data.text,\n sourceTitle: data.sourceTitle,\n sourceAssetId: data.sourceAssetId,\n });\n }\n };\n\n doc.addEventListener('keydown', handleKeydown, true); // capture phase to beat the browser\n doc.addEventListener('focusin', handleFocusIn, true);\n win.addEventListener('message', handleMessage);\n\n return () => {\n doc.removeEventListener('keydown', handleKeydown, true);\n doc.removeEventListener('focusin', handleFocusIn, true);\n win.removeEventListener('message', handleMessage);\n };\n }, [scope, setQuote]);\n}\n"],"names":["createContext","createStore","useContext","jsx","Fragment","useState","useStore","useMemo","useEffect","_a"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"QuoteContext.cjs","sources":["../../src/composer/QuoteContext.tsx"],"sourcesContent":["import {\n createContext,\n type RefObject,\n useContext,\n useEffect,\n useMemo,\n useState,\n type ReactNode,\n} from 'react';\nimport { useStore } from 'zustand';\nimport { createStore, type StoreApi } from 'zustand/vanilla';\n\nexport interface QuoteData {\n /** The selected/quoted text. */\n text: string;\n /** Title of the source (e.g., asset title, document name). */\n sourceTitle?: string;\n /** Asset ID of the source (for attribution). */\n sourceAssetId?: string;\n /** Message ID of the source message (when quoting from chat). */\n sourceMessageId?: string;\n /** Role of the source message ('assistant' | 'user'). */\n sourceRole?: string;\n}\n\ninterface QuoteContextValue {\n quote: QuoteData | null;\n setQuote: (quote: QuoteData | null) => void;\n clearQuote: () => void;\n}\n\nconst QuoteCtx = createContext<QuoteContextValue | null>(null);\n\ninterface QuoteStoreState {\n quote: QuoteData | null;\n}\n\n/**\n * A composer's pending quote, kept outside React (`createQuoteStore`), like\n * `AttachmentStore`: one per chat when a host shows several.\n */\nexport type QuoteStore = StoreApi<QuoteStoreState>;\n\n/** An empty `QuoteStore`, for `<QuoteProvider store>`. */\nexport function createQuoteStore(): QuoteStore {\n return createStore<QuoteStoreState>(() => ({ quote: null }));\n}\n\n/**\n * The composer's pending quote. Like \\`AttachmentProvider\\`, a `store` makes\n * it that store's, and without one it reuses a provider already mounted\n * above, so a host can keep the quote across a remounting \\`AthenaChat\\`.\n */\nexport function QuoteProvider({ children, store }: { children: ReactNode; store?: QuoteStore }) {\n const outer = useContext(QuoteCtx);\n if (store) return <StoreQuoteProvider store={store}>{children}</StoreQuoteProvider>;\n if (outer) return <>{children}</>;\n return <OwnQuoteProvider>{children}</OwnQuoteProvider>;\n}\n\nfunction OwnQuoteProvider({ children }: { children: ReactNode }) {\n const [store] = useState(createQuoteStore);\n return <StoreQuoteProvider store={store}>{children}</StoreQuoteProvider>;\n}\n\nfunction StoreQuoteProvider({ children, store }: { children: ReactNode; store: QuoteStore }) {\n const quote = useStore(store, (state) => state.quote);\n const actions = useMemo(\n () => ({\n setQuote: (next: QuoteData | null) => store.setState({ quote: next }),\n clearQuote: () => store.setState({ quote: null }),\n }),\n [store],\n );\n const value = useMemo(() => ({ quote, ...actions }), [quote, actions]);\n\n return (\n <QuoteCtx.Provider value={value}>\n {children}\n </QuoteCtx.Provider>\n );\n}\n\nexport function useQuote(): QuoteContextValue {\n const ctx = useContext(QuoteCtx);\n if (!ctx) {\n throw new Error('[AthenaSDK] useQuote must be used within <QuoteProvider>');\n }\n return ctx;\n}\n\n/**\n * Whether a message came from a frame embedded directly in this window, for\n * any origin: the window of one of this document's iframes (an identity\n * comparison, safe cross-origin), or, for a frame inside a shadow root, a\n * window whose `parent` is this window (`parent` is readable on a\n * cross-origin window). A message port, a worker, this window itself, a\n * grandchild frame or an unrelated window is refused. `win` is the window the\n * message came to (default: this one), e.g. a popped-out chat's.\n */\nexport function isDirectChildFrame(\n source: MessageEventSource | null,\n win: Window = window,\n): boolean {\n if (!source || source === win) return false;\n for (const frame of win.document.querySelectorAll('iframe')) {\n if (frame.contentWindow === source) return true;\n }\n try {\n return Reflect.get(source, 'parent') === win;\n } catch {\n return false;\n }\n}\n\n/** `AthenaChat`'s thread root: the chats `useQuoteFromPostMessage` tells apart. */\nconst CHAT_ROOT_SELECTOR = '.aui-thread-root';\n\n/**\n * The chat the person last focused in each window, which takes a quote that\n * names no chat (a selection outside every chat, an embedded frame's text)\n * when that window shows several. A focus, not data: no state of the chats\n * themselves.\n */\nconst lastFocusedChatRoots = new WeakMap<Document, Element>();\n\n/** The element a node is, or sits in; duck-typed, since a pop-out window's nodes are another realm's. */\nfunction elementOf(node: Node | null | undefined): Element | null {\n if (!node) return null;\n return node.nodeType === 1 ? (node as Element) : node.parentElement;\n}\n\nexport interface QuoteFromPostMessageOptions {\n /**\n * An element inside the chat this composer belongs to. With several chats in\n * one window, a ⌘L selection goes to the chat it was made in, and one made\n * outside every chat (or an embedded frame's text) to the chat the person\n * last focused; the keys and an embedded frame's messages are heard in this\n * element's own window, a pop-out included. Without it, every quote is this\n * composer's, as before.\n */\n scope?: RefObject<Element | null>;\n}\n\n/**\n * Listens for:\n * 1. Cmd+L / Ctrl+L keydown — grabs the current text selection and sets it as a quote.\n * `preventDefault` stops the browser from focusing the URL bar.\n * 2. PostMessage events from child iframes (asset panels, embedded content)\n * with type `athena-add-to-composer`, only from a frame embedded directly\n * in this window ({@link isDirectChildFrame}).\n *\n * Mount this once per composer inside AthenaProvider (`AthenaChat` does).\n */\nexport function useQuoteFromPostMessage({ scope }: QuoteFromPostMessageOptions = {}) {\n const { setQuote } = useQuote();\n\n useEffect(() => {\n const doc = scope?.current?.ownerDocument ?? document;\n const win = doc.defaultView ?? window;\n const chatRoot = () => scope?.current?.closest(CHAT_ROOT_SELECTOR) ?? null;\n // Whether this composer takes a quote made at `anchor` (null: one that names no chat).\n const takes = (anchor: Node | null) => {\n const mine = chatRoot();\n if (!mine) return true;\n const owner = elementOf(anchor)?.closest(CHAT_ROOT_SELECTOR) ?? null;\n if (owner) return owner === mine;\n const remembered = lastFocusedChatRoots.get(doc);\n const focused = remembered?.isConnected ? remembered : doc.querySelector(CHAT_ROOT_SELECTOR);\n return focused === mine;\n };\n\n const handleFocusIn = (event: FocusEvent) => {\n const mine = chatRoot();\n const target = event.target as Node | null;\n if (mine && target && typeof target.nodeType === 'number' && mine.contains(target)) {\n lastFocusedChatRoots.set(doc, mine);\n }\n };\n\n // ── Cmd+L / Ctrl+L keyboard handler ──────────────────────────────\n const handleKeydown = (e: KeyboardEvent) => {\n if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'l') {\n const sel = doc.getSelection();\n const selection = sel?.toString()?.trim();\n\n if (selection && selection.length > 0 && takes(sel?.anchorNode ?? null)) {\n e.preventDefault();\n\n // Walk up from the selection anchor to find the message container.\n // assistant-ui message roots have data-role=\"assistant\" or data-role=\"user\".\n let messageId: string | undefined;\n let role: string | undefined;\n let node = elementOf(sel?.anchorNode);\n while (node && node !== doc.body) {\n const dataRole = node.getAttribute('data-role');\n if (dataRole === 'assistant' || dataRole === 'user') {\n role = dataRole;\n // assistant-ui sets data-message-id on message roots\n messageId = node.getAttribute('data-message-id') ?? undefined;\n break;\n }\n node = node.parentElement;\n }\n\n setQuote({ text: selection, sourceRole: role, sourceMessageId: messageId });\n }\n }\n };\n\n // ── PostMessage handler (from iframes) ───────────────────────────\n // Accepts messages from any origin, but only from a frame embedded\n // directly in this window: the SDK consumer controls which iframes are\n // embedded, and that is the trust boundary. A popup, an opener or another\n // tab holding a reference to this window cannot stage composer text.\n const handleMessage = (event: MessageEvent) => {\n const data = event.data;\n if (\n data &&\n typeof data === 'object' &&\n data.type === 'athena-add-to-composer' &&\n typeof data.text === 'string' &&\n data.text.trim().length > 0 &&\n isDirectChildFrame(event.source, win) &&\n takes(null)\n ) {\n setQuote({\n text: data.text,\n sourceTitle: data.sourceTitle,\n sourceAssetId: data.sourceAssetId,\n });\n }\n };\n\n doc.addEventListener('keydown', handleKeydown, true); // capture phase to beat the browser\n doc.addEventListener('focusin', handleFocusIn, true);\n win.addEventListener('message', handleMessage);\n\n return () => {\n doc.removeEventListener('keydown', handleKeydown, true);\n doc.removeEventListener('focusin', handleFocusIn, true);\n win.removeEventListener('message', handleMessage);\n };\n }, [scope, setQuote]);\n}\n"],"names":["createContext","createStore","useContext","jsx","Fragment","useState","useStore","useMemo","useEffect","_a"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const
|
|
3
|
+
const require$$0 = require("react");
|
|
4
4
|
const react = require("@assistant-ui/react");
|
|
5
5
|
const athenaDiagnostics = require("../diagnostics/athena-diagnostics.cjs");
|
|
6
6
|
const errors = require("../diagnostics/errors.cjs");
|
|
@@ -40,13 +40,13 @@ function takeRestoredAttachments({
|
|
|
40
40
|
(_b = store == null ? void 0 : store.restoredAttachments) == null ? void 0 : _b.delete(threadId);
|
|
41
41
|
return kept.filter((attachment) => assetIdsInDraft.has(attachment.assetId));
|
|
42
42
|
}
|
|
43
|
-
const ComposerHandoffContext =
|
|
43
|
+
const ComposerHandoffContext = require$$0.createContext(null);
|
|
44
44
|
function useComposerHandoffStore() {
|
|
45
|
-
return
|
|
45
|
+
return require$$0.useContext(ComposerHandoffContext);
|
|
46
46
|
}
|
|
47
47
|
function useFocusComposer() {
|
|
48
48
|
const store = useComposerHandoffStore();
|
|
49
|
-
return
|
|
49
|
+
return require$$0.useCallback(() => {
|
|
50
50
|
if (store) focusComposer({ store });
|
|
51
51
|
}, [store]);
|
|
52
52
|
}
|
|
@@ -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 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,17 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const
|
|
3
|
+
const require$$0 = require("react");
|
|
4
4
|
const react = require("@assistant-ui/react");
|
|
5
5
|
const threadIdContext = require("../threads/thread-id-context.cjs");
|
|
6
6
|
const composerHandoff = require("./composer-handoff.cjs");
|
|
7
7
|
function useAppendToComposer() {
|
|
8
8
|
const aui = react.useAui();
|
|
9
9
|
const store = composerHandoff.useComposerHandoffStore();
|
|
10
|
-
const threadId =
|
|
10
|
+
const threadId = require$$0.useContext(threadIdContext.AthenaStatewireThreadIdContext);
|
|
11
11
|
const ready = composerHandoff.useComposerReady();
|
|
12
|
-
const readyRef =
|
|
12
|
+
const readyRef = require$$0.useRef(ready);
|
|
13
13
|
readyRef.current = ready;
|
|
14
|
-
return
|
|
14
|
+
return require$$0.useCallback(
|
|
15
15
|
(text, opts) => {
|
|
16
16
|
const write = {
|
|
17
17
|
text,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAppendToComposer.cjs","sources":["../../src/composer/useAppendToComposer.ts"],"sourcesContent":["import { useCallback, useContext, useRef } from 'react';\nimport { useAui } from '@assistant-ui/react';\nimport { AthenaStatewireThreadIdContext } from '../threads/thread-id-context';\nimport {\n applyComposerWrite,\n queueComposerWrite,\n useComposerHandoffStore,\n useComposerReady,\n type ComposerWrite,\n} from './composer-handoff';\n\nexport interface AppendToComposerOptions {\n /** Replace the current draft instead of appending on a new line. */\n replace?: boolean;\n /**\n * Focus the composer with the caret after the text once the editor shows\n * it — for a prefilled draft the user is meant to finish by typing or\n * dictating. Defaults to false.\n */\n focus?: boolean;\n}\n\n/**\n * Hook to programmatically append text to the composer without sending it.\n *\n * Safe to call at any time: a write made before the chat is ready (the\n * thread list still resolving the active thread, or the thread's history\n * still loading) waits in the provider and lands once the composer is\n * ready, instead of being lost with the mount it was written into. A\n * never-started chat is ready without a live socket. The write is bound to\n * the thread it was made for: if the user switches threads first, it is\n * dropped (a `composer.handoff` diagnostic says so), never written into\n * another thread.\n *\n * Use `useSendMessage()` for workflow shortcuts or other UI that should\n * immediately submit a prompt.\n *\n * Usage:\n * const append = useAppendToComposer();\n * append(\"some text to add\");\n * append(\"quoted text\", { replace: true }); // replaces existing text\n * append(\"Here is what happened: \", { replace: true, focus: true }); // caret after the text\n */\nexport function useAppendToComposer() {\n const aui = useAui();\n const store = useComposerHandoffStore();\n const threadId = useContext(AthenaStatewireThreadIdContext);\n const ready = useComposerReady();\n // The callback stays identity-stable across readiness changes.\n const readyRef = useRef(ready);\n readyRef.current = ready;\n\n return useCallback(\n (text: string, opts?: AppendToComposerOptions) => {\n const write: ComposerWrite = {\n text,\n replace: opts?.replace ?? false,\n send: false,\n focus: opts?.focus ?? false,\n threadId,\n };\n if (store && !readyRef.current) {\n queueComposerWrite({ store, write });\n return;\n }\n applyComposerWrite({ target: aui, store, write });\n },\n [aui, store, threadId],\n );\n}\n"],"names":["useAui","useComposerHandoffStore","useContext","AthenaStatewireThreadIdContext","useComposerReady","useRef","useCallback","queueComposerWrite","applyComposerWrite"],"mappings":";;;;;;AA2CO,SAAS,sBAAsB;AACpC,QAAM,MAAMA,MAAAA,OAAA;AACZ,QAAM,QAAQC,gBAAAA,wBAAA;AACd,QAAM,WAAWC,
|
|
1
|
+
{"version":3,"file":"useAppendToComposer.cjs","sources":["../../src/composer/useAppendToComposer.ts"],"sourcesContent":["import { useCallback, useContext, useRef } from 'react';\nimport { useAui } from '@assistant-ui/react';\nimport { AthenaStatewireThreadIdContext } from '../threads/thread-id-context';\nimport {\n applyComposerWrite,\n queueComposerWrite,\n useComposerHandoffStore,\n useComposerReady,\n type ComposerWrite,\n} from './composer-handoff';\n\nexport interface AppendToComposerOptions {\n /** Replace the current draft instead of appending on a new line. */\n replace?: boolean;\n /**\n * Focus the composer with the caret after the text once the editor shows\n * it — for a prefilled draft the user is meant to finish by typing or\n * dictating. Defaults to false.\n */\n focus?: boolean;\n}\n\n/**\n * Hook to programmatically append text to the composer without sending it.\n *\n * Safe to call at any time: a write made before the chat is ready (the\n * thread list still resolving the active thread, or the thread's history\n * still loading) waits in the provider and lands once the composer is\n * ready, instead of being lost with the mount it was written into. A\n * never-started chat is ready without a live socket. The write is bound to\n * the thread it was made for: if the user switches threads first, it is\n * dropped (a `composer.handoff` diagnostic says so), never written into\n * another thread.\n *\n * Use `useSendMessage()` for workflow shortcuts or other UI that should\n * immediately submit a prompt.\n *\n * Usage:\n * const append = useAppendToComposer();\n * append(\"some text to add\");\n * append(\"quoted text\", { replace: true }); // replaces existing text\n * append(\"Here is what happened: \", { replace: true, focus: true }); // caret after the text\n */\nexport function useAppendToComposer() {\n const aui = useAui();\n const store = useComposerHandoffStore();\n const threadId = useContext(AthenaStatewireThreadIdContext);\n const ready = useComposerReady();\n // The callback stays identity-stable across readiness changes.\n const readyRef = useRef(ready);\n readyRef.current = ready;\n\n return useCallback(\n (text: string, opts?: AppendToComposerOptions) => {\n const write: ComposerWrite = {\n text,\n replace: opts?.replace ?? false,\n send: false,\n focus: opts?.focus ?? false,\n threadId,\n };\n if (store && !readyRef.current) {\n queueComposerWrite({ store, write });\n return;\n }\n applyComposerWrite({ target: aui, store, write });\n },\n [aui, store, threadId],\n );\n}\n"],"names":["useAui","useComposerHandoffStore","useContext","AthenaStatewireThreadIdContext","useComposerReady","useRef","useCallback","queueComposerWrite","applyComposerWrite"],"mappings":";;;;;;AA2CO,SAAS,sBAAsB;AACpC,QAAM,MAAMA,MAAAA,OAAA;AACZ,QAAM,QAAQC,gBAAAA,wBAAA;AACd,QAAM,WAAWC,WAAAA,WAAWC,8CAA8B;AAC1D,QAAM,QAAQC,gBAAAA,iBAAA;AAEd,QAAM,WAAWC,WAAAA,OAAO,KAAK;AAC7B,WAAS,UAAU;AAEnB,SAAOC,WAAAA;AAAAA,IACL,CAAC,MAAc,SAAmC;AAChD,YAAM,QAAuB;AAAA,QAC3B;AAAA,QACA,UAAS,6BAAM,YAAW;AAAA,QAC1B,MAAM;AAAA,QACN,QAAO,6BAAM,UAAS;AAAA,QACtB;AAAA,MAAA;AAEF,UAAI,SAAS,CAAC,SAAS,SAAS;AAC9BC,2CAAmB,EAAE,OAAO,OAAO;AACnC;AAAA,MACF;AACAC,sBAAAA,mBAAmB,EAAE,QAAQ,KAAK,OAAO,OAAO;AAAA,IAClD;AAAA,IACA,CAAC,KAAK,OAAO,QAAQ;AAAA,EAAA;AAEzB;;"}
|