@athenaintel/react 0.43.0 → 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 +215 -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/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 +14 -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 -25
- 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 -25
- 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 +547 -124
- package/dist/agent-runtime/src/use-deep-agent-voice.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-voice.d.ts +129 -10
- package/dist/agent-runtime/src/use-deep-agent-voice.js +487 -64
- 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 +52 -36
- package/dist/chat/super-grouping/SuperGroupingCard.cjs.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingCard.d.ts +19 -4
- package/dist/chat/super-grouping/SuperGroupingCard.js +29 -13
- 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 +73 -40
- package/dist/chat/super-grouping/ToolTimeline.cjs.map +1 -1
- package/dist/chat/super-grouping/ToolTimeline.d.ts +10 -2
- package/dist/chat/super-grouping/ToolTimeline.js +69 -36
- 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 +5 -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/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 +4 -4
- package/dist/chat-ui/mentions/mention-chip.cjs.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 +3 -3
- package/dist/chat-ui/mentions/use-mention-asset.cjs.map +1 -1
- 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 +2 -2
- package/dist/chat-ui/rich-text/chat-link.cjs.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 +6 -6
- package/dist/chat-ui/rich-text/chat-node-views.cjs.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/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 +51 -51
- package/dist/threads/statewire-thread-list.cjs.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-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,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 livekitClient = require("livekit-client");
|
|
5
5
|
const auth = require("../runtime/auth.cjs");
|
|
6
6
|
const credentialRenewal = require("../runtime/credential-renewal.cjs");
|
|
@@ -56,18 +56,18 @@ const useAthenaVoiceSession = (options = {}) => {
|
|
|
56
56
|
useBridge = createSession ? useNoBridge : auth.useParentBridge
|
|
57
57
|
} = options;
|
|
58
58
|
const bridge = useBridge();
|
|
59
|
-
const bridgeRef =
|
|
59
|
+
const bridgeRef = require$$0.useRef(bridge);
|
|
60
60
|
bridgeRef.current = bridge;
|
|
61
|
-
const bridgeReadyWaitersRef =
|
|
62
|
-
|
|
61
|
+
const bridgeReadyWaitersRef = require$$0.useRef([]);
|
|
62
|
+
require$$0.useEffect(() => {
|
|
63
63
|
if (!bridge.ready) return;
|
|
64
64
|
const waiters = bridgeReadyWaitersRef.current;
|
|
65
65
|
bridgeReadyWaitersRef.current = [];
|
|
66
66
|
for (const resolve of waiters) resolve();
|
|
67
67
|
}, [bridge.ready]);
|
|
68
|
-
const sessionRef =
|
|
68
|
+
const sessionRef = require$$0.useRef(session);
|
|
69
69
|
sessionRef.current = session;
|
|
70
|
-
const createSessionAsViewer =
|
|
70
|
+
const createSessionAsViewer = require$$0.useCallback(
|
|
71
71
|
async (signal) => {
|
|
72
72
|
if (!bridgeRef.current.ready) {
|
|
73
73
|
await new Promise((resolve) => {
|
|
@@ -95,16 +95,16 @@ const useAthenaVoiceSession = (options = {}) => {
|
|
|
95
95
|
},
|
|
96
96
|
[]
|
|
97
97
|
);
|
|
98
|
-
const [status, setStatus] =
|
|
99
|
-
const [activeSpeaker, setActiveSpeaker] =
|
|
98
|
+
const [status, setStatus] = require$$0.useState("idle");
|
|
99
|
+
const [activeSpeaker, setActiveSpeaker] = require$$0.useState(
|
|
100
100
|
null
|
|
101
101
|
);
|
|
102
|
-
const [isMuted, setIsMuted] =
|
|
103
|
-
const [transcript, setTranscript] =
|
|
104
|
-
const [sessionId, setSessionId] =
|
|
105
|
-
const [roomName, setRoomName] =
|
|
106
|
-
const [error, setError] =
|
|
107
|
-
const callbacksRef =
|
|
102
|
+
const [isMuted, setIsMuted] = require$$0.useState(false);
|
|
103
|
+
const [transcript, setTranscript] = require$$0.useState([]);
|
|
104
|
+
const [sessionId, setSessionId] = require$$0.useState(null);
|
|
105
|
+
const [roomName, setRoomName] = require$$0.useState(null);
|
|
106
|
+
const [error, setError] = require$$0.useState(null);
|
|
107
|
+
const callbacksRef = require$$0.useRef({
|
|
108
108
|
createSession: createSession ?? createSessionAsViewer,
|
|
109
109
|
onTranscript,
|
|
110
110
|
onInterimTranscript,
|
|
@@ -116,20 +116,20 @@ const useAthenaVoiceSession = (options = {}) => {
|
|
|
116
116
|
onInterimTranscript,
|
|
117
117
|
onError
|
|
118
118
|
};
|
|
119
|
-
const roomRef =
|
|
120
|
-
const abortRef =
|
|
121
|
-
const attachedElementsRef =
|
|
122
|
-
const ownedAudioRef =
|
|
123
|
-
const committedSegmentIdsRef =
|
|
124
|
-
const startingRef =
|
|
125
|
-
const fail =
|
|
119
|
+
const roomRef = require$$0.useRef(null);
|
|
120
|
+
const abortRef = require$$0.useRef(null);
|
|
121
|
+
const attachedElementsRef = require$$0.useRef([]);
|
|
122
|
+
const ownedAudioRef = require$$0.useRef(null);
|
|
123
|
+
const committedSegmentIdsRef = require$$0.useRef(/* @__PURE__ */ new Set());
|
|
124
|
+
const startingRef = require$$0.useRef(false);
|
|
125
|
+
const fail = require$$0.useCallback((cause) => {
|
|
126
126
|
var _a, _b;
|
|
127
127
|
const err = toError(cause);
|
|
128
128
|
setError(err);
|
|
129
129
|
setStatus("error");
|
|
130
130
|
(_b = (_a = callbacksRef.current).onError) == null ? void 0 : _b.call(_a, err);
|
|
131
131
|
}, []);
|
|
132
|
-
const detachAudio =
|
|
132
|
+
const detachAudio = require$$0.useCallback(() => {
|
|
133
133
|
for (const element of attachedElementsRef.current) {
|
|
134
134
|
element.srcObject = null;
|
|
135
135
|
if (element === ownedAudioRef.current) element.remove();
|
|
@@ -137,7 +137,7 @@ const useAthenaVoiceSession = (options = {}) => {
|
|
|
137
137
|
attachedElementsRef.current = [];
|
|
138
138
|
ownedAudioRef.current = null;
|
|
139
139
|
}, []);
|
|
140
|
-
const teardown =
|
|
140
|
+
const teardown = require$$0.useCallback(async () => {
|
|
141
141
|
var _a;
|
|
142
142
|
(_a = abortRef.current) == null ? void 0 : _a.abort();
|
|
143
143
|
abortRef.current = null;
|
|
@@ -150,13 +150,13 @@ const useAthenaVoiceSession = (options = {}) => {
|
|
|
150
150
|
await room.disconnect(true);
|
|
151
151
|
}
|
|
152
152
|
}, [detachAudio]);
|
|
153
|
-
const stop =
|
|
153
|
+
const stop = require$$0.useCallback(async () => {
|
|
154
154
|
const hadRoom = roomRef.current !== null || abortRef.current !== null;
|
|
155
155
|
await teardown();
|
|
156
156
|
setActiveSpeaker(null);
|
|
157
157
|
if (hadRoom) setStatus("ended");
|
|
158
158
|
}, [teardown]);
|
|
159
|
-
const attachTrack =
|
|
159
|
+
const attachTrack = require$$0.useCallback(
|
|
160
160
|
(track) => {
|
|
161
161
|
if (track.kind !== livekitClient.Track.Kind.Audio) return;
|
|
162
162
|
if (audioElement) {
|
|
@@ -172,7 +172,7 @@ const useAthenaVoiceSession = (options = {}) => {
|
|
|
172
172
|
},
|
|
173
173
|
[audioElement]
|
|
174
174
|
);
|
|
175
|
-
const handleTranscription =
|
|
175
|
+
const handleTranscription = require$$0.useCallback(
|
|
176
176
|
(segments, participant, room) => {
|
|
177
177
|
var _a, _b, _c, _d;
|
|
178
178
|
const speaker = speakerOf(participant, room);
|
|
@@ -199,7 +199,7 @@ const useAthenaVoiceSession = (options = {}) => {
|
|
|
199
199
|
},
|
|
200
200
|
[]
|
|
201
201
|
);
|
|
202
|
-
const start =
|
|
202
|
+
const start = require$$0.useCallback(async () => {
|
|
203
203
|
if (startingRef.current || roomRef.current) return;
|
|
204
204
|
startingRef.current = true;
|
|
205
205
|
setError(null);
|
|
@@ -264,20 +264,20 @@ const useAthenaVoiceSession = (options = {}) => {
|
|
|
264
264
|
handleTranscription,
|
|
265
265
|
teardown
|
|
266
266
|
]);
|
|
267
|
-
const setMicrophone =
|
|
267
|
+
const setMicrophone = require$$0.useCallback(async (enabled) => {
|
|
268
268
|
const room = roomRef.current;
|
|
269
269
|
if (!room) return;
|
|
270
270
|
await room.localParticipant.setMicrophoneEnabled(enabled);
|
|
271
271
|
setIsMuted(!enabled);
|
|
272
272
|
}, []);
|
|
273
|
-
const mute =
|
|
274
|
-
const unmute =
|
|
275
|
-
const clearTranscript =
|
|
273
|
+
const mute = require$$0.useCallback(() => setMicrophone(false), [setMicrophone]);
|
|
274
|
+
const unmute = require$$0.useCallback(() => setMicrophone(true), [setMicrophone]);
|
|
275
|
+
const clearTranscript = require$$0.useCallback(() => {
|
|
276
276
|
committedSegmentIdsRef.current.clear();
|
|
277
277
|
setTranscript([]);
|
|
278
278
|
}, []);
|
|
279
|
-
const unmountTimerRef =
|
|
280
|
-
|
|
279
|
+
const unmountTimerRef = require$$0.useRef(null);
|
|
280
|
+
require$$0.useEffect(() => {
|
|
281
281
|
if (unmountTimerRef.current !== null) {
|
|
282
282
|
clearTimeout(unmountTimerRef.current);
|
|
283
283
|
unmountTimerRef.current = null;
|
|
@@ -289,7 +289,7 @@ const useAthenaVoiceSession = (options = {}) => {
|
|
|
289
289
|
}, 0);
|
|
290
290
|
};
|
|
291
291
|
}, [teardown]);
|
|
292
|
-
return
|
|
292
|
+
return require$$0.useMemo(
|
|
293
293
|
() => ({
|
|
294
294
|
status,
|
|
295
295
|
isConnecting: status === "connecting",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-athena-voice-session.cjs","sources":["../../src/voice/use-athena-voice-session.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n Room,\n RoomEvent,\n Track,\n type Participant,\n type RemoteTrack,\n type TranscriptionSegment,\n} from 'livekit-client';\nimport { type ParentBridge, useParentBridge, type ParentBridgeState } from '../runtime/auth';\nimport { isCredentialRefusal } from '../runtime/credential-renewal';\n\n/**\n * Realtime connection details for one Athena voice session. This is the shape\n * the Athena voice session endpoint returns; the hook only reads these\n * fields, so any server that proxies that call can hand it straight back.\n */\nexport interface AthenaVoiceSessionCredentials {\n /** Realtime signalling URL (`wss://…`). */\n server_url: string;\n /** Short-lived participant JWT scoped to `room_name`. */\n token: string;\n room_name?: string;\n /**\n * Athena session asset the voice run is persisted into. Use it with\n * `GET /api/v0/sessions/{asset_id}/download` to retrieve the transcript\n * after the call.\n */\n asset_id?: string;\n}\n\nexport type AthenaVoiceSessionStatus =\n | 'idle'\n | 'connecting'\n | 'connected'\n | 'reconnecting'\n | 'ended'\n | 'error';\n\nexport type AthenaVoiceSpeaker = 'user' | 'agent';\n\n/** One committed (final) transcription segment from either side of the call. */\nexport interface AthenaVoiceTranscriptTurn {\n id: string;\n speaker: AthenaVoiceSpeaker;\n text: string;\n /** Segment start, in ms since the room's epoch. */\n startTime: number;\n endTime: number;\n language: string;\n}\n\n/**\n * A voice tool the Athena voice agent can run. These are voice tool\n * names, not the chat `Toolkits` ids: `'web_search_browse_toolkit'` is not a\n * voice tool, `'web_search'` is. Only these names are accepted.\n *\n * The agent also has tools that call back into the client over room RPC\n * (clipboard, selection, screen contents, opening assets). This hook registers\n * no RPC handlers, so they are not part of its contract.\n */\nexport type AthenaVoiceToolId =\n /** Web search. */\n | 'web_search'\n /** Legacy alias of `web_search`; prefer `web_search`. */\n | 'search_web'\n /** Fetch and read one URL. */\n | 'browse'\n /** @deprecated Retired: accepted and ignored, the agent gets no such tool. */\n | 'search_knowledge_base'\n /** @deprecated Retired: accepted and ignored, the agent gets no such tool. */\n | 'search_knowledge_base_lr'\n /** Read Athena assets by id, as the viewer. */\n | 'read_full_asset'\n /** Search the viewer's Athena assets. */\n | 'search_assets'\n /** Hand a question to the general agent and speak its answer. */\n | 'ask_agent'\n /** Save a note for the user (a stub on the worker today). */\n | 'save_note'\n /** Current date and time, Eastern. */\n | 'get_current_time_est';\n\n/**\n * Voice agent configuration for a session the hook creates itself (see\n * `UseAthenaVoiceSessionOptions.session`). Mirrors the body of the Athena\n * voice session endpoint; every field is optional and falls back to the\n * server default.\n */\nexport interface AthenaVoiceSessionConfig {\n /** Persona / instructions for the voice agent. */\n system_prompt?: string;\n /** Realtime provider, e.g. `'openai'` or `'google'`. */\n provider?: string;\n /** Provider model id, e.g. `'gpt-realtime-2'`. */\n model?: string;\n /** Provider voice id, e.g. `'marin'` (OpenAI) or `'Aoede'` (Google). */\n voice?: string;\n temperature?: number;\n /** BCP-47 language tag; default `'en'`. */\n language?: string;\n /**\n * Voice tools the agent may call. Omit it for the server's default set\n * (`web_search`, `save_note`, `ask_agent`, …); pass `[]` for a\n * pure conversation with no tool calls.\n */\n enabled_tools?: AthenaVoiceToolId[];\n /** IANA timezone of the speaker, e.g. `'America/New_York'`. */\n timezone?: string;\n /**\n * Start without the agent's opening greeting: it stays quiet (no audio, no\n * transcript turn) until a participant speaks. Default `false`.\n */\n silent_start?: boolean;\n}\n\nexport interface UseAthenaVoiceSessionOptions {\n /**\n * Creates the voice session. Omit it when the app is served from a\n * Marathon computer-asset URL: the hook then calls the Athena voice session\n * endpoint itself with the viewer's bearer token from `/_athena/auth`, so\n * the session is created as — and shows up in the sessions of — whoever is\n * using the app.\n *\n * Works for workspace members and external SSO viewers alike: the scoped\n * `athview_` viewer credential is authorized for the voice session route and\n * `agents/general/invoke` the same way it is for `/api/v0/sessions`.\n *\n * Supply it when the app runs anywhere else (standalone, custom auth): it\n * should run on the caller's own server so the Athena API key never reaches\n * the browser. The hook only reads the returned credentials.\n *\n * Decide once: switching between supplying and omitting it across renders\n * of the same component is not supported.\n */\n createSession?: (\n signal: AbortSignal,\n ) => Promise<AthenaVoiceSessionCredentials>;\n /**\n * Agent configuration for sessions the hook creates itself. Ignored when\n * `createSession` is supplied.\n */\n session?: AthenaVoiceSessionConfig;\n /** Called once per committed transcript turn, in arrival order. */\n onTranscript?: (turn: AthenaVoiceTranscriptTurn) => void;\n /** Called with interim (non-final) transcript text as it streams in. */\n onInterimTranscript?: (speaker: AthenaVoiceSpeaker, text: string) => void;\n onError?: (error: Error) => void;\n /**\n * Where to play the agent's audio. Defaults to a detached `<audio>` element\n * the hook creates and removes itself.\n */\n audioElement?: HTMLMediaElement | null;\n /** Enable the microphone as soon as the room connects. Default `true`. */\n autoEnableMicrophone?: boolean;\n /** @internal Overrides `new Room()`; used by tests. */\n createRoom?: () => Room;\n /** @internal Overrides `useParentBridge()`; used by tests. */\n useBridge?: () => ParentBridgeState & Partial<Pick<ParentBridge, 'renewToken'>>;\n}\n\nexport interface UseAthenaVoiceSessionReturn {\n status: AthenaVoiceSessionStatus;\n /** True between `start()` resolving the session and the room connecting. */\n isConnecting: boolean;\n isConnected: boolean;\n /** Who is speaking right now, or `null` when the room is quiet. */\n activeSpeaker: AthenaVoiceSpeaker | null;\n isMuted: boolean;\n /** Committed transcript turns so far, in arrival order. */\n transcript: AthenaVoiceTranscriptTurn[];\n /** Athena session asset id, once the session has been created. */\n sessionId: string | null;\n roomName: string | null;\n error: Error | null;\n /** Creates a session and joins the room. No-op while a session is live. */\n start: () => Promise<void>;\n /** Leaves the room and stops local tracks. Safe to call at any time. */\n stop: () => Promise<void>;\n mute: () => Promise<void>;\n unmute: () => Promise<void>;\n /** Clears `transcript`; does not affect the live session. */\n clearTranscript: () => void;\n}\n\nconst toError = (value: unknown): Error =>\n value instanceof Error ? value : new Error(String(value));\n\nconst NO_BRIDGE: ParentBridgeState = {\n token: null,\n statewireSyncUrl: null,\n backendBaseUrl: null,\n appUrl: null,\n hostAnswered: false,\n ready: true,\n};\n// Stands in for `useParentBridge` when the caller creates sessions itself, so\n// the hook never fetches `/_athena/auth` it would not use.\nconst useNoBridge = (): ParentBridgeState => NO_BRIDGE;\n\nconst NO_VIEWER_TOKEN_MESSAGE =\n 'useAthenaVoiceSession: no Athena viewer token. Either serve the app from ' +\n 'a Marathon computer-asset URL (which mints one via /_athena/auth) or pass ' +\n '`createSession` to create the session through your own server.';\n\n/**\n * Creates an Athena voice session as the current viewer. Exported so apps with\n * their own bridge state (or a server proxy holding a user bearer) can reuse\n * the exact request the hook makes.\n */\nexport const createAthenaVoiceSession = async ({\n backendBaseUrl,\n token,\n session = {},\n signal,\n}: {\n /** Bare Athena API base, e.g. `https://api.athenaintel.com`. */\n backendBaseUrl: string;\n /** Bearer token for the user the session belongs to. */\n token: string;\n session?: AthenaVoiceSessionConfig;\n signal?: AbortSignal;\n}): Promise<AthenaVoiceSessionCredentials> => {\n const url: string = `${backendBaseUrl.replace(/\\/+$/, '')}/api/orpheus/create-session`;\n const response: Response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify(session),\n signal,\n });\n if (!response.ok) {\n const detail: string = await response.text().catch(() => '');\n // `status` lets a caller tell a refused credential (401) from any other failure.\n throw Object.assign(\n new Error(\n `Athena voice session creation failed (${response.status})${detail ? `: ${detail}` : ''}`,\n ),\n { status: response.status },\n );\n }\n return (await response.json()) as AthenaVoiceSessionCredentials;\n};\n\nconst speakerOf = (\n participant: Participant | undefined,\n room: Room,\n): AthenaVoiceSpeaker =>\n participant !== undefined &&\n participant.identity === room.localParticipant.identity\n ? 'user'\n : 'agent';\n\n/**\n * Runs one Athena voice session from React.\n *\n * Owns the whole browser-side lifecycle the voice API leaves to the caller:\n * creating the session through the app's own server, joining the room,\n * publishing the microphone, playing the agent's audio, tracking who is\n * speaking, committing transcript turns from room transcription events, and\n * tearing everything down on `stop()` or unmount. A second `start()` while a\n * session is live (or still connecting) is ignored, so React StrictMode's\n * double-invoked effects cannot dispatch two agents into one room.\n */\nexport const useAthenaVoiceSession = (\n options: UseAthenaVoiceSessionOptions = {},\n): UseAthenaVoiceSessionReturn => {\n const {\n createSession,\n session,\n onTranscript,\n onInterimTranscript,\n onError,\n audioElement,\n autoEnableMicrophone = true,\n createRoom,\n useBridge = createSession ? useNoBridge : useParentBridge,\n } = options;\n\n // Viewer identity minted by Marathon (`/_athena/auth`) or the Athena app\n // iframe bridge. Only consulted when the caller did not supply `createSession`.\n const bridge: ParentBridgeState & Partial<Pick<ParentBridge, 'renewToken'>> = useBridge();\n const bridgeRef = useRef(bridge);\n bridgeRef.current = bridge;\n const bridgeReadyWaitersRef = useRef<Array<() => void>>([]);\n useEffect(() => {\n if (!bridge.ready) return;\n const waiters: Array<() => void> = bridgeReadyWaitersRef.current;\n bridgeReadyWaitersRef.current = [];\n for (const resolve of waiters) resolve();\n }, [bridge.ready]);\n\n const sessionRef = useRef<AthenaVoiceSessionConfig | undefined>(session);\n sessionRef.current = session;\n\n const createSessionAsViewer = useCallback(\n async (signal: AbortSignal): Promise<AthenaVoiceSessionCredentials> => {\n if (!bridgeRef.current.ready) {\n await new Promise<void>((resolve) => {\n bridgeReadyWaitersRef.current.push(resolve);\n signal.addEventListener('abort', () => resolve(), { once: true });\n });\n if (signal.aborted) throw new Error('aborted');\n }\n const { token, backendBaseUrl, renewToken } = bridgeRef.current;\n if (!token || !backendBaseUrl) throw new Error(NO_VIEWER_TOKEN_MESSAGE);\n const create = (viewerToken: string) =>\n createAthenaVoiceSession({\n backendBaseUrl,\n token: viewerToken,\n session: sessionRef.current,\n signal,\n });\n try {\n return await create(token);\n } catch (error) {\n // The host refused the viewer token: renew it through the bridge (a\n // Marathon re-mint or the parent window's next token) and try once more.\n if (!isCredentialRefusal(error) || !renewToken) throw error;\n const renewed = await renewToken({ force: true });\n if (!renewed || renewed === token) throw error;\n return create(renewed);\n }\n },\n [],\n );\n\n const [status, setStatus] = useState<AthenaVoiceSessionStatus>('idle');\n const [activeSpeaker, setActiveSpeaker] = useState<AthenaVoiceSpeaker | null>(\n null,\n );\n const [isMuted, setIsMuted] = useState<boolean>(false);\n const [transcript, setTranscript] = useState<AthenaVoiceTranscriptTurn[]>([]);\n const [sessionId, setSessionId] = useState<string | null>(null);\n const [roomName, setRoomName] = useState<string | null>(null);\n const [error, setError] = useState<Error | null>(null);\n\n // Latest callbacks without re-subscribing room listeners on every render.\n const callbacksRef = useRef({\n createSession: createSession ?? createSessionAsViewer,\n onTranscript,\n onInterimTranscript,\n onError,\n });\n callbacksRef.current = {\n createSession: createSession ?? createSessionAsViewer,\n onTranscript,\n onInterimTranscript,\n onError,\n };\n\n const roomRef = useRef<Room | null>(null);\n const abortRef = useRef<AbortController | null>(null);\n const attachedElementsRef = useRef<HTMLMediaElement[]>([]);\n const ownedAudioRef = useRef<HTMLMediaElement | null>(null);\n const committedSegmentIdsRef = useRef<Set<string>>(new Set());\n // Guards `start()` against re-entry from the moment it is called, before any\n // state update lands — a StrictMode double effect fires both calls\n // synchronously in the same tick.\n const startingRef = useRef<boolean>(false);\n\n const fail = useCallback((cause: unknown) => {\n const err: Error = toError(cause);\n setError(err);\n setStatus('error');\n callbacksRef.current.onError?.(err);\n }, []);\n\n const detachAudio = useCallback(() => {\n for (const element of attachedElementsRef.current) {\n element.srcObject = null;\n if (element === ownedAudioRef.current) element.remove();\n }\n attachedElementsRef.current = [];\n ownedAudioRef.current = null;\n }, []);\n\n const teardown = useCallback(async () => {\n abortRef.current?.abort();\n abortRef.current = null;\n const room: Room | null = roomRef.current;\n roomRef.current = null;\n startingRef.current = false;\n detachAudio();\n if (room) {\n room.removeAllListeners();\n await room.disconnect(true);\n }\n }, [detachAudio]);\n\n const stop = useCallback(async () => {\n const hadRoom: boolean =\n roomRef.current !== null || abortRef.current !== null;\n await teardown();\n setActiveSpeaker(null);\n if (hadRoom) setStatus('ended');\n }, [teardown]);\n\n const attachTrack = useCallback(\n (track: RemoteTrack) => {\n if (track.kind !== Track.Kind.Audio) return;\n if (audioElement) {\n track.attach(audioElement);\n attachedElementsRef.current.push(audioElement);\n return;\n }\n const element: HTMLMediaElement = track.attach();\n element.setAttribute('data-athena-voice-audio', '');\n document.body.appendChild(element);\n ownedAudioRef.current = element;\n attachedElementsRef.current.push(element);\n },\n [audioElement],\n );\n\n const handleTranscription = useCallback(\n (\n segments: TranscriptionSegment[],\n participant: Participant | undefined,\n room: Room,\n ) => {\n const speaker: AthenaVoiceSpeaker = speakerOf(participant, room);\n const committed: AthenaVoiceTranscriptTurn[] = [];\n for (const segment of segments) {\n if (!segment.final) {\n callbacksRef.current.onInterimTranscript?.(speaker, segment.text);\n continue;\n }\n if (committedSegmentIdsRef.current.has(segment.id)) continue;\n committedSegmentIdsRef.current.add(segment.id);\n committed.push({\n id: segment.id,\n speaker,\n text: segment.text,\n startTime: segment.startTime,\n endTime: segment.endTime,\n language: segment.language,\n });\n }\n if (committed.length === 0) return;\n setTranscript((previous) => [...previous, ...committed]);\n for (const turn of committed) callbacksRef.current.onTranscript?.(turn);\n },\n [],\n );\n\n const start = useCallback(async () => {\n if (startingRef.current || roomRef.current) return;\n startingRef.current = true;\n setError(null);\n setSessionId(null);\n setRoomName(null);\n setStatus('connecting');\n\n const controller = new AbortController();\n abortRef.current = controller;\n\n let credentials: AthenaVoiceSessionCredentials;\n try {\n credentials = await callbacksRef.current.createSession(controller.signal);\n } catch (cause) {\n if (controller.signal.aborted) return;\n abortRef.current = null;\n startingRef.current = false;\n fail(cause);\n return;\n }\n if (controller.signal.aborted) return;\n\n setSessionId(credentials.asset_id ?? null);\n setRoomName(credentials.room_name ?? null);\n\n const room: Room = createRoom ? createRoom() : new Room();\n roomRef.current = room;\n\n room\n .on(RoomEvent.TrackSubscribed, attachTrack)\n .on(RoomEvent.ActiveSpeakersChanged, (speakers: Participant[]) => {\n const first: Participant | undefined = speakers[0];\n setActiveSpeaker(first ? speakerOf(first, room) : null);\n })\n .on(RoomEvent.TranscriptionReceived, (segments, participant) =>\n handleTranscription(segments, participant, room),\n )\n .on(RoomEvent.Reconnecting, () => setStatus('reconnecting'))\n .on(RoomEvent.Reconnected, () => setStatus('connected'))\n .on(RoomEvent.Disconnected, () => {\n if (roomRef.current !== room) return;\n roomRef.current = null;\n startingRef.current = false;\n detachAudio();\n setActiveSpeaker(null);\n setStatus('ended');\n })\n .on(RoomEvent.MediaDevicesError, fail);\n\n try {\n await room.connect(credentials.server_url, credentials.token);\n if (controller.signal.aborted) return;\n if (autoEnableMicrophone) {\n await room.localParticipant.setMicrophoneEnabled(true);\n setIsMuted(false);\n } else {\n setIsMuted(true);\n }\n if (controller.signal.aborted) return;\n abortRef.current = null;\n startingRef.current = false;\n setStatus('connected');\n } catch (cause) {\n if (controller.signal.aborted) return;\n await teardown();\n fail(cause);\n }\n }, [\n attachTrack,\n autoEnableMicrophone,\n createRoom,\n detachAudio,\n fail,\n handleTranscription,\n teardown,\n ]);\n\n const setMicrophone = useCallback(async (enabled: boolean) => {\n const room: Room | null = roomRef.current;\n if (!room) return;\n await room.localParticipant.setMicrophoneEnabled(enabled);\n setIsMuted(!enabled);\n }, []);\n const mute = useCallback(() => setMicrophone(false), [setMicrophone]);\n const unmute = useCallback(() => setMicrophone(true), [setMicrophone]);\n\n const clearTranscript = useCallback(() => {\n committedSegmentIdsRef.current.clear();\n setTranscript([]);\n }, []);\n\n // Unmount teardown is deferred one tick so StrictMode's synchronous\n // unmount/remount of the same instance does not abort an in-flight\n // `createSession` (which would dispatch a second voice agent on remount).\n const unmountTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n useEffect(() => {\n if (unmountTimerRef.current !== null) {\n clearTimeout(unmountTimerRef.current);\n unmountTimerRef.current = null;\n }\n return () => {\n unmountTimerRef.current = setTimeout(() => {\n unmountTimerRef.current = null;\n void teardown();\n }, 0);\n };\n }, [teardown]);\n\n return useMemo<UseAthenaVoiceSessionReturn>(\n () => ({\n status,\n isConnecting: status === 'connecting',\n isConnected: status === 'connected' || status === 'reconnecting',\n activeSpeaker,\n isMuted,\n transcript,\n sessionId,\n roomName,\n error,\n start,\n stop,\n mute,\n unmute,\n clearTranscript,\n }),\n [\n status,\n activeSpeaker,\n isMuted,\n transcript,\n sessionId,\n roomName,\n error,\n start,\n stop,\n mute,\n unmute,\n clearTranscript,\n ],\n );\n};\n"],"names":["useParentBridge","useRef","useEffect","useCallback","error","isCredentialRefusal","useState","Track","Room","RoomEvent","useMemo"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"use-athena-voice-session.cjs","sources":["../../src/voice/use-athena-voice-session.ts"],"sourcesContent":["import { useCallback, useEffect, useMemo, useRef, useState } from 'react';\nimport {\n Room,\n RoomEvent,\n Track,\n type Participant,\n type RemoteTrack,\n type TranscriptionSegment,\n} from 'livekit-client';\nimport { type ParentBridge, useParentBridge, type ParentBridgeState } from '../runtime/auth';\nimport { isCredentialRefusal } from '../runtime/credential-renewal';\n\n/**\n * Realtime connection details for one Athena voice session. This is the shape\n * the Athena voice session endpoint returns; the hook only reads these\n * fields, so any server that proxies that call can hand it straight back.\n */\nexport interface AthenaVoiceSessionCredentials {\n /** Realtime signalling URL (`wss://…`). */\n server_url: string;\n /** Short-lived participant JWT scoped to `room_name`. */\n token: string;\n room_name?: string;\n /**\n * Athena session asset the voice run is persisted into. Use it with\n * `GET /api/v0/sessions/{asset_id}/download` to retrieve the transcript\n * after the call.\n */\n asset_id?: string;\n}\n\nexport type AthenaVoiceSessionStatus =\n | 'idle'\n | 'connecting'\n | 'connected'\n | 'reconnecting'\n | 'ended'\n | 'error';\n\nexport type AthenaVoiceSpeaker = 'user' | 'agent';\n\n/** One committed (final) transcription segment from either side of the call. */\nexport interface AthenaVoiceTranscriptTurn {\n id: string;\n speaker: AthenaVoiceSpeaker;\n text: string;\n /** Segment start, in ms since the room's epoch. */\n startTime: number;\n endTime: number;\n language: string;\n}\n\n/**\n * A voice tool the Athena voice agent can run. These are voice tool\n * names, not the chat `Toolkits` ids: `'web_search_browse_toolkit'` is not a\n * voice tool, `'web_search'` is. Only these names are accepted.\n *\n * The agent also has tools that call back into the client over room RPC\n * (clipboard, selection, screen contents, opening assets). This hook registers\n * no RPC handlers, so they are not part of its contract.\n */\nexport type AthenaVoiceToolId =\n /** Web search. */\n | 'web_search'\n /** Legacy alias of `web_search`; prefer `web_search`. */\n | 'search_web'\n /** Fetch and read one URL. */\n | 'browse'\n /** @deprecated Retired: accepted and ignored, the agent gets no such tool. */\n | 'search_knowledge_base'\n /** @deprecated Retired: accepted and ignored, the agent gets no such tool. */\n | 'search_knowledge_base_lr'\n /** Read Athena assets by id, as the viewer. */\n | 'read_full_asset'\n /** Search the viewer's Athena assets. */\n | 'search_assets'\n /** Hand a question to the general agent and speak its answer. */\n | 'ask_agent'\n /** Save a note for the user (a stub on the worker today). */\n | 'save_note'\n /** Current date and time, Eastern. */\n | 'get_current_time_est';\n\n/**\n * Voice agent configuration for a session the hook creates itself (see\n * `UseAthenaVoiceSessionOptions.session`). Mirrors the body of the Athena\n * voice session endpoint; every field is optional and falls back to the\n * server default.\n */\nexport interface AthenaVoiceSessionConfig {\n /** Persona / instructions for the voice agent. */\n system_prompt?: string;\n /** Realtime provider, e.g. `'openai'` or `'google'`. */\n provider?: string;\n /** Provider model id, e.g. `'gpt-realtime-2'`. */\n model?: string;\n /** Provider voice id, e.g. `'marin'` (OpenAI) or `'Aoede'` (Google). */\n voice?: string;\n temperature?: number;\n /** BCP-47 language tag; default `'en'`. */\n language?: string;\n /**\n * Voice tools the agent may call. Omit it for the server's default set\n * (`web_search`, `save_note`, `ask_agent`, …); pass `[]` for a\n * pure conversation with no tool calls.\n */\n enabled_tools?: AthenaVoiceToolId[];\n /** IANA timezone of the speaker, e.g. `'America/New_York'`. */\n timezone?: string;\n /**\n * Start without the agent's opening greeting: it stays quiet (no audio, no\n * transcript turn) until a participant speaks. Default `false`.\n */\n silent_start?: boolean;\n}\n\nexport interface UseAthenaVoiceSessionOptions {\n /**\n * Creates the voice session. Omit it when the app is served from a\n * Marathon computer-asset URL: the hook then calls the Athena voice session\n * endpoint itself with the viewer's bearer token from `/_athena/auth`, so\n * the session is created as — and shows up in the sessions of — whoever is\n * using the app.\n *\n * Works for workspace members and external SSO viewers alike: the scoped\n * `athview_` viewer credential is authorized for the voice session route and\n * `agents/general/invoke` the same way it is for `/api/v0/sessions`.\n *\n * Supply it when the app runs anywhere else (standalone, custom auth): it\n * should run on the caller's own server so the Athena API key never reaches\n * the browser. The hook only reads the returned credentials.\n *\n * Decide once: switching between supplying and omitting it across renders\n * of the same component is not supported.\n */\n createSession?: (\n signal: AbortSignal,\n ) => Promise<AthenaVoiceSessionCredentials>;\n /**\n * Agent configuration for sessions the hook creates itself. Ignored when\n * `createSession` is supplied.\n */\n session?: AthenaVoiceSessionConfig;\n /** Called once per committed transcript turn, in arrival order. */\n onTranscript?: (turn: AthenaVoiceTranscriptTurn) => void;\n /** Called with interim (non-final) transcript text as it streams in. */\n onInterimTranscript?: (speaker: AthenaVoiceSpeaker, text: string) => void;\n onError?: (error: Error) => void;\n /**\n * Where to play the agent's audio. Defaults to a detached `<audio>` element\n * the hook creates and removes itself.\n */\n audioElement?: HTMLMediaElement | null;\n /** Enable the microphone as soon as the room connects. Default `true`. */\n autoEnableMicrophone?: boolean;\n /** @internal Overrides `new Room()`; used by tests. */\n createRoom?: () => Room;\n /** @internal Overrides `useParentBridge()`; used by tests. */\n useBridge?: () => ParentBridgeState & Partial<Pick<ParentBridge, 'renewToken'>>;\n}\n\nexport interface UseAthenaVoiceSessionReturn {\n status: AthenaVoiceSessionStatus;\n /** True between `start()` resolving the session and the room connecting. */\n isConnecting: boolean;\n isConnected: boolean;\n /** Who is speaking right now, or `null` when the room is quiet. */\n activeSpeaker: AthenaVoiceSpeaker | null;\n isMuted: boolean;\n /** Committed transcript turns so far, in arrival order. */\n transcript: AthenaVoiceTranscriptTurn[];\n /** Athena session asset id, once the session has been created. */\n sessionId: string | null;\n roomName: string | null;\n error: Error | null;\n /** Creates a session and joins the room. No-op while a session is live. */\n start: () => Promise<void>;\n /** Leaves the room and stops local tracks. Safe to call at any time. */\n stop: () => Promise<void>;\n mute: () => Promise<void>;\n unmute: () => Promise<void>;\n /** Clears `transcript`; does not affect the live session. */\n clearTranscript: () => void;\n}\n\nconst toError = (value: unknown): Error =>\n value instanceof Error ? value : new Error(String(value));\n\nconst NO_BRIDGE: ParentBridgeState = {\n token: null,\n statewireSyncUrl: null,\n backendBaseUrl: null,\n appUrl: null,\n hostAnswered: false,\n ready: true,\n};\n// Stands in for `useParentBridge` when the caller creates sessions itself, so\n// the hook never fetches `/_athena/auth` it would not use.\nconst useNoBridge = (): ParentBridgeState => NO_BRIDGE;\n\nconst NO_VIEWER_TOKEN_MESSAGE =\n 'useAthenaVoiceSession: no Athena viewer token. Either serve the app from ' +\n 'a Marathon computer-asset URL (which mints one via /_athena/auth) or pass ' +\n '`createSession` to create the session through your own server.';\n\n/**\n * Creates an Athena voice session as the current viewer. Exported so apps with\n * their own bridge state (or a server proxy holding a user bearer) can reuse\n * the exact request the hook makes.\n */\nexport const createAthenaVoiceSession = async ({\n backendBaseUrl,\n token,\n session = {},\n signal,\n}: {\n /** Bare Athena API base, e.g. `https://api.athenaintel.com`. */\n backendBaseUrl: string;\n /** Bearer token for the user the session belongs to. */\n token: string;\n session?: AthenaVoiceSessionConfig;\n signal?: AbortSignal;\n}): Promise<AthenaVoiceSessionCredentials> => {\n const url: string = `${backendBaseUrl.replace(/\\/+$/, '')}/api/orpheus/create-session`;\n const response: Response = await fetch(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${token}`,\n },\n body: JSON.stringify(session),\n signal,\n });\n if (!response.ok) {\n const detail: string = await response.text().catch(() => '');\n // `status` lets a caller tell a refused credential (401) from any other failure.\n throw Object.assign(\n new Error(\n `Athena voice session creation failed (${response.status})${detail ? `: ${detail}` : ''}`,\n ),\n { status: response.status },\n );\n }\n return (await response.json()) as AthenaVoiceSessionCredentials;\n};\n\nconst speakerOf = (\n participant: Participant | undefined,\n room: Room,\n): AthenaVoiceSpeaker =>\n participant !== undefined &&\n participant.identity === room.localParticipant.identity\n ? 'user'\n : 'agent';\n\n/**\n * Runs one Athena voice session from React.\n *\n * Owns the whole browser-side lifecycle the voice API leaves to the caller:\n * creating the session through the app's own server, joining the room,\n * publishing the microphone, playing the agent's audio, tracking who is\n * speaking, committing transcript turns from room transcription events, and\n * tearing everything down on `stop()` or unmount. A second `start()` while a\n * session is live (or still connecting) is ignored, so React StrictMode's\n * double-invoked effects cannot dispatch two agents into one room.\n */\nexport const useAthenaVoiceSession = (\n options: UseAthenaVoiceSessionOptions = {},\n): UseAthenaVoiceSessionReturn => {\n const {\n createSession,\n session,\n onTranscript,\n onInterimTranscript,\n onError,\n audioElement,\n autoEnableMicrophone = true,\n createRoom,\n useBridge = createSession ? useNoBridge : useParentBridge,\n } = options;\n\n // Viewer identity minted by Marathon (`/_athena/auth`) or the Athena app\n // iframe bridge. Only consulted when the caller did not supply `createSession`.\n const bridge: ParentBridgeState & Partial<Pick<ParentBridge, 'renewToken'>> = useBridge();\n const bridgeRef = useRef(bridge);\n bridgeRef.current = bridge;\n const bridgeReadyWaitersRef = useRef<Array<() => void>>([]);\n useEffect(() => {\n if (!bridge.ready) return;\n const waiters: Array<() => void> = bridgeReadyWaitersRef.current;\n bridgeReadyWaitersRef.current = [];\n for (const resolve of waiters) resolve();\n }, [bridge.ready]);\n\n const sessionRef = useRef<AthenaVoiceSessionConfig | undefined>(session);\n sessionRef.current = session;\n\n const createSessionAsViewer = useCallback(\n async (signal: AbortSignal): Promise<AthenaVoiceSessionCredentials> => {\n if (!bridgeRef.current.ready) {\n await new Promise<void>((resolve) => {\n bridgeReadyWaitersRef.current.push(resolve);\n signal.addEventListener('abort', () => resolve(), { once: true });\n });\n if (signal.aborted) throw new Error('aborted');\n }\n const { token, backendBaseUrl, renewToken } = bridgeRef.current;\n if (!token || !backendBaseUrl) throw new Error(NO_VIEWER_TOKEN_MESSAGE);\n const create = (viewerToken: string) =>\n createAthenaVoiceSession({\n backendBaseUrl,\n token: viewerToken,\n session: sessionRef.current,\n signal,\n });\n try {\n return await create(token);\n } catch (error) {\n // The host refused the viewer token: renew it through the bridge (a\n // Marathon re-mint or the parent window's next token) and try once more.\n if (!isCredentialRefusal(error) || !renewToken) throw error;\n const renewed = await renewToken({ force: true });\n if (!renewed || renewed === token) throw error;\n return create(renewed);\n }\n },\n [],\n );\n\n const [status, setStatus] = useState<AthenaVoiceSessionStatus>('idle');\n const [activeSpeaker, setActiveSpeaker] = useState<AthenaVoiceSpeaker | null>(\n null,\n );\n const [isMuted, setIsMuted] = useState<boolean>(false);\n const [transcript, setTranscript] = useState<AthenaVoiceTranscriptTurn[]>([]);\n const [sessionId, setSessionId] = useState<string | null>(null);\n const [roomName, setRoomName] = useState<string | null>(null);\n const [error, setError] = useState<Error | null>(null);\n\n // Latest callbacks without re-subscribing room listeners on every render.\n const callbacksRef = useRef({\n createSession: createSession ?? createSessionAsViewer,\n onTranscript,\n onInterimTranscript,\n onError,\n });\n callbacksRef.current = {\n createSession: createSession ?? createSessionAsViewer,\n onTranscript,\n onInterimTranscript,\n onError,\n };\n\n const roomRef = useRef<Room | null>(null);\n const abortRef = useRef<AbortController | null>(null);\n const attachedElementsRef = useRef<HTMLMediaElement[]>([]);\n const ownedAudioRef = useRef<HTMLMediaElement | null>(null);\n const committedSegmentIdsRef = useRef<Set<string>>(new Set());\n // Guards `start()` against re-entry from the moment it is called, before any\n // state update lands — a StrictMode double effect fires both calls\n // synchronously in the same tick.\n const startingRef = useRef<boolean>(false);\n\n const fail = useCallback((cause: unknown) => {\n const err: Error = toError(cause);\n setError(err);\n setStatus('error');\n callbacksRef.current.onError?.(err);\n }, []);\n\n const detachAudio = useCallback(() => {\n for (const element of attachedElementsRef.current) {\n element.srcObject = null;\n if (element === ownedAudioRef.current) element.remove();\n }\n attachedElementsRef.current = [];\n ownedAudioRef.current = null;\n }, []);\n\n const teardown = useCallback(async () => {\n abortRef.current?.abort();\n abortRef.current = null;\n const room: Room | null = roomRef.current;\n roomRef.current = null;\n startingRef.current = false;\n detachAudio();\n if (room) {\n room.removeAllListeners();\n await room.disconnect(true);\n }\n }, [detachAudio]);\n\n const stop = useCallback(async () => {\n const hadRoom: boolean =\n roomRef.current !== null || abortRef.current !== null;\n await teardown();\n setActiveSpeaker(null);\n if (hadRoom) setStatus('ended');\n }, [teardown]);\n\n const attachTrack = useCallback(\n (track: RemoteTrack) => {\n if (track.kind !== Track.Kind.Audio) return;\n if (audioElement) {\n track.attach(audioElement);\n attachedElementsRef.current.push(audioElement);\n return;\n }\n const element: HTMLMediaElement = track.attach();\n element.setAttribute('data-athena-voice-audio', '');\n document.body.appendChild(element);\n ownedAudioRef.current = element;\n attachedElementsRef.current.push(element);\n },\n [audioElement],\n );\n\n const handleTranscription = useCallback(\n (\n segments: TranscriptionSegment[],\n participant: Participant | undefined,\n room: Room,\n ) => {\n const speaker: AthenaVoiceSpeaker = speakerOf(participant, room);\n const committed: AthenaVoiceTranscriptTurn[] = [];\n for (const segment of segments) {\n if (!segment.final) {\n callbacksRef.current.onInterimTranscript?.(speaker, segment.text);\n continue;\n }\n if (committedSegmentIdsRef.current.has(segment.id)) continue;\n committedSegmentIdsRef.current.add(segment.id);\n committed.push({\n id: segment.id,\n speaker,\n text: segment.text,\n startTime: segment.startTime,\n endTime: segment.endTime,\n language: segment.language,\n });\n }\n if (committed.length === 0) return;\n setTranscript((previous) => [...previous, ...committed]);\n for (const turn of committed) callbacksRef.current.onTranscript?.(turn);\n },\n [],\n );\n\n const start = useCallback(async () => {\n if (startingRef.current || roomRef.current) return;\n startingRef.current = true;\n setError(null);\n setSessionId(null);\n setRoomName(null);\n setStatus('connecting');\n\n const controller = new AbortController();\n abortRef.current = controller;\n\n let credentials: AthenaVoiceSessionCredentials;\n try {\n credentials = await callbacksRef.current.createSession(controller.signal);\n } catch (cause) {\n if (controller.signal.aborted) return;\n abortRef.current = null;\n startingRef.current = false;\n fail(cause);\n return;\n }\n if (controller.signal.aborted) return;\n\n setSessionId(credentials.asset_id ?? null);\n setRoomName(credentials.room_name ?? null);\n\n const room: Room = createRoom ? createRoom() : new Room();\n roomRef.current = room;\n\n room\n .on(RoomEvent.TrackSubscribed, attachTrack)\n .on(RoomEvent.ActiveSpeakersChanged, (speakers: Participant[]) => {\n const first: Participant | undefined = speakers[0];\n setActiveSpeaker(first ? speakerOf(first, room) : null);\n })\n .on(RoomEvent.TranscriptionReceived, (segments, participant) =>\n handleTranscription(segments, participant, room),\n )\n .on(RoomEvent.Reconnecting, () => setStatus('reconnecting'))\n .on(RoomEvent.Reconnected, () => setStatus('connected'))\n .on(RoomEvent.Disconnected, () => {\n if (roomRef.current !== room) return;\n roomRef.current = null;\n startingRef.current = false;\n detachAudio();\n setActiveSpeaker(null);\n setStatus('ended');\n })\n .on(RoomEvent.MediaDevicesError, fail);\n\n try {\n await room.connect(credentials.server_url, credentials.token);\n if (controller.signal.aborted) return;\n if (autoEnableMicrophone) {\n await room.localParticipant.setMicrophoneEnabled(true);\n setIsMuted(false);\n } else {\n setIsMuted(true);\n }\n if (controller.signal.aborted) return;\n abortRef.current = null;\n startingRef.current = false;\n setStatus('connected');\n } catch (cause) {\n if (controller.signal.aborted) return;\n await teardown();\n fail(cause);\n }\n }, [\n attachTrack,\n autoEnableMicrophone,\n createRoom,\n detachAudio,\n fail,\n handleTranscription,\n teardown,\n ]);\n\n const setMicrophone = useCallback(async (enabled: boolean) => {\n const room: Room | null = roomRef.current;\n if (!room) return;\n await room.localParticipant.setMicrophoneEnabled(enabled);\n setIsMuted(!enabled);\n }, []);\n const mute = useCallback(() => setMicrophone(false), [setMicrophone]);\n const unmute = useCallback(() => setMicrophone(true), [setMicrophone]);\n\n const clearTranscript = useCallback(() => {\n committedSegmentIdsRef.current.clear();\n setTranscript([]);\n }, []);\n\n // Unmount teardown is deferred one tick so StrictMode's synchronous\n // unmount/remount of the same instance does not abort an in-flight\n // `createSession` (which would dispatch a second voice agent on remount).\n const unmountTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n useEffect(() => {\n if (unmountTimerRef.current !== null) {\n clearTimeout(unmountTimerRef.current);\n unmountTimerRef.current = null;\n }\n return () => {\n unmountTimerRef.current = setTimeout(() => {\n unmountTimerRef.current = null;\n void teardown();\n }, 0);\n };\n }, [teardown]);\n\n return useMemo<UseAthenaVoiceSessionReturn>(\n () => ({\n status,\n isConnecting: status === 'connecting',\n isConnected: status === 'connected' || status === 'reconnecting',\n activeSpeaker,\n isMuted,\n transcript,\n sessionId,\n roomName,\n error,\n start,\n stop,\n mute,\n unmute,\n clearTranscript,\n }),\n [\n status,\n activeSpeaker,\n isMuted,\n transcript,\n sessionId,\n roomName,\n error,\n start,\n stop,\n mute,\n unmute,\n clearTranscript,\n ],\n );\n};\n"],"names":["useParentBridge","useRef","useEffect","useCallback","error","isCredentialRefusal","useState","Track","Room","RoomEvent","useMemo"],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
4
|
const reactQuery = require("@tanstack/react-query");
|
|
5
5
|
const lucideReact = require("lucide-react");
|
|
6
|
-
const
|
|
6
|
+
const require$$0 = require("react");
|
|
7
7
|
const useAthenaRestQuery = require("../lib/use-athena-rest-query.cjs");
|
|
8
8
|
const AthenaContext = require("../provider/AthenaContext.cjs");
|
|
9
9
|
const liveDesktopApi = require("./live-desktop-api.cjs");
|
|
@@ -35,12 +35,12 @@ const ComputerLiveDesktopView = ({
|
|
|
35
35
|
const status = useSessionWorkspace.useAthenaComputerStatus({ assetId });
|
|
36
36
|
const state = ((_a = status.data) == null ? void 0 : _a.state.toLowerCase()) ?? null;
|
|
37
37
|
const running = state !== null && RUNNING_STATES.has(state) && ((_b = status.data) == null ? void 0 : _b.explicitStop) !== "stopping";
|
|
38
|
-
const visible = ((_c =
|
|
39
|
-
const [viewer, setViewer] =
|
|
40
|
-
const [notice, setNotice] =
|
|
41
|
-
const [switchError, setSwitchError] =
|
|
42
|
-
const frameRef =
|
|
43
|
-
const viewerRef =
|
|
38
|
+
const visible = ((_c = require$$0.useContext(sessionWorkbenchContext.SessionWorkbenchContext)) == null ? void 0 : _c.isVisible) ?? true;
|
|
39
|
+
const [viewer, setViewer] = require$$0.useState(null);
|
|
40
|
+
const [notice, setNotice] = require$$0.useState(null);
|
|
41
|
+
const [switchError, setSwitchError] = require$$0.useState(null);
|
|
42
|
+
const frameRef = require$$0.useRef(null);
|
|
43
|
+
const viewerRef = require$$0.useRef(null);
|
|
44
44
|
viewerRef.current = viewer;
|
|
45
45
|
const session = reactQuery.useMutation(
|
|
46
46
|
{
|
|
@@ -86,23 +86,23 @@ const ComputerLiveDesktopView = ({
|
|
|
86
86
|
queryClient
|
|
87
87
|
);
|
|
88
88
|
const { mutate, reset } = session;
|
|
89
|
-
const opened =
|
|
90
|
-
const disconnectedByPerson =
|
|
91
|
-
|
|
89
|
+
const opened = require$$0.useRef(false);
|
|
90
|
+
const disconnectedByPerson = require$$0.useRef(false);
|
|
91
|
+
require$$0.useEffect(() => {
|
|
92
92
|
if (running && visible) return;
|
|
93
93
|
reset();
|
|
94
94
|
setViewer(null);
|
|
95
95
|
setSwitchError(null);
|
|
96
96
|
opened.current = false;
|
|
97
97
|
}, [running, visible, reset]);
|
|
98
|
-
|
|
98
|
+
require$$0.useEffect(() => {
|
|
99
99
|
if (!running || !visible || opened.current || disconnectedByPerson.current) return;
|
|
100
100
|
opened.current = true;
|
|
101
101
|
mutate({ mode: liveDesktopApi.LiveDesktopMode.WATCH, start: false });
|
|
102
102
|
}, [running, visible, mutate]);
|
|
103
103
|
const viewerUrl = (viewer == null ? void 0 : viewer.url) ?? null;
|
|
104
104
|
const viewerState = (viewer == null ? void 0 : viewer.state) ?? null;
|
|
105
|
-
|
|
105
|
+
require$$0.useEffect(() => {
|
|
106
106
|
if (!viewerUrl) return void 0;
|
|
107
107
|
const origin = new URL(viewerUrl).origin;
|
|
108
108
|
const end = (text) => {
|
|
@@ -128,7 +128,7 @@ const ComputerLiveDesktopView = ({
|
|
|
128
128
|
window.addEventListener("message", onMessage);
|
|
129
129
|
return () => window.removeEventListener("message", onMessage);
|
|
130
130
|
}, [viewerUrl]);
|
|
131
|
-
|
|
131
|
+
require$$0.useEffect(() => {
|
|
132
132
|
if (!viewerUrl || viewerState !== "connecting") return void 0;
|
|
133
133
|
const timer = setTimeout(() => {
|
|
134
134
|
setViewer((current) => (current == null ? void 0 : current.url) === viewerUrl ? null : current);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ComputerLiveDesktop.cjs","sources":["../../src/workbench/ComputerLiveDesktop.tsx"],"sourcesContent":["\"use client\";\n\nimport { useMutation } from '@tanstack/react-query';\nimport {\n AlertCircleIcon,\n EyeIcon,\n LoaderIcon,\n MonitorOffIcon,\n MousePointer2Icon,\n PlayIcon,\n RefreshCwIcon,\n XIcon,\n} from 'lucide-react';\nimport { type FC, type ReactNode, useContext, useEffect, useRef, useState } from 'react';\nimport { useAthenaQueryClient } from '../lib/use-athena-rest-query';\nimport { cn } from '../lib/utils';\nimport { useAthenaConfig } from '../provider/AthenaContext';\nimport {\n createComputerLiveDesktopSession,\n finalLiveDesktopCloseNotice,\n LiveDesktopMode,\n type LiveDesktopSession,\n liveDesktopViewerUrl,\n readLiveDesktopViewerMessage,\n} from './live-desktop-api';\nimport { SessionWorkbenchContext } from './session-workbench-context';\nimport { useAthenaComputerStatus } from './use-session-workspace';\n\n/** How long a viewer may take to show video before the pane calls it failed. */\nexport const LIVE_DESKTOP_READY_TIMEOUT_MS = 30_000;\n\nconst RUNNING_STATES: ReadonlySet<string> = new Set(['started', 'running', 'ready']);\n\nconst BUTTON_CLASS =\n 'inline-flex shrink-0 items-center gap-1 rounded-md border border-border bg-background px-2 py-1 font-medium text-xs transition-colors hover:bg-muted outline-none focus-visible:ring-2 focus-visible:ring-ring/60 disabled:opacity-60';\n\n/** The viewer page the pane frames: one per ticket, its own messages move it on. */\ninterface MountedViewer {\n url: string;\n mode: LiveDesktopMode;\n display: { width: number; height: number } | null;\n /** `connected` once the page reports video (`ready`); never on a socket alone. */\n state: 'connecting' | 'connected';\n}\n\n/** Why the pane shows no viewer, when it has something to say. */\ntype Notice =\n | { kind: 'display_not_running'; text: string }\n | { kind: 'unsupported'; text: string }\n | { kind: 'ended'; text: string }\n | { kind: 'failed'; text: string };\n\ninterface SessionRequest {\n mode: LiveDesktopMode;\n start: boolean;\n}\n\nconst Placeholder: FC<{ icon?: ReactNode; children: ReactNode; action?: ReactNode }> = ({\n icon,\n children,\n action,\n}) => (\n <div className=\"flex h-full w-full flex-col items-center justify-center gap-2 p-4 text-center\">\n {icon}\n <p className=\"max-w-72 text-muted-foreground text-xs leading-snug\">{children}</p>\n {action}\n </div>\n);\n\nexport interface ComputerLiveDesktopProps {\n assetId: string;\n className?: string;\n /** How long a viewer may take to show video ({@link LIVE_DESKTOP_READY_TIMEOUT_MS}). */\n readyTimeoutMs?: number;\n}\n\n/**\n * The computer's screen, live — watch it, or take control and use it — framed\n * from agora's Selkies viewer (agora `web/api/computer/live_desktop_viewer.py`).\n *\n * Opens watching as soon as it mounts on a running computer, and ends when it\n * unmounts, its workbench collapses to the rail, or the computer stops (an open\n * view keeps the computer awake, up to agora's 30-minute cap). Needs EDIT on\n * the computer, in its own workspace, and an app the computer serves on Athena\n * (agora binds the viewer to this page's origin). A computer without a display\n * (one not made from the Browser template) says so instead.\n *\n * The frame runs Selkies' page from the guest, sandboxed as Olympus frames it:\n * scripts on agora's origin, no popups, forms or top navigation. Its messages\n * only move this pane between connecting, connected and ended. Each computer\n * is its own instance (keyed by `assetId`), so a switch never shows or drives\n * the previous computer's screen.\n */\nexport const ComputerLiveDesktop: FC<ComputerLiveDesktopProps> = (props) => (\n <ComputerLiveDesktopView key={props.assetId} {...props} />\n);\n\nconst ComputerLiveDesktopView: FC<ComputerLiveDesktopProps> = ({\n assetId,\n className,\n readyTimeoutMs = LIVE_DESKTOP_READY_TIMEOUT_MS,\n}) => {\n const config = useAthenaConfig();\n const { backendUrl, apiKey, getToken } = config;\n const queryClient = useAthenaQueryClient();\n const status = useAthenaComputerStatus({ assetId });\n const state = status.data?.state.toLowerCase() ?? null;\n const running =\n state !== null && RUNNING_STATES.has(state) && status.data?.explicitStop !== 'stopping';\n // Hidden in a collapsed workbench, the pane stops its stream.\n const visible = useContext(SessionWorkbenchContext)?.isVisible ?? true;\n\n const [viewer, setViewer] = useState<MountedViewer | null>(null);\n const [notice, setNotice] = useState<Notice | null>(null);\n // A mode switch that failed while a viewer stayed on screen.\n const [switchError, setSwitchError] = useState<string | null>(null);\n const frameRef = useRef<HTMLIFrameElement>(null);\n const viewerRef = useRef<MountedViewer | null>(null);\n viewerRef.current = viewer;\n\n const session = useMutation<LiveDesktopSession, Error, SessionRequest>(\n {\n mutationFn: ({ mode, start }) =>\n createComputerLiveDesktopSession({\n backendUrl,\n // `config.token` is read at request time: the provider serves the\n // latest token through a getter.\n auth: { apiKey, token: config.token, getToken },\n assetId,\n mode,\n start,\n embedOrigin: typeof window === 'undefined' ? null : window.location.origin,\n }),\n onSuccess: (answer) => {\n setSwitchError(null);\n if (answer.status !== 'ready') {\n setViewer(null);\n setNotice({ kind: answer.status, text: answer.detail });\n return;\n }\n let url: string;\n try {\n url = liveDesktopViewerUrl({ backendUrl, viewerPath: answer.viewerPath });\n } catch {\n setViewer(null);\n setNotice({\n kind: 'failed',\n text: 'The computer’s desktop answered with a page this app will not open.',\n });\n return;\n }\n // The new page replaces the one on screen only now that it exists.\n setViewer({ url, mode: answer.mode, display: answer.display, state: 'connecting' });\n setNotice(null);\n },\n onError: (error) => {\n // A failed switch leaves the working viewer where it is.\n if (viewerRef.current) {\n setSwitchError(error.message);\n return;\n }\n setNotice({ kind: 'failed', text: error.message });\n },\n },\n queryClient,\n );\n const { mutate, reset } = session;\n\n const opened = useRef(false);\n const disconnectedByPerson = useRef(false);\n\n // Hidden, or the computer stopped: drop the view. Its ticket is spent, so\n // showing again (or the computer starting again) asks for a fresh one.\n useEffect(() => {\n if (running && visible) return;\n reset();\n setViewer(null);\n setSwitchError(null);\n opened.current = false;\n }, [running, visible, reset]);\n // Watch once the computer is known to be running; never wake one.\n useEffect(() => {\n if (!running || !visible || opened.current || disconnectedByPerson.current) return;\n opened.current = true;\n mutate({ mode: LiveDesktopMode.WATCH, start: false });\n }, [running, visible, mutate]);\n\n // The viewer page's own messages move it on; a page agora ended takes the\n // frame down (an unseen stream would keep the computer awake).\n const viewerUrl = viewer?.url ?? null;\n const viewerState = viewer?.state ?? null;\n useEffect(() => {\n if (!viewerUrl) return undefined;\n const origin = new URL(viewerUrl).origin;\n const end = (text: string) => {\n setViewer((current) => (current?.url === viewerUrl ? null : current));\n setNotice({ kind: 'ended', text });\n };\n const onMessage = (event: MessageEvent) => {\n if (event.origin !== origin || event.source !== frameRef.current?.contentWindow) return;\n const message = readLiveDesktopViewerMessage(event.data);\n if (!message) return;\n if (message.status === 'ready') {\n setViewer((current) =>\n current?.url === viewerUrl ? { ...current, state: 'connected' } : current,\n );\n } else if (message.status === 'error') {\n end(message.detail);\n } else if (message.status === 'closed') {\n const final = finalLiveDesktopCloseNotice(message.code);\n if (final) end(final);\n }\n };\n window.addEventListener('message', onMessage);\n return () => window.removeEventListener('message', onMessage);\n }, [viewerUrl]);\n // No video within the timeout takes the frame down too.\n useEffect(() => {\n if (!viewerUrl || viewerState !== 'connecting') return undefined;\n const timer = setTimeout(() => {\n setViewer((current) => (current?.url === viewerUrl ? null : current));\n setNotice({\n kind: 'ended',\n text: 'The desktop did not start streaming here. Reconnect to try again.',\n });\n }, readyTimeoutMs);\n return () => clearTimeout(timer);\n }, [viewerUrl, viewerState, readyTimeoutMs]);\n\n const watch = (start = false) => {\n disconnectedByPerson.current = false;\n opened.current = true;\n mutate({ mode: LiveDesktopMode.WATCH, start });\n };\n const control = () => mutate({ mode: LiveDesktopMode.CONTROL, start: false });\n const disconnect = () => {\n disconnectedByPerson.current = true;\n reset();\n setViewer(null);\n setNotice(null);\n setSwitchError(null);\n };\n\n const aspect = viewer?.display ? `${viewer.display.width} / ${viewer.display.height}` : '16 / 10';\n let body: ReactNode;\n if (!running) {\n body = (\n <Placeholder icon={<MonitorOffIcon className=\"size-5 text-muted-foreground/70\" aria-hidden />}>\n {status.isPending\n ? 'Checking the computer…'\n : 'The computer is not running. Its desktop shows here once it is.'}\n </Placeholder>\n );\n } else if (viewer) {\n body = (\n <>\n <iframe\n ref={frameRef}\n key={viewer.url}\n src={viewer.url}\n title=\"Live desktop\"\n className=\"h-full w-full border-0 bg-black\"\n sandbox=\"allow-scripts allow-same-origin allow-pointer-lock\"\n allow=\"fullscreen; keyboard-map; autoplay; clipboard-write\"\n referrerPolicy=\"no-referrer\"\n data-live-desktop-frame=\"\"\n />\n {viewer.state === 'connecting' || session.isPending ? (\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center bg-black/40\">\n <LoaderIcon className=\"size-5 animate-spin text-white\" aria-label=\"Connecting\" />\n </div>\n ) : null}\n {switchError ? (\n <div\n role=\"alert\"\n className=\"absolute inset-x-2 bottom-2 flex items-start gap-2 rounded-md border border-red-200 bg-red-50 px-2 py-1.5 text-red-900 text-xs\"\n >\n <AlertCircleIcon className=\"mt-0.5 size-3.5 shrink-0\" aria-hidden />\n <span className=\"min-w-0 flex-1\">{switchError}</span>\n <button\n type=\"button\"\n onClick={() => setSwitchError(null)}\n aria-label=\"Dismiss\"\n className=\"shrink-0 rounded p-0.5 hover:bg-red-100\"\n >\n <XIcon className=\"size-3\" aria-hidden />\n </button>\n </div>\n ) : null}\n </>\n );\n } else if (session.isPending) {\n body = (\n <Placeholder icon={<LoaderIcon className=\"size-5 animate-spin text-muted-foreground\" aria-hidden />}>\n Connecting to the desktop…\n </Placeholder>\n );\n } else if (notice?.kind === 'display_not_running') {\n body = (\n <Placeholder\n icon={<MonitorOffIcon className=\"size-5 text-muted-foreground/70\" aria-hidden />}\n action={\n <button type=\"button\" onClick={() => watch(true)} className={BUTTON_CLASS}>\n <PlayIcon className=\"size-3.5\" aria-hidden />\n Start the display\n </button>\n }\n >\n {notice.text}\n </Placeholder>\n );\n } else if (notice?.kind === 'unsupported') {\n body = (\n <Placeholder icon={<MonitorOffIcon className=\"size-5 text-muted-foreground/70\" aria-hidden />}>\n {notice.text}\n </Placeholder>\n );\n } else if (notice) {\n body = (\n <Placeholder\n icon={\n notice.kind === 'failed' ? (\n <AlertCircleIcon className=\"size-5 text-red-600\" aria-hidden />\n ) : (\n <MonitorOffIcon className=\"size-5 text-muted-foreground/70\" aria-hidden />\n )\n }\n action={\n <button type=\"button\" onClick={() => watch()} className={BUTTON_CLASS}>\n <RefreshCwIcon className=\"size-3.5\" aria-hidden />\n {notice.kind === 'failed' ? 'Try again' : 'Reconnect'}\n </button>\n }\n >\n {notice.text}\n </Placeholder>\n );\n } else {\n body = (\n <Placeholder\n icon={<EyeIcon className=\"size-5 text-muted-foreground/70\" aria-hidden />}\n action={\n <button type=\"button\" onClick={() => watch()} className={BUTTON_CLASS}>\n <EyeIcon className=\"size-3.5\" aria-hidden />\n Watch live\n </button>\n }\n >\n Watch the computer’s screen as the agent works.\n </Placeholder>\n );\n }\n\n const liveMode = running && viewer ? viewer.mode : null;\n return (\n <section aria-label=\"Live desktop\" className={cn('flex flex-col gap-1.5', className)}>\n <div className=\"flex items-center gap-2\">\n <h3 className=\"font-medium text-[11px] text-muted-foreground uppercase tracking-wide\">\n Live desktop\n </h3>\n {liveMode ? (\n <span\n data-mode={liveMode}\n className={cn(\n 'rounded-full px-1.5 py-px text-[10px]',\n liveMode === LiveDesktopMode.CONTROL\n ? 'bg-amber-100 text-amber-900'\n : 'bg-muted text-muted-foreground',\n )}\n >\n {liveMode === LiveDesktopMode.CONTROL ? 'In control' : 'Watching'}\n </span>\n ) : null}\n <div className=\"min-w-0 flex-1\" />\n {liveMode === LiveDesktopMode.WATCH ? (\n <button type=\"button\" onClick={control} disabled={session.isPending} className={BUTTON_CLASS}>\n <MousePointer2Icon className=\"size-3.5\" aria-hidden />\n Take control\n </button>\n ) : null}\n {liveMode === LiveDesktopMode.CONTROL ? (\n <button type=\"button\" onClick={() => watch()} disabled={session.isPending} className={BUTTON_CLASS}>\n <EyeIcon className=\"size-3.5\" aria-hidden />\n Stop controlling\n </button>\n ) : null}\n {liveMode ? (\n <button\n type=\"button\"\n onClick={disconnect}\n aria-label=\"Disconnect from the desktop\"\n title=\"Disconnect\"\n className={cn(BUTTON_CLASS, 'px-1.5')}\n >\n <XIcon className=\"size-3.5\" aria-hidden />\n </button>\n ) : null}\n </div>\n {/* The remote screen's aspect is a runtime value no static utility expresses. */}\n <div\n className=\"relative w-full overflow-hidden rounded-lg border border-border bg-muted/40\"\n style={{ aspectRatio: aspect }}\n >\n {body}\n </div>\n </section>\n );\n};\n"],"names":["jsxs","jsx","useAthenaConfig","useAthenaQueryClient","useAthenaComputerStatus","useContext","SessionWorkbenchContext","useState","useRef","useMutation","createComputerLiveDesktopSession","liveDesktopViewerUrl","useEffect","LiveDesktopMode","_a","readLiveDesktopViewerMessage","finalLiveDesktopCloseNotice","MonitorOffIcon","Fragment","LoaderIcon","AlertCircleIcon","XIcon","PlayIcon","RefreshCwIcon","EyeIcon","cn","MousePointer2Icon"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ComputerLiveDesktop.cjs","sources":["../../src/workbench/ComputerLiveDesktop.tsx"],"sourcesContent":["\"use client\";\n\nimport { useMutation } from '@tanstack/react-query';\nimport {\n AlertCircleIcon,\n EyeIcon,\n LoaderIcon,\n MonitorOffIcon,\n MousePointer2Icon,\n PlayIcon,\n RefreshCwIcon,\n XIcon,\n} from 'lucide-react';\nimport { type FC, type ReactNode, useContext, useEffect, useRef, useState } from 'react';\nimport { useAthenaQueryClient } from '../lib/use-athena-rest-query';\nimport { cn } from '../lib/utils';\nimport { useAthenaConfig } from '../provider/AthenaContext';\nimport {\n createComputerLiveDesktopSession,\n finalLiveDesktopCloseNotice,\n LiveDesktopMode,\n type LiveDesktopSession,\n liveDesktopViewerUrl,\n readLiveDesktopViewerMessage,\n} from './live-desktop-api';\nimport { SessionWorkbenchContext } from './session-workbench-context';\nimport { useAthenaComputerStatus } from './use-session-workspace';\n\n/** How long a viewer may take to show video before the pane calls it failed. */\nexport const LIVE_DESKTOP_READY_TIMEOUT_MS = 30_000;\n\nconst RUNNING_STATES: ReadonlySet<string> = new Set(['started', 'running', 'ready']);\n\nconst BUTTON_CLASS =\n 'inline-flex shrink-0 items-center gap-1 rounded-md border border-border bg-background px-2 py-1 font-medium text-xs transition-colors hover:bg-muted outline-none focus-visible:ring-2 focus-visible:ring-ring/60 disabled:opacity-60';\n\n/** The viewer page the pane frames: one per ticket, its own messages move it on. */\ninterface MountedViewer {\n url: string;\n mode: LiveDesktopMode;\n display: { width: number; height: number } | null;\n /** `connected` once the page reports video (`ready`); never on a socket alone. */\n state: 'connecting' | 'connected';\n}\n\n/** Why the pane shows no viewer, when it has something to say. */\ntype Notice =\n | { kind: 'display_not_running'; text: string }\n | { kind: 'unsupported'; text: string }\n | { kind: 'ended'; text: string }\n | { kind: 'failed'; text: string };\n\ninterface SessionRequest {\n mode: LiveDesktopMode;\n start: boolean;\n}\n\nconst Placeholder: FC<{ icon?: ReactNode; children: ReactNode; action?: ReactNode }> = ({\n icon,\n children,\n action,\n}) => (\n <div className=\"flex h-full w-full flex-col items-center justify-center gap-2 p-4 text-center\">\n {icon}\n <p className=\"max-w-72 text-muted-foreground text-xs leading-snug\">{children}</p>\n {action}\n </div>\n);\n\nexport interface ComputerLiveDesktopProps {\n assetId: string;\n className?: string;\n /** How long a viewer may take to show video ({@link LIVE_DESKTOP_READY_TIMEOUT_MS}). */\n readyTimeoutMs?: number;\n}\n\n/**\n * The computer's screen, live — watch it, or take control and use it — framed\n * from agora's Selkies viewer (agora `web/api/computer/live_desktop_viewer.py`).\n *\n * Opens watching as soon as it mounts on a running computer, and ends when it\n * unmounts, its workbench collapses to the rail, or the computer stops (an open\n * view keeps the computer awake, up to agora's 30-minute cap). Needs EDIT on\n * the computer, in its own workspace, and an app the computer serves on Athena\n * (agora binds the viewer to this page's origin). A computer without a display\n * (one not made from the Browser template) says so instead.\n *\n * The frame runs Selkies' page from the guest, sandboxed as Olympus frames it:\n * scripts on agora's origin, no popups, forms or top navigation. Its messages\n * only move this pane between connecting, connected and ended. Each computer\n * is its own instance (keyed by `assetId`), so a switch never shows or drives\n * the previous computer's screen.\n */\nexport const ComputerLiveDesktop: FC<ComputerLiveDesktopProps> = (props) => (\n <ComputerLiveDesktopView key={props.assetId} {...props} />\n);\n\nconst ComputerLiveDesktopView: FC<ComputerLiveDesktopProps> = ({\n assetId,\n className,\n readyTimeoutMs = LIVE_DESKTOP_READY_TIMEOUT_MS,\n}) => {\n const config = useAthenaConfig();\n const { backendUrl, apiKey, getToken } = config;\n const queryClient = useAthenaQueryClient();\n const status = useAthenaComputerStatus({ assetId });\n const state = status.data?.state.toLowerCase() ?? null;\n const running =\n state !== null && RUNNING_STATES.has(state) && status.data?.explicitStop !== 'stopping';\n // Hidden in a collapsed workbench, the pane stops its stream.\n const visible = useContext(SessionWorkbenchContext)?.isVisible ?? true;\n\n const [viewer, setViewer] = useState<MountedViewer | null>(null);\n const [notice, setNotice] = useState<Notice | null>(null);\n // A mode switch that failed while a viewer stayed on screen.\n const [switchError, setSwitchError] = useState<string | null>(null);\n const frameRef = useRef<HTMLIFrameElement>(null);\n const viewerRef = useRef<MountedViewer | null>(null);\n viewerRef.current = viewer;\n\n const session = useMutation<LiveDesktopSession, Error, SessionRequest>(\n {\n mutationFn: ({ mode, start }) =>\n createComputerLiveDesktopSession({\n backendUrl,\n // `config.token` is read at request time: the provider serves the\n // latest token through a getter.\n auth: { apiKey, token: config.token, getToken },\n assetId,\n mode,\n start,\n embedOrigin: typeof window === 'undefined' ? null : window.location.origin,\n }),\n onSuccess: (answer) => {\n setSwitchError(null);\n if (answer.status !== 'ready') {\n setViewer(null);\n setNotice({ kind: answer.status, text: answer.detail });\n return;\n }\n let url: string;\n try {\n url = liveDesktopViewerUrl({ backendUrl, viewerPath: answer.viewerPath });\n } catch {\n setViewer(null);\n setNotice({\n kind: 'failed',\n text: 'The computer’s desktop answered with a page this app will not open.',\n });\n return;\n }\n // The new page replaces the one on screen only now that it exists.\n setViewer({ url, mode: answer.mode, display: answer.display, state: 'connecting' });\n setNotice(null);\n },\n onError: (error) => {\n // A failed switch leaves the working viewer where it is.\n if (viewerRef.current) {\n setSwitchError(error.message);\n return;\n }\n setNotice({ kind: 'failed', text: error.message });\n },\n },\n queryClient,\n );\n const { mutate, reset } = session;\n\n const opened = useRef(false);\n const disconnectedByPerson = useRef(false);\n\n // Hidden, or the computer stopped: drop the view. Its ticket is spent, so\n // showing again (or the computer starting again) asks for a fresh one.\n useEffect(() => {\n if (running && visible) return;\n reset();\n setViewer(null);\n setSwitchError(null);\n opened.current = false;\n }, [running, visible, reset]);\n // Watch once the computer is known to be running; never wake one.\n useEffect(() => {\n if (!running || !visible || opened.current || disconnectedByPerson.current) return;\n opened.current = true;\n mutate({ mode: LiveDesktopMode.WATCH, start: false });\n }, [running, visible, mutate]);\n\n // The viewer page's own messages move it on; a page agora ended takes the\n // frame down (an unseen stream would keep the computer awake).\n const viewerUrl = viewer?.url ?? null;\n const viewerState = viewer?.state ?? null;\n useEffect(() => {\n if (!viewerUrl) return undefined;\n const origin = new URL(viewerUrl).origin;\n const end = (text: string) => {\n setViewer((current) => (current?.url === viewerUrl ? null : current));\n setNotice({ kind: 'ended', text });\n };\n const onMessage = (event: MessageEvent) => {\n if (event.origin !== origin || event.source !== frameRef.current?.contentWindow) return;\n const message = readLiveDesktopViewerMessage(event.data);\n if (!message) return;\n if (message.status === 'ready') {\n setViewer((current) =>\n current?.url === viewerUrl ? { ...current, state: 'connected' } : current,\n );\n } else if (message.status === 'error') {\n end(message.detail);\n } else if (message.status === 'closed') {\n const final = finalLiveDesktopCloseNotice(message.code);\n if (final) end(final);\n }\n };\n window.addEventListener('message', onMessage);\n return () => window.removeEventListener('message', onMessage);\n }, [viewerUrl]);\n // No video within the timeout takes the frame down too.\n useEffect(() => {\n if (!viewerUrl || viewerState !== 'connecting') return undefined;\n const timer = setTimeout(() => {\n setViewer((current) => (current?.url === viewerUrl ? null : current));\n setNotice({\n kind: 'ended',\n text: 'The desktop did not start streaming here. Reconnect to try again.',\n });\n }, readyTimeoutMs);\n return () => clearTimeout(timer);\n }, [viewerUrl, viewerState, readyTimeoutMs]);\n\n const watch = (start = false) => {\n disconnectedByPerson.current = false;\n opened.current = true;\n mutate({ mode: LiveDesktopMode.WATCH, start });\n };\n const control = () => mutate({ mode: LiveDesktopMode.CONTROL, start: false });\n const disconnect = () => {\n disconnectedByPerson.current = true;\n reset();\n setViewer(null);\n setNotice(null);\n setSwitchError(null);\n };\n\n const aspect = viewer?.display ? `${viewer.display.width} / ${viewer.display.height}` : '16 / 10';\n let body: ReactNode;\n if (!running) {\n body = (\n <Placeholder icon={<MonitorOffIcon className=\"size-5 text-muted-foreground/70\" aria-hidden />}>\n {status.isPending\n ? 'Checking the computer…'\n : 'The computer is not running. Its desktop shows here once it is.'}\n </Placeholder>\n );\n } else if (viewer) {\n body = (\n <>\n <iframe\n ref={frameRef}\n key={viewer.url}\n src={viewer.url}\n title=\"Live desktop\"\n className=\"h-full w-full border-0 bg-black\"\n sandbox=\"allow-scripts allow-same-origin allow-pointer-lock\"\n allow=\"fullscreen; keyboard-map; autoplay; clipboard-write\"\n referrerPolicy=\"no-referrer\"\n data-live-desktop-frame=\"\"\n />\n {viewer.state === 'connecting' || session.isPending ? (\n <div className=\"pointer-events-none absolute inset-0 flex items-center justify-center bg-black/40\">\n <LoaderIcon className=\"size-5 animate-spin text-white\" aria-label=\"Connecting\" />\n </div>\n ) : null}\n {switchError ? (\n <div\n role=\"alert\"\n className=\"absolute inset-x-2 bottom-2 flex items-start gap-2 rounded-md border border-red-200 bg-red-50 px-2 py-1.5 text-red-900 text-xs\"\n >\n <AlertCircleIcon className=\"mt-0.5 size-3.5 shrink-0\" aria-hidden />\n <span className=\"min-w-0 flex-1\">{switchError}</span>\n <button\n type=\"button\"\n onClick={() => setSwitchError(null)}\n aria-label=\"Dismiss\"\n className=\"shrink-0 rounded p-0.5 hover:bg-red-100\"\n >\n <XIcon className=\"size-3\" aria-hidden />\n </button>\n </div>\n ) : null}\n </>\n );\n } else if (session.isPending) {\n body = (\n <Placeholder icon={<LoaderIcon className=\"size-5 animate-spin text-muted-foreground\" aria-hidden />}>\n Connecting to the desktop…\n </Placeholder>\n );\n } else if (notice?.kind === 'display_not_running') {\n body = (\n <Placeholder\n icon={<MonitorOffIcon className=\"size-5 text-muted-foreground/70\" aria-hidden />}\n action={\n <button type=\"button\" onClick={() => watch(true)} className={BUTTON_CLASS}>\n <PlayIcon className=\"size-3.5\" aria-hidden />\n Start the display\n </button>\n }\n >\n {notice.text}\n </Placeholder>\n );\n } else if (notice?.kind === 'unsupported') {\n body = (\n <Placeholder icon={<MonitorOffIcon className=\"size-5 text-muted-foreground/70\" aria-hidden />}>\n {notice.text}\n </Placeholder>\n );\n } else if (notice) {\n body = (\n <Placeholder\n icon={\n notice.kind === 'failed' ? (\n <AlertCircleIcon className=\"size-5 text-red-600\" aria-hidden />\n ) : (\n <MonitorOffIcon className=\"size-5 text-muted-foreground/70\" aria-hidden />\n )\n }\n action={\n <button type=\"button\" onClick={() => watch()} className={BUTTON_CLASS}>\n <RefreshCwIcon className=\"size-3.5\" aria-hidden />\n {notice.kind === 'failed' ? 'Try again' : 'Reconnect'}\n </button>\n }\n >\n {notice.text}\n </Placeholder>\n );\n } else {\n body = (\n <Placeholder\n icon={<EyeIcon className=\"size-5 text-muted-foreground/70\" aria-hidden />}\n action={\n <button type=\"button\" onClick={() => watch()} className={BUTTON_CLASS}>\n <EyeIcon className=\"size-3.5\" aria-hidden />\n Watch live\n </button>\n }\n >\n Watch the computer’s screen as the agent works.\n </Placeholder>\n );\n }\n\n const liveMode = running && viewer ? viewer.mode : null;\n return (\n <section aria-label=\"Live desktop\" className={cn('flex flex-col gap-1.5', className)}>\n <div className=\"flex items-center gap-2\">\n <h3 className=\"font-medium text-[11px] text-muted-foreground uppercase tracking-wide\">\n Live desktop\n </h3>\n {liveMode ? (\n <span\n data-mode={liveMode}\n className={cn(\n 'rounded-full px-1.5 py-px text-[10px]',\n liveMode === LiveDesktopMode.CONTROL\n ? 'bg-amber-100 text-amber-900'\n : 'bg-muted text-muted-foreground',\n )}\n >\n {liveMode === LiveDesktopMode.CONTROL ? 'In control' : 'Watching'}\n </span>\n ) : null}\n <div className=\"min-w-0 flex-1\" />\n {liveMode === LiveDesktopMode.WATCH ? (\n <button type=\"button\" onClick={control} disabled={session.isPending} className={BUTTON_CLASS}>\n <MousePointer2Icon className=\"size-3.5\" aria-hidden />\n Take control\n </button>\n ) : null}\n {liveMode === LiveDesktopMode.CONTROL ? (\n <button type=\"button\" onClick={() => watch()} disabled={session.isPending} className={BUTTON_CLASS}>\n <EyeIcon className=\"size-3.5\" aria-hidden />\n Stop controlling\n </button>\n ) : null}\n {liveMode ? (\n <button\n type=\"button\"\n onClick={disconnect}\n aria-label=\"Disconnect from the desktop\"\n title=\"Disconnect\"\n className={cn(BUTTON_CLASS, 'px-1.5')}\n >\n <XIcon className=\"size-3.5\" aria-hidden />\n </button>\n ) : null}\n </div>\n {/* The remote screen's aspect is a runtime value no static utility expresses. */}\n <div\n className=\"relative w-full overflow-hidden rounded-lg border border-border bg-muted/40\"\n style={{ aspectRatio: aspect }}\n >\n {body}\n </div>\n </section>\n );\n};\n"],"names":["jsxs","jsx","useAthenaConfig","useAthenaQueryClient","useAthenaComputerStatus","useContext","SessionWorkbenchContext","useState","useRef","useMutation","createComputerLiveDesktopSession","liveDesktopViewerUrl","useEffect","LiveDesktopMode","_a","readLiveDesktopViewerMessage","finalLiveDesktopCloseNotice","MonitorOffIcon","Fragment","LoaderIcon","AlertCircleIcon","XIcon","PlayIcon","RefreshCwIcon","EyeIcon","cn","MousePointer2Icon"],"mappings":";;;;;;;;;;;;AA6BO,MAAM,gCAAgC;AAE7C,MAAM,iBAAsC,oBAAI,IAAI,CAAC,WAAW,WAAW,OAAO,CAAC;AAEnF,MAAM,eACJ;AAuBF,MAAM,cAAiF,CAAC;AAAA,EACtF;AAAA,EACA;AAAA,EACA;AACF,MACEA,2BAAAA,KAAC,OAAA,EAAI,WAAU,iFACZ,UAAA;AAAA,EAAA;AAAA,EACDC,2BAAAA,IAAC,KAAA,EAAE,WAAU,uDAAuD,SAAA,CAAS;AAAA,EAC5E;AAAA,GACH;AA2BK,MAAM,sBAAoD,CAAC,UAChEA,+BAAC,2BAA6C,GAAG,MAAA,GAAnB,MAAM,OAAoB;AAG1D,MAAM,0BAAwD,CAAC;AAAA,EAC7D;AAAA,EACA;AAAA,EACA,iBAAiB;AACnB,MAAM;;AACJ,QAAM,SAASC,cAAAA,gBAAA;AACf,QAAM,EAAE,YAAY,QAAQ,SAAA,IAAa;AACzC,QAAM,cAAcC,mBAAAA,qBAAA;AACpB,QAAM,SAASC,oBAAAA,wBAAwB,EAAE,SAAS;AAClD,QAAM,UAAQ,YAAO,SAAP,mBAAa,MAAM,kBAAiB;AAClD,QAAM,UACJ,UAAU,QAAQ,eAAe,IAAI,KAAK,OAAK,YAAO,SAAP,mBAAa,kBAAiB;AAE/E,QAAM,YAAUC,gBAAAA,WAAWC,+CAAuB,MAAlCD,mBAAqC,cAAa;AAElE,QAAM,CAAC,QAAQ,SAAS,IAAIE,WAAAA,SAA+B,IAAI;AAC/D,QAAM,CAAC,QAAQ,SAAS,IAAIA,WAAAA,SAAwB,IAAI;AAExD,QAAM,CAAC,aAAa,cAAc,IAAIA,WAAAA,SAAwB,IAAI;AAClE,QAAM,WAAWC,WAAAA,OAA0B,IAAI;AAC/C,QAAM,YAAYA,WAAAA,OAA6B,IAAI;AACnD,YAAU,UAAU;AAEpB,QAAM,UAAUC,WAAAA;AAAAA,IACd;AAAA,MACE,YAAY,CAAC,EAAE,MAAM,MAAA,MACnBC,eAAAA,iCAAiC;AAAA,QAC/B;AAAA;AAAA;AAAA,QAGA,MAAM,EAAE,QAAQ,OAAO,OAAO,OAAO,SAAA;AAAA,QACrC;AAAA,QACA;AAAA,QACA;AAAA,QACA,aAAa,OAAO,WAAW,cAAc,OAAO,OAAO,SAAS;AAAA,MAAA,CACrE;AAAA,MACH,WAAW,CAAC,WAAW;AACrB,uBAAe,IAAI;AACnB,YAAI,OAAO,WAAW,SAAS;AAC7B,oBAAU,IAAI;AACd,oBAAU,EAAE,MAAM,OAAO,QAAQ,MAAM,OAAO,QAAQ;AACtD;AAAA,QACF;AACA,YAAI;AACJ,YAAI;AACF,gBAAMC,eAAAA,qBAAqB,EAAE,YAAY,YAAY,OAAO,YAAY;AAAA,QAC1E,QAAQ;AACN,oBAAU,IAAI;AACd,oBAAU;AAAA,YACR,MAAM;AAAA,YACN,MAAM;AAAA,UAAA,CACP;AACD;AAAA,QACF;AAEA,kBAAU,EAAE,KAAK,MAAM,OAAO,MAAM,SAAS,OAAO,SAAS,OAAO,aAAA,CAAc;AAClF,kBAAU,IAAI;AAAA,MAChB;AAAA,MACA,SAAS,CAAC,UAAU;AAElB,YAAI,UAAU,SAAS;AACrB,yBAAe,MAAM,OAAO;AAC5B;AAAA,QACF;AACA,kBAAU,EAAE,MAAM,UAAU,MAAM,MAAM,SAAS;AAAA,MACnD;AAAA,IAAA;AAAA,IAEF;AAAA,EAAA;AAEF,QAAM,EAAE,QAAQ,MAAA,IAAU;AAE1B,QAAM,SAASH,WAAAA,OAAO,KAAK;AAC3B,QAAM,uBAAuBA,WAAAA,OAAO,KAAK;AAIzCI,aAAAA,UAAU,MAAM;AACd,QAAI,WAAW,QAAS;AACxB,UAAA;AACA,cAAU,IAAI;AACd,mBAAe,IAAI;AACnB,WAAO,UAAU;AAAA,EACnB,GAAG,CAAC,SAAS,SAAS,KAAK,CAAC;AAE5BA,aAAAA,UAAU,MAAM;AACd,QAAI,CAAC,WAAW,CAAC,WAAW,OAAO,WAAW,qBAAqB,QAAS;AAC5E,WAAO,UAAU;AACjB,WAAO,EAAE,MAAMC,eAAAA,gBAAgB,OAAO,OAAO,OAAO;AAAA,EACtD,GAAG,CAAC,SAAS,SAAS,MAAM,CAAC;AAI7B,QAAM,aAAY,iCAAQ,QAAO;AACjC,QAAM,eAAc,iCAAQ,UAAS;AACrCD,aAAAA,UAAU,MAAM;AACd,QAAI,CAAC,UAAW,QAAO;AACvB,UAAM,SAAS,IAAI,IAAI,SAAS,EAAE;AAClC,UAAM,MAAM,CAAC,SAAiB;AAC5B,gBAAU,CAAC,aAAa,mCAAS,SAAQ,YAAY,OAAO,OAAQ;AACpE,gBAAU,EAAE,MAAM,SAAS,KAAA,CAAM;AAAA,IACnC;AACA,UAAM,YAAY,CAAC,UAAwB;;AACzC,UAAI,MAAM,WAAW,UAAU,MAAM,aAAWE,MAAA,SAAS,YAAT,gBAAAA,IAAkB,eAAe;AACjF,YAAM,UAAUC,eAAAA,6BAA6B,MAAM,IAAI;AACvD,UAAI,CAAC,QAAS;AACd,UAAI,QAAQ,WAAW,SAAS;AAC9B;AAAA,UAAU,CAAC,aACT,mCAAS,SAAQ,YAAY,EAAE,GAAG,SAAS,OAAO,gBAAgB;AAAA,QAAA;AAAA,MAEtE,WAAW,QAAQ,WAAW,SAAS;AACrC,YAAI,QAAQ,MAAM;AAAA,MACpB,WAAW,QAAQ,WAAW,UAAU;AACtC,cAAM,QAAQC,eAAAA,4BAA4B,QAAQ,IAAI;AACtD,YAAI,WAAW,KAAK;AAAA,MACtB;AAAA,IACF;AACA,WAAO,iBAAiB,WAAW,SAAS;AAC5C,WAAO,MAAM,OAAO,oBAAoB,WAAW,SAAS;AAAA,EAC9D,GAAG,CAAC,SAAS,CAAC;AAEdJ,aAAAA,UAAU,MAAM;AACd,QAAI,CAAC,aAAa,gBAAgB,aAAc,QAAO;AACvD,UAAM,QAAQ,WAAW,MAAM;AAC7B,gBAAU,CAAC,aAAa,mCAAS,SAAQ,YAAY,OAAO,OAAQ;AACpE,gBAAU;AAAA,QACR,MAAM;AAAA,QACN,MAAM;AAAA,MAAA,CACP;AAAA,IACH,GAAG,cAAc;AACjB,WAAO,MAAM,aAAa,KAAK;AAAA,EACjC,GAAG,CAAC,WAAW,aAAa,cAAc,CAAC;AAE3C,QAAM,QAAQ,CAAC,QAAQ,UAAU;AAC/B,yBAAqB,UAAU;AAC/B,WAAO,UAAU;AACjB,WAAO,EAAE,MAAMC,eAAAA,gBAAgB,OAAO,OAAO;AAAA,EAC/C;AACA,QAAM,UAAU,MAAM,OAAO,EAAE,MAAMA,eAAAA,gBAAgB,SAAS,OAAO,OAAO;AAC5E,QAAM,aAAa,MAAM;AACvB,yBAAqB,UAAU;AAC/B,UAAA;AACA,cAAU,IAAI;AACd,cAAU,IAAI;AACd,mBAAe,IAAI;AAAA,EACrB;AAEA,QAAM,UAAS,iCAAQ,WAAU,GAAG,OAAO,QAAQ,KAAK,MAAM,OAAO,QAAQ,MAAM,KAAK;AACxF,MAAI;AACJ,MAAI,CAAC,SAAS;AACZ,WACEZ,2BAAAA,IAAC,aAAA,EAAY,MAAMA,+BAACgB,YAAAA,gBAAA,EAAe,WAAU,mCAAkC,eAAW,KAAA,CAAC,GACxF,UAAA,OAAO,YACJ,2BACA,mEACN;AAAA,EAEJ,WAAW,QAAQ;AACjB,WACEjB,2BAAAA,KAAAkB,qBAAA,EACE,UAAA;AAAA,MAAAjB,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACC,KAAK;AAAA,UAEL,KAAK,OAAO;AAAA,UACZ,OAAM;AAAA,UACN,WAAU;AAAA,UACV,SAAQ;AAAA,UACR,OAAM;AAAA,UACN,gBAAe;AAAA,UACf,2BAAwB;AAAA,QAAA;AAAA,QAPnB,OAAO;AAAA,MAAA;AAAA,MASb,OAAO,UAAU,gBAAgB,QAAQ,2CACvC,OAAA,EAAI,WAAU,qFACb,UAAAA,+BAACkB,YAAAA,cAAW,WAAU,kCAAiC,cAAW,aAAA,CAAa,GACjF,IACE;AAAA,MACH,cACCnB,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,WAAU;AAAA,UAEV,UAAA;AAAA,YAAAC,2BAAAA,IAACmB,YAAAA,iBAAA,EAAgB,WAAU,4BAA2B,eAAW,MAAC;AAAA,YAClEnB,2BAAAA,IAAC,QAAA,EAAK,WAAU,kBAAkB,UAAA,aAAY;AAAA,YAC9CA,2BAAAA;AAAAA,cAAC;AAAA,cAAA;AAAA,gBACC,MAAK;AAAA,gBACL,SAAS,MAAM,eAAe,IAAI;AAAA,gBAClC,cAAW;AAAA,gBACX,WAAU;AAAA,gBAEV,UAAAA,2BAAAA,IAACoB,mBAAA,EAAM,WAAU,UAAS,eAAW,KAAA,CAAC;AAAA,cAAA;AAAA,YAAA;AAAA,UACxC;AAAA,QAAA;AAAA,MAAA,IAEA;AAAA,IAAA,GACN;AAAA,EAEJ,WAAW,QAAQ,WAAW;AAC5B,WACEpB,2BAAAA,IAAC,aAAA,EAAY,MAAMA,2BAAAA,IAACkB,YAAAA,YAAA,EAAW,WAAU,6CAA4C,eAAW,KAAA,CAAC,GAAI,UAAA,6BAAA,CAErG;AAAA,EAEJ,YAAW,iCAAQ,UAAS,uBAAuB;AACjD,WACElB,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAMA,2BAAAA,IAACgB,4BAAA,EAAe,WAAU,mCAAkC,eAAW,MAAC;AAAA,QAC9E,QACEjB,2BAAAA,KAAC,UAAA,EAAO,MAAK,UAAS,SAAS,MAAM,MAAM,IAAI,GAAG,WAAW,cAC3D,UAAA;AAAA,UAAAC,2BAAAA,IAACqB,YAAAA,UAAA,EAAS,WAAU,YAAW,eAAW,MAAC;AAAA,UAAE;AAAA,QAAA,GAE/C;AAAA,QAGD,UAAA,OAAO;AAAA,MAAA;AAAA,IAAA;AAAA,EAGd,YAAW,iCAAQ,UAAS,eAAe;AACzC,WACErB,2BAAAA,IAAC,aAAA,EAAY,MAAMA,2BAAAA,IAACgB,YAAAA,gBAAA,EAAe,WAAU,mCAAkC,eAAW,KAAA,CAAC,GACxF,UAAA,OAAO,MACV;AAAA,EAEJ,WAAW,QAAQ;AACjB,WACEhB,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,MACE,OAAO,SAAS,WACdA,2BAAAA,IAACmB,+BAAgB,WAAU,uBAAsB,eAAW,MAAC,IAE7DnB,2BAAAA,IAACgB,4BAAA,EAAe,WAAU,mCAAkC,eAAW,MAAC;AAAA,QAG5E,QACEjB,2BAAAA,KAAC,UAAA,EAAO,MAAK,UAAS,SAAS,MAAM,MAAA,GAAS,WAAW,cACvD,UAAA;AAAA,UAAAC,2BAAAA,IAACsB,YAAAA,eAAA,EAAc,WAAU,YAAW,eAAW,MAAC;AAAA,UAC/C,OAAO,SAAS,WAAW,cAAc;AAAA,QAAA,GAC5C;AAAA,QAGD,UAAA,OAAO;AAAA,MAAA;AAAA,IAAA;AAAA,EAGd,OAAO;AACL,WACEtB,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,MAAMA,2BAAAA,IAACuB,qBAAA,EAAQ,WAAU,mCAAkC,eAAW,MAAC;AAAA,QACvE,QACExB,2BAAAA,KAAC,UAAA,EAAO,MAAK,UAAS,SAAS,MAAM,MAAA,GAAS,WAAW,cACvD,UAAA;AAAA,UAAAC,2BAAAA,IAACuB,YAAAA,SAAA,EAAQ,WAAU,YAAW,eAAW,MAAC;AAAA,UAAE;AAAA,QAAA,GAE9C;AAAA,QAEH,UAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAIL;AAEA,QAAM,WAAW,WAAW,SAAS,OAAO,OAAO;AACnD,SACExB,gCAAC,aAAQ,cAAW,gBAAe,WAAWyB,OAAAA,GAAG,yBAAyB,SAAS,GACjF,UAAA;AAAA,IAAAzB,2BAAAA,KAAC,OAAA,EAAI,WAAU,2BACb,UAAA;AAAA,MAAAC,2BAAAA,IAAC,MAAA,EAAG,WAAU,yEAAwE,UAAA,gBAEtF;AAAA,MACC,WACCA,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACC,aAAW;AAAA,UACX,WAAWwB,OAAAA;AAAAA,YACT;AAAA,YACA,aAAaZ,eAAAA,gBAAgB,UACzB,gCACA;AAAA,UAAA;AAAA,UAGL,UAAA,aAAaA,+BAAgB,UAAU,eAAe;AAAA,QAAA;AAAA,MAAA,IAEvD;AAAA,MACJZ,2BAAAA,IAAC,OAAA,EAAI,WAAU,iBAAA,CAAiB;AAAA,MAC/B,aAAaY,eAAAA,gBAAgB,QAC5Bb,2BAAAA,KAAC,UAAA,EAAO,MAAK,UAAS,SAAS,SAAS,UAAU,QAAQ,WAAW,WAAW,cAC9E,UAAA;AAAA,QAAAC,2BAAAA,IAACyB,YAAAA,mBAAA,EAAkB,WAAU,YAAW,eAAW,MAAC;AAAA,QAAE;AAAA,MAAA,EAAA,CAExD,IACE;AAAA,MACH,aAAab,eAAAA,gBAAgB,UAC5Bb,2BAAAA,KAAC,YAAO,MAAK,UAAS,SAAS,MAAM,SAAS,UAAU,QAAQ,WAAW,WAAW,cACpF,UAAA;AAAA,QAAAC,2BAAAA,IAACuB,YAAAA,SAAA,EAAQ,WAAU,YAAW,eAAW,MAAC;AAAA,QAAE;AAAA,MAAA,EAAA,CAE9C,IACE;AAAA,MACH,WACCvB,2BAAAA;AAAAA,QAAC;AAAA,QAAA;AAAA,UACC,MAAK;AAAA,UACL,SAAS;AAAA,UACT,cAAW;AAAA,UACX,OAAM;AAAA,UACN,WAAWwB,OAAAA,GAAG,cAAc,QAAQ;AAAA,UAEpC,UAAAxB,2BAAAA,IAACoB,mBAAA,EAAM,WAAU,YAAW,eAAW,KAAA,CAAC;AAAA,QAAA;AAAA,MAAA,IAExC;AAAA,IAAA,GACN;AAAA,IAEApB,2BAAAA;AAAAA,MAAC;AAAA,MAAA;AAAA,QACC,WAAU;AAAA,QACV,OAAO,EAAE,aAAa,OAAA;AAAA,QAErB,UAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EACH,GACF;AAEJ;;;"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
|
-
const react
|
|
4
|
+
const react = require("@assistant-ui/react");
|
|
5
5
|
const reactQuery = require("@tanstack/react-query");
|
|
6
6
|
const lucideReact = require("lucide-react");
|
|
7
|
-
const
|
|
7
|
+
const require$$0 = require("react");
|
|
8
8
|
const assetPanelStore = require("../assets/asset-panel-store.cjs");
|
|
9
9
|
const AssetPanel = require("../assets/AssetPanel.cjs");
|
|
10
10
|
const useAthenaRestQuery = require("../lib/use-athena-rest-query.cjs");
|
|
@@ -37,35 +37,35 @@ const SessionWorkbenchInner = ({
|
|
|
37
37
|
className
|
|
38
38
|
}) => {
|
|
39
39
|
const layout = workbenchLayoutContext.useWorkbenchLayout();
|
|
40
|
-
const [ownCollapsed, setOwnCollapsed] =
|
|
40
|
+
const [ownCollapsed, setOwnCollapsed] = require$$0.useState(false);
|
|
41
41
|
const collapsed = layout ? layout.collapsed : ownCollapsed;
|
|
42
42
|
const setCollapsed = layout ? layout.setCollapsed : setOwnCollapsed;
|
|
43
43
|
const maximized = (layout == null ? void 0 : layout.maximized) ?? false;
|
|
44
44
|
const setMaximized = layout == null ? void 0 : layout.setMaximized;
|
|
45
45
|
const hostsAssetPanel = (layout == null ? void 0 : layout.hostsAssetPanel) ?? false;
|
|
46
|
-
const threadId =
|
|
46
|
+
const threadId = require$$0.useContext(threadIdContext.AthenaStatewireThreadIdContext);
|
|
47
47
|
const threadList = statewireThreadList.useAthenaStatewireThreadList();
|
|
48
|
-
const hasMessages = react
|
|
49
|
-
const sessionPersisted = react
|
|
48
|
+
const hasMessages = react.useAuiState((state) => state.thread.messages.length > 0);
|
|
49
|
+
const sessionPersisted = react.useAuiState(
|
|
50
50
|
(state) => {
|
|
51
51
|
var _a;
|
|
52
52
|
return statewireState.readDeepAgentStreamValues((_a = state.thread.extras) == null ? void 0 : _a.state).sessionPersisted;
|
|
53
53
|
}
|
|
54
54
|
);
|
|
55
|
-
const isRunning = react
|
|
55
|
+
const isRunning = react.useAuiState(
|
|
56
56
|
(state) => {
|
|
57
57
|
var _a;
|
|
58
58
|
return ((_a = state.thread.extras) == null ? void 0 : _a.status) === "running";
|
|
59
59
|
}
|
|
60
60
|
);
|
|
61
61
|
const isPersisted = threadList ? !threadList.isNewChat : sessionPersisted === true || hasMessages;
|
|
62
|
-
const paneContext =
|
|
62
|
+
const paneContext = require$$0.useMemo(
|
|
63
63
|
() => ({ threadId, isPersisted, isRunning, isVisible: !collapsed }),
|
|
64
64
|
[threadId, isPersisted, isRunning, collapsed]
|
|
65
65
|
);
|
|
66
66
|
const queryClient = reactQuery.useQueryClient();
|
|
67
|
-
const wasRunning =
|
|
68
|
-
|
|
67
|
+
const wasRunning = require$$0.useRef(isRunning);
|
|
68
|
+
require$$0.useEffect(() => {
|
|
69
69
|
if (wasRunning.current && !isRunning) {
|
|
70
70
|
void queryClient.invalidateQueries({ queryKey: useSessionWorkspace.SESSION_WORKSPACE_QUERY_KEY });
|
|
71
71
|
}
|
|
@@ -73,25 +73,25 @@ const SessionWorkbenchInner = ({
|
|
|
73
73
|
}, [isRunning, queryClient]);
|
|
74
74
|
const assetPanelOpen = assetPanelStore.useAssetPanelStore((state) => state.isOpen);
|
|
75
75
|
const closeAssetPanel = assetPanelStore.useAssetPanelStore((state) => state.closePanel);
|
|
76
|
-
const allPanes =
|
|
76
|
+
const allPanes = require$$0.useMemo(
|
|
77
77
|
() => hostsAssetPanel && assetPanelOpen ? [...panes, OPEN_ASSETS_PANE] : panes,
|
|
78
78
|
[assetPanelOpen, hostsAssetPanel, panes]
|
|
79
79
|
);
|
|
80
|
-
const paneById =
|
|
81
|
-
const paneIds =
|
|
82
|
-
const defaults =
|
|
80
|
+
const paneById = require$$0.useMemo(() => new Map(allPanes.map((pane) => [pane.id, pane])), [allPanes]);
|
|
81
|
+
const paneIds = require$$0.useMemo(() => new Set(paneById.keys()), [paneById]);
|
|
82
|
+
const defaults = require$$0.useMemo(() => {
|
|
83
83
|
const open = defaultOpenPaneIds.filter((id) => panes.some((pane) => pane.id === id));
|
|
84
84
|
return { open, active: open[0] ?? null };
|
|
85
85
|
}, [defaultOpenPaneIds, panes]);
|
|
86
|
-
const [tabsState, dispatchTabs] =
|
|
86
|
+
const [tabsState, dispatchTabs] = require$$0.useReducer(sessionWorkbenchModel.workbenchTabsReducer, {});
|
|
87
87
|
const threadKey = threadId ?? "";
|
|
88
88
|
const defaultCollapsed = (layout == null ? void 0 : layout.defaultCollapsed) ?? false;
|
|
89
|
-
const collapsedByThread =
|
|
89
|
+
const collapsedByThread = require$$0.useRef(/* @__PURE__ */ new Map());
|
|
90
90
|
const setThreadCollapsed = (next) => {
|
|
91
91
|
collapsedByThread.current.set(threadKey, next);
|
|
92
92
|
setCollapsed(next);
|
|
93
93
|
};
|
|
94
|
-
|
|
94
|
+
require$$0.useLayoutEffect(() => {
|
|
95
95
|
setCollapsed(collapsedByThread.current.get(threadKey) ?? defaultCollapsed);
|
|
96
96
|
}, [threadKey, defaultCollapsed, setCollapsed]);
|
|
97
97
|
let tabs = sessionWorkbenchModel.visibleThreadTabs(sessionWorkbenchModel.threadTabs(tabsState, threadKey, defaults), paneIds);
|
|
@@ -101,9 +101,9 @@ const SessionWorkbenchInner = ({
|
|
|
101
101
|
active: tabs.active ?? SESSION_WORKBENCH_ASSETS_PANE_ID
|
|
102
102
|
};
|
|
103
103
|
}
|
|
104
|
-
const latest =
|
|
104
|
+
const latest = require$$0.useRef({ threadKey, defaults, setCollapsed });
|
|
105
105
|
latest.current = { threadKey, defaults, setCollapsed };
|
|
106
|
-
|
|
106
|
+
require$$0.useEffect(() => {
|
|
107
107
|
if (!hostsAssetPanel) return void 0;
|
|
108
108
|
return assetPanelStore.useAssetPanelStore.subscribe((state, previous) => {
|
|
109
109
|
if (state.currentThreadId !== previous.currentThreadId) return;
|
|
@@ -124,7 +124,7 @@ const SessionWorkbenchInner = ({
|
|
|
124
124
|
if (paneId === SESSION_WORKBENCH_ASSETS_PANE_ID) closeAssetPanel();
|
|
125
125
|
dispatchTabs({ type: "close", threadKey, paneId, defaults });
|
|
126
126
|
};
|
|
127
|
-
const baseId =
|
|
127
|
+
const baseId = require$$0.useId();
|
|
128
128
|
const tabId = (paneId) => `${baseId}-tab-${paneId}`;
|
|
129
129
|
const panelId = `${baseId}-panel`;
|
|
130
130
|
const onTabKeyDown = (event, index) => {
|
|
@@ -319,8 +319,8 @@ const PaneMenuItems = ({ panes, openIds, onOpen }) => /* @__PURE__ */ jsxRuntime
|
|
|
319
319
|
) }, pane.id);
|
|
320
320
|
}) });
|
|
321
321
|
const AddPaneMenu = ({ panes, openIds, onOpen }) => {
|
|
322
|
-
const [open, setOpen] =
|
|
323
|
-
const [query, setQuery] =
|
|
322
|
+
const [open, setOpen] = require$$0.useState(false);
|
|
323
|
+
const [query, setQuery] = require$$0.useState("");
|
|
324
324
|
const shown = sessionWorkbenchModel.filterWorkbenchPanes(panes, query);
|
|
325
325
|
const choose = (paneId) => {
|
|
326
326
|
onOpen(paneId);
|