@athenaintel/react 0.42.2 → 0.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +225 -3
- package/dist/agent-runtime/src/answer-label.cjs +137 -0
- package/dist/agent-runtime/src/answer-label.cjs.map +1 -0
- package/dist/agent-runtime/src/answer-label.d.ts +104 -0
- package/dist/agent-runtime/src/answer-label.js +137 -0
- package/dist/agent-runtime/src/answer-label.js.map +1 -0
- package/dist/agent-runtime/src/answer-rows.cjs +180 -0
- package/dist/agent-runtime/src/answer-rows.cjs.map +1 -0
- package/dist/agent-runtime/src/answer-rows.d.ts +86 -0
- package/dist/agent-runtime/src/answer-rows.js +180 -0
- package/dist/agent-runtime/src/answer-rows.js.map +1 -0
- package/dist/agent-runtime/src/client-tool-bridge.cjs +15 -15
- package/dist/agent-runtime/src/client-tool-bridge.cjs.map +1 -1
- package/dist/agent-runtime/src/conversation-index.cjs +8 -8
- package/dist/agent-runtime/src/conversation-index.cjs.map +1 -1
- package/dist/agent-runtime/src/conversation-list-groups.d.ts +74 -0
- package/dist/agent-runtime/src/decision-checks.cjs +207 -0
- package/dist/agent-runtime/src/decision-checks.cjs.map +1 -0
- package/dist/agent-runtime/src/decision-checks.d.ts +142 -0
- package/dist/agent-runtime/src/decision-checks.js +207 -0
- package/dist/agent-runtime/src/decision-checks.js.map +1 -0
- package/dist/agent-runtime/src/desktop-handoff.d.ts +12 -0
- package/dist/agent-runtime/src/errors.cjs +18 -0
- package/dist/agent-runtime/src/errors.cjs.map +1 -1
- package/dist/agent-runtime/src/errors.d.ts +7 -0
- package/dist/agent-runtime/src/errors.js +18 -0
- package/dist/agent-runtime/src/errors.js.map +1 -1
- package/dist/agent-runtime/src/generated/runconfig-contract.cjs +12 -0
- package/dist/agent-runtime/src/generated/runconfig-contract.cjs.map +1 -1
- package/dist/agent-runtime/src/generated/runconfig-contract.d.ts +6 -6
- package/dist/agent-runtime/src/generated/runconfig-contract.js +12 -0
- package/dist/agent-runtime/src/generated/runconfig-contract.js.map +1 -1
- package/dist/agent-runtime/src/handoff-arrival.cjs +60 -0
- package/dist/agent-runtime/src/handoff-arrival.cjs.map +1 -0
- package/dist/agent-runtime/src/handoff-arrival.d.ts +46 -0
- package/dist/agent-runtime/src/handoff-arrival.js +60 -0
- package/dist/agent-runtime/src/handoff-arrival.js.map +1 -0
- package/dist/agent-runtime/src/index.d.ts +15 -8
- package/dist/agent-runtime/src/interrupts.cjs +43 -18
- package/dist/agent-runtime/src/interrupts.cjs.map +1 -1
- package/dist/agent-runtime/src/interrupts.d.ts +19 -2
- package/dist/agent-runtime/src/interrupts.js +28 -3
- package/dist/agent-runtime/src/interrupts.js.map +1 -1
- package/dist/agent-runtime/src/lane-history.cjs +8 -8
- package/dist/agent-runtime/src/lane-history.cjs.map +1 -1
- package/dist/agent-runtime/src/messages.cjs +43 -8
- package/dist/agent-runtime/src/messages.cjs.map +1 -1
- package/dist/agent-runtime/src/messages.d.ts +25 -3
- package/dist/agent-runtime/src/messages.js +43 -8
- package/dist/agent-runtime/src/messages.js.map +1 -1
- package/dist/agent-runtime/src/offline-status.cjs +36 -0
- package/dist/agent-runtime/src/offline-status.cjs.map +1 -0
- package/dist/agent-runtime/src/offline-status.d.ts +118 -3
- package/dist/agent-runtime/src/offline-status.js +36 -0
- package/dist/agent-runtime/src/offline-status.js.map +1 -0
- package/dist/agent-runtime/src/queue.cjs +0 -9
- package/dist/agent-runtime/src/queue.cjs.map +1 -1
- package/dist/agent-runtime/src/queue.js +0 -9
- package/dist/agent-runtime/src/queue.js.map +1 -1
- package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs +9 -9
- package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs.map +1 -1
- package/dist/agent-runtime/src/runtime-catalog.cjs +42 -0
- package/dist/agent-runtime/src/runtime-catalog.cjs.map +1 -0
- package/dist/agent-runtime/src/runtime-catalog.d.ts +35 -0
- package/dist/agent-runtime/src/runtime-catalog.js +42 -0
- package/dist/agent-runtime/src/runtime-catalog.js.map +1 -0
- package/dist/agent-runtime/src/runtime-messages.cjs.map +1 -1
- package/dist/agent-runtime/src/runtime-messages.d.ts +1 -1
- package/dist/agent-runtime/src/runtime-messages.js.map +1 -1
- package/dist/agent-runtime/src/runtime.d.ts +40 -0
- package/dist/agent-runtime/src/statewire-suspended.cjs +3 -3
- package/dist/agent-runtime/src/statewire-suspended.cjs.map +1 -1
- package/dist/agent-runtime/src/subagents.cjs +32 -2
- package/dist/agent-runtime/src/subagents.cjs.map +1 -1
- package/dist/agent-runtime/src/subagents.d.ts +9 -0
- package/dist/agent-runtime/src/subagents.js +30 -0
- package/dist/agent-runtime/src/subagents.js.map +1 -1
- package/dist/agent-runtime/src/thread-driver.cjs +67 -0
- package/dist/agent-runtime/src/thread-driver.cjs.map +1 -0
- package/dist/agent-runtime/src/thread-driver.d.ts +49 -0
- package/dist/agent-runtime/src/thread-driver.js +67 -0
- package/dist/agent-runtime/src/thread-driver.js.map +1 -0
- package/dist/agent-runtime/src/thread-handoff-flow-machine.d.ts +172 -0
- package/dist/agent-runtime/src/thread-handoff-protocol.d.ts +756 -0
- package/dist/agent-runtime/src/thread-handoff-qr.d.ts +11 -0
- package/dist/agent-runtime/src/thread-handoff.d.ts +3 -364
- package/dist/agent-runtime/src/thread-status.cjs +3 -3
- package/dist/agent-runtime/src/thread-status.cjs.map +1 -1
- package/dist/agent-runtime/src/tool-metadata.cjs +210 -33
- package/dist/agent-runtime/src/tool-metadata.cjs.map +1 -1
- package/dist/agent-runtime/src/tool-metadata.d.ts +12 -0
- package/dist/agent-runtime/src/tool-metadata.js +210 -33
- package/dist/agent-runtime/src/tool-metadata.js.map +1 -1
- package/dist/agent-runtime/src/tool-names.cjs +2 -0
- package/dist/agent-runtime/src/tool-names.cjs.map +1 -1
- package/dist/agent-runtime/src/tool-names.d.ts +2 -0
- package/dist/agent-runtime/src/tool-names.js +2 -0
- package/dist/agent-runtime/src/tool-names.js.map +1 -1
- package/dist/agent-runtime/src/types.d.ts +10 -2
- package/dist/agent-runtime/src/use-conversation-list.cjs +11 -11
- package/dist/agent-runtime/src/use-conversation-list.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.cjs +24 -19
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.d.ts +2 -1
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.js +6 -1
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.js.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-config.cjs +14 -14
- package/dist/agent-runtime/src/use-deep-agent-config.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-edit-submit.cjs +6 -6
- package/dist/agent-runtime/src/use-deep-agent-edit-submit.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-runtime.cjs +16 -16
- package/dist/agent-runtime/src/use-deep-agent-runtime.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-thread.cjs +45 -45
- package/dist/agent-runtime/src/use-deep-agent-thread.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-voice.cjs +572 -134
- package/dist/agent-runtime/src/use-deep-agent-voice.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-voice.d.ts +137 -10
- package/dist/agent-runtime/src/use-deep-agent-voice.js +514 -76
- package/dist/agent-runtime/src/use-deep-agent-voice.js.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-window-sync.cjs +26 -26
- package/dist/agent-runtime/src/use-deep-agent-window-sync.cjs.map +1 -1
- package/dist/agent-runtime/src/use-historical-edit-attachments.cjs +4 -4
- package/dist/agent-runtime/src/use-historical-edit-attachments.cjs.map +1 -1
- package/dist/agent-runtime/src/use-thread-handoff-flow.d.ts +28 -26
- package/dist/agent-runtime/src/voice-media.cjs +117 -0
- package/dist/agent-runtime/src/voice-media.cjs.map +1 -0
- package/dist/agent-runtime/src/voice-media.d.ts +49 -0
- package/dist/agent-runtime/src/voice-media.js +117 -0
- package/dist/agent-runtime/src/voice-media.js.map +1 -0
- package/dist/agent-runtime/src/voice-wire-types.d.ts +32 -0
- package/dist/assets/AssetPanel.cjs +11 -11
- package/dist/assets/AssetPanel.cjs.map +1 -1
- package/dist/assets/AthenaAssetEmbed.cjs +11 -9
- package/dist/assets/AthenaAssetEmbed.cjs.map +1 -1
- package/dist/assets/AthenaAssetEmbed.d.ts +7 -0
- package/dist/assets/AthenaAssetEmbed.js +4 -2
- package/dist/assets/AthenaAssetEmbed.js.map +1 -1
- package/dist/assets/AthenaLayout.cjs +16 -16
- package/dist/assets/AthenaLayout.cjs.map +1 -1
- package/dist/assets/use-asset-content.cjs +4 -4
- package/dist/assets/use-asset-content.cjs.map +1 -1
- package/dist/assets/use-asset-embed.cjs +14 -7
- package/dist/assets/use-asset-embed.cjs.map +1 -1
- package/dist/assets/use-asset-embed.d.ts +11 -1
- package/dist/assets/use-asset-embed.js +10 -3
- package/dist/assets/use-asset-embed.js.map +1 -1
- package/dist/auth/AthenaAuthContext.cjs +3 -3
- package/dist/auth/AthenaAuthContext.cjs.map +1 -1
- package/dist/auth/AthenaAuthProvider.cjs +8 -8
- package/dist/auth/AthenaAuthProvider.cjs.map +1 -1
- package/dist/auth/AthenaCredentialSourceContext.cjs +5 -5
- package/dist/auth/AthenaCredentialSourceContext.cjs.map +1 -1
- package/dist/auth/AthenaSSOProvider.cjs +14 -14
- package/dist/auth/AthenaSSOProvider.cjs.map +1 -1
- package/dist/auth/credential-source.cjs +26 -13
- package/dist/auth/credential-source.cjs.map +1 -1
- package/dist/auth/credential-source.d.ts +8 -0
- package/dist/auth/credential-source.js +26 -13
- package/dist/auth/credential-source.js.map +1 -1
- package/dist/catalog/agent-model-options.cjs +25 -17
- package/dist/catalog/agent-model-options.cjs.map +1 -1
- package/dist/catalog/agent-model-options.d.ts +38 -5
- package/dist/catalog/agent-model-options.js +25 -17
- package/dist/catalog/agent-model-options.js.map +1 -1
- package/dist/catalog/channel-refusal.cjs +36 -0
- package/dist/catalog/channel-refusal.cjs.map +1 -0
- package/dist/catalog/channel-refusal.d.ts +29 -0
- package/dist/catalog/channel-refusal.js +36 -0
- package/dist/catalog/channel-refusal.js.map +1 -0
- package/dist/catalog/chat-pickers.cjs +60 -24
- package/dist/catalog/chat-pickers.cjs.map +1 -1
- package/dist/catalog/chat-pickers.d.ts +12 -2
- package/dist/catalog/chat-pickers.js +56 -20
- package/dist/catalog/chat-pickers.js.map +1 -1
- package/dist/catalog/runtime-catalog.cjs +89 -23
- package/dist/catalog/runtime-catalog.cjs.map +1 -1
- package/dist/catalog/runtime-catalog.d.ts +8 -2
- package/dist/catalog/runtime-catalog.js +83 -17
- package/dist/catalog/runtime-catalog.js.map +1 -1
- package/dist/catalog/use-athena-chat-mode.cjs +12 -12
- package/dist/catalog/use-athena-chat-mode.cjs.map +1 -1
- package/dist/chat/AthenaChat.cjs +155 -67
- package/dist/chat/AthenaChat.cjs.map +1 -1
- package/dist/chat/AthenaChat.d.ts +42 -2
- package/dist/chat/AthenaChat.js +106 -18
- package/dist/chat/AthenaChat.js.map +1 -1
- package/dist/chat/AthenaChatErrorBoundary.cjs +3 -3
- package/dist/chat/AthenaChatErrorBoundary.cjs.map +1 -1
- package/dist/chat/DrivingOnChip.cjs +23 -0
- package/dist/chat/DrivingOnChip.cjs.map +1 -0
- package/dist/chat/DrivingOnChip.d.ts +17 -0
- package/dist/chat/DrivingOnChip.js +23 -0
- package/dist/chat/DrivingOnChip.js.map +1 -0
- package/dist/chat/StatewireApprovalCard.cjs +125 -31
- package/dist/chat/StatewireApprovalCard.cjs.map +1 -1
- package/dist/chat/StatewireApprovalCard.d.ts +73 -1
- package/dist/chat/StatewireApprovalCard.js +115 -21
- package/dist/chat/StatewireApprovalCard.js.map +1 -1
- package/dist/chat/StatewireClientToolBridge.cjs +2 -2
- package/dist/chat/StatewireClientToolBridge.cjs.map +1 -1
- package/dist/chat/StatewireQueuedMessages.cjs +25 -63
- package/dist/chat/StatewireQueuedMessages.cjs.map +1 -1
- package/dist/chat/StatewireQueuedMessages.d.ts +11 -13
- package/dist/chat/StatewireQueuedMessages.js +16 -54
- package/dist/chat/StatewireQueuedMessages.js.map +1 -1
- package/dist/chat/WaitingOnYouBanner.cjs +3 -3
- package/dist/chat/WaitingOnYouBanner.cjs.map +1 -1
- package/dist/chat/athena-chat-welcome.cjs +2 -2
- package/dist/chat/athena-chat-welcome.cjs.map +1 -1
- package/dist/chat/athena-citation-links.cjs +5 -5
- package/dist/chat/athena-citation-links.cjs.map +1 -1
- package/dist/chat/athena-composer-controls.cjs +26 -16
- package/dist/chat/athena-composer-controls.cjs.map +1 -1
- package/dist/chat/athena-composer-controls.d.ts +6 -0
- package/dist/chat/athena-composer-controls.js +26 -16
- package/dist/chat/athena-composer-controls.js.map +1 -1
- package/dist/chat/athena-turn-end-status.cjs +42 -0
- package/dist/chat/athena-turn-end-status.cjs.map +1 -0
- package/dist/chat/athena-turn-end-status.d.ts +24 -0
- package/dist/chat/athena-turn-end-status.js +42 -0
- package/dist/chat/athena-turn-end-status.js.map +1 -0
- package/dist/chat/browser-decision-check.cjs +131 -0
- package/dist/chat/browser-decision-check.cjs.map +1 -0
- package/dist/chat/browser-decision-check.d.ts +61 -0
- package/dist/chat/browser-decision-check.js +131 -0
- package/dist/chat/browser-decision-check.js.map +1 -0
- package/dist/chat/chat-outbox-rows.cjs +3 -3
- package/dist/chat/chat-outbox-rows.cjs.map +1 -1
- package/dist/chat/chat-voice-controls.cjs +93 -28
- package/dist/chat/chat-voice-controls.cjs.map +1 -1
- package/dist/chat/chat-voice-controls.d.ts +36 -2
- package/dist/chat/chat-voice-controls.js +89 -24
- package/dist/chat/chat-voice-controls.js.map +1 -1
- package/dist/chat/composer-keyboard-hint.cjs +5 -5
- package/dist/chat/composer-keyboard-hint.cjs.map +1 -1
- package/dist/chat/device-operation.cjs +29 -0
- package/dist/chat/device-operation.cjs.map +1 -0
- package/dist/chat/device-operation.d.ts +34 -0
- package/dist/chat/device-operation.js +29 -0
- package/dist/chat/device-operation.js.map +1 -0
- package/dist/chat/super-grouping/CollapsibleGroup.cjs +14 -14
- package/dist/chat/super-grouping/CollapsibleGroup.cjs.map +1 -1
- package/dist/chat/super-grouping/GroupedMessageParts.cjs +4 -4
- package/dist/chat/super-grouping/GroupedMessageParts.cjs.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingCard.cjs +60 -38
- package/dist/chat/super-grouping/SuperGroupingCard.cjs.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingCard.d.ts +24 -4
- package/dist/chat/super-grouping/SuperGroupingCard.js +37 -15
- package/dist/chat/super-grouping/SuperGroupingCard.js.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingTranscript.cjs +32 -32
- package/dist/chat/super-grouping/SuperGroupingTranscript.cjs.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingTranscript.js +3 -3
- package/dist/chat/super-grouping/SuperGroupingTranscript.js.map +1 -1
- package/dist/chat/super-grouping/ToolTimeline.cjs +97 -37
- package/dist/chat/super-grouping/ToolTimeline.cjs.map +1 -1
- package/dist/chat/super-grouping/ToolTimeline.d.ts +14 -2
- package/dist/chat/super-grouping/ToolTimeline.js +94 -34
- package/dist/chat/super-grouping/ToolTimeline.js.map +1 -1
- package/dist/chat/super-grouping/activity-timeline.cjs +47 -12
- package/dist/chat/super-grouping/activity-timeline.cjs.map +1 -1
- package/dist/chat/super-grouping/activity-timeline.d.ts +21 -0
- package/dist/chat/super-grouping/activity-timeline.js +47 -12
- package/dist/chat/super-grouping/activity-timeline.js.map +1 -1
- package/dist/chat/super-grouping/grouping-function.cjs +4 -0
- package/dist/chat/super-grouping/grouping-function.cjs.map +1 -1
- package/dist/chat/super-grouping/grouping-function.d.ts +7 -0
- package/dist/chat/super-grouping/grouping-function.js +5 -1
- package/dist/chat/super-grouping/grouping-function.js.map +1 -1
- package/dist/chat/super-grouping/index.cjs +6 -0
- package/dist/chat/super-grouping/index.cjs.map +1 -1
- package/dist/chat/super-grouping/index.d.ts +6 -2
- package/dist/chat/super-grouping/index.js +7 -1
- package/dist/chat/super-grouping/index.js.map +1 -1
- package/dist/chat/super-grouping/timeline-step.cjs +61 -2
- package/dist/chat/super-grouping/timeline-step.cjs.map +1 -1
- package/dist/chat/super-grouping/timeline-step.d.ts +13 -1
- package/dist/chat/super-grouping/timeline-step.js +61 -2
- package/dist/chat/super-grouping/timeline-step.js.map +1 -1
- package/dist/chat/super-grouping/tool-part-placement.cjs +17 -0
- package/dist/chat/super-grouping/tool-part-placement.cjs.map +1 -0
- package/dist/chat/super-grouping/tool-part-placement.d.ts +22 -0
- package/dist/chat/super-grouping/tool-part-placement.js +17 -0
- package/dist/chat/super-grouping/tool-part-placement.js.map +1 -0
- package/dist/chat/thread-scroll-to-bottom.cjs +2 -2
- package/dist/chat/thread-scroll-to-bottom.cjs.map +1 -1
- package/dist/chat/thread-scroll-to-bottom.d.ts +10 -7
- package/dist/chat/thread-scroll-to-bottom.js +2 -2
- package/dist/chat/thread-scroll-to-bottom.js.map +1 -1
- package/dist/chat/tooltip-icon-button.cjs +2 -2
- package/dist/chat/tooltip-icon-button.cjs.map +1 -1
- package/dist/chat/use-athena-voice-live.cjs +11 -0
- package/dist/chat/use-athena-voice-live.cjs.map +1 -0
- package/dist/chat/use-athena-voice-live.d.ts +11 -0
- package/dist/chat/use-athena-voice-live.js +11 -0
- package/dist/chat/use-athena-voice-live.js.map +1 -0
- package/dist/chat/use-statewire-approval-request.cjs +56 -24
- package/dist/chat/use-statewire-approval-request.cjs.map +1 -1
- package/dist/chat/use-statewire-approval-request.d.ts +33 -4
- package/dist/chat/use-statewire-approval-request.js +41 -9
- package/dist/chat/use-statewire-approval-request.js.map +1 -1
- package/dist/chat-ui/auth/sign-in-card.cjs +2 -2
- package/dist/chat-ui/auth/sign-in-card.cjs.map +1 -1
- package/dist/chat-ui/composer/tiptap-composer.cjs +138 -107
- package/dist/chat-ui/composer/tiptap-composer.cjs.map +1 -1
- package/dist/chat-ui/composer/tiptap-composer.d.ts +20 -4
- package/dist/chat-ui/composer/tiptap-composer.js +85 -54
- package/dist/chat-ui/composer/tiptap-composer.js.map +1 -1
- package/dist/chat-ui/header/conversation-history-panel.cjs +49 -23
- package/dist/chat-ui/header/conversation-history-panel.cjs.map +1 -1
- package/dist/chat-ui/header/conversation-history-panel.d.ts +12 -1
- package/dist/chat-ui/header/conversation-history-panel.js +38 -12
- package/dist/chat-ui/header/conversation-history-panel.js.map +1 -1
- package/dist/chat-ui/index.cjs +18 -0
- package/dist/chat-ui/index.cjs.map +1 -1
- package/dist/chat-ui/index.d.ts +7 -1
- package/dist/chat-ui/index.js +18 -0
- package/dist/chat-ui/index.js.map +1 -1
- package/dist/chat-ui/mentions/mention-chip.cjs +147 -38
- package/dist/chat-ui/mentions/mention-chip.cjs.map +1 -1
- package/dist/chat-ui/mentions/mention-chip.d.ts +17 -1
- package/dist/chat-ui/mentions/mention-chip.js +146 -37
- package/dist/chat-ui/mentions/mention-chip.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.cjs +10 -9
- package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.js +3 -2
- package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-popup.cjs +2 -2
- package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-popup.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/menu-list.cjs +29 -6
- package/dist/chat-ui/mentions/suggestions/components/menu-list.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/menu-list.d.ts +7 -1
- package/dist/chat-ui/mentions/suggestions/components/menu-list.js +25 -2
- package/dist/chat-ui/mentions/suggestions/components/menu-list.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/use-keyboard-navigation.cjs +2 -2
- package/dist/chat-ui/mentions/suggestions/components/use-keyboard-navigation.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/use-menu-navigation.cjs +2 -2
- package/dist/chat-ui/mentions/suggestions/components/use-menu-navigation.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/api-client.cjs +3 -3
- package/dist/chat-ui/mentions/suggestions/data/api-client.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/orchestrator.cjs +56 -2
- package/dist/chat-ui/mentions/suggestions/data/orchestrator.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/orchestrator.d.ts +12 -0
- package/dist/chat-ui/mentions/suggestions/data/orchestrator.js +56 -2
- package/dist/chat-ui/mentions/suggestions/data/orchestrator.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs +24 -3
- package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/sources/index.d.ts +7 -0
- package/dist/chat-ui/mentions/suggestions/data/sources/index.js +24 -3
- package/dist/chat-ui/mentions/suggestions/data/sources/index.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.cjs +35 -13
- package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.d.ts +15 -1
- package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.js +28 -6
- package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/use-menu-items.cjs +9 -6
- package/dist/chat-ui/mentions/suggestions/data/use-menu-items.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/use-menu-items.d.ts +3 -0
- package/dist/chat-ui/mentions/suggestions/data/use-menu-items.js +5 -2
- package/dist/chat-ui/mentions/suggestions/data/use-menu-items.js.map +1 -1
- package/dist/chat-ui/mentions/use-account-workspace-id.cjs +45 -10
- package/dist/chat-ui/mentions/use-account-workspace-id.cjs.map +1 -1
- package/dist/chat-ui/mentions/use-account-workspace-id.d.ts +24 -1
- package/dist/chat-ui/mentions/use-account-workspace-id.js +46 -11
- package/dist/chat-ui/mentions/use-account-workspace-id.js.map +1 -1
- package/dist/chat-ui/mentions/use-member-avatar.cjs +4 -4
- package/dist/chat-ui/mentions/use-member-avatar.cjs.map +1 -1
- package/dist/chat-ui/mentions/use-mention-asset.cjs +140 -0
- package/dist/chat-ui/mentions/use-mention-asset.cjs.map +1 -0
- package/dist/chat-ui/mentions/use-mention-asset.d.ts +16 -0
- package/dist/chat-ui/mentions/use-mention-asset.js +140 -0
- package/dist/chat-ui/mentions/use-mention-asset.js.map +1 -0
- package/dist/chat-ui/messages/answer-label.cjs +42 -0
- package/dist/chat-ui/messages/answer-label.cjs.map +1 -0
- package/dist/chat-ui/messages/answer-label.d.ts +33 -0
- package/dist/chat-ui/messages/answer-label.js +42 -0
- package/dist/chat-ui/messages/answer-label.js.map +1 -0
- package/dist/chat-ui/messages/arrival-animation.cjs +13 -0
- package/dist/chat-ui/messages/arrival-animation.cjs.map +1 -0
- package/dist/chat-ui/messages/arrival-animation.d.ts +14 -0
- package/dist/chat-ui/messages/arrival-animation.js +13 -0
- package/dist/chat-ui/messages/arrival-animation.js.map +1 -0
- package/dist/chat-ui/messages/continue-pill.cjs +5 -5
- package/dist/chat-ui/messages/continue-pill.cjs.map +1 -1
- package/dist/chat-ui/messages/handoff-arrival-divider.cjs +44 -0
- package/dist/chat-ui/messages/handoff-arrival-divider.cjs.map +1 -0
- package/dist/chat-ui/messages/handoff-arrival-divider.d.ts +17 -0
- package/dist/chat-ui/messages/handoff-arrival-divider.js +44 -0
- package/dist/chat-ui/messages/handoff-arrival-divider.js.map +1 -0
- package/dist/chat-ui/messages/message-actions-config.cjs +3 -3
- package/dist/chat-ui/messages/message-actions-config.cjs.map +1 -1
- package/dist/chat-ui/messages/message-components.cjs +8 -4
- package/dist/chat-ui/messages/message-components.cjs.map +1 -1
- package/dist/chat-ui/messages/message-components.js +5 -1
- package/dist/chat-ui/messages/message-components.js.map +1 -1
- package/dist/chat-ui/messages/message-images.cjs +66 -0
- package/dist/chat-ui/messages/message-images.cjs.map +1 -0
- package/dist/chat-ui/messages/message-images.d.ts +16 -0
- package/dist/chat-ui/messages/message-images.js +66 -0
- package/dist/chat-ui/messages/message-images.js.map +1 -0
- package/dist/chat-ui/messages/user-edit-composer.cjs +2 -2
- package/dist/chat-ui/messages/user-edit-composer.cjs.map +1 -1
- package/dist/chat-ui/messages/wake-marker.cjs +3 -3
- package/dist/chat-ui/messages/wake-marker.cjs.map +1 -1
- package/dist/chat-ui/rich-text/chat-link.cjs +7 -6
- package/dist/chat-ui/rich-text/chat-link.cjs.map +1 -1
- package/dist/chat-ui/rich-text/chat-link.d.ts +2 -3
- package/dist/chat-ui/rich-text/chat-link.js +6 -5
- package/dist/chat-ui/rich-text/chat-link.js.map +1 -1
- package/dist/chat-ui/rich-text/chat-message-body.cjs +8 -8
- package/dist/chat-ui/rich-text/chat-message-body.cjs.map +1 -1
- package/dist/chat-ui/rich-text/chat-node-views.cjs +7 -6
- package/dist/chat-ui/rich-text/chat-node-views.cjs.map +1 -1
- package/dist/chat-ui/rich-text/chat-node-views.js +1 -0
- package/dist/chat-ui/rich-text/chat-node-views.js.map +1 -1
- package/dist/chat-ui/rich-text/dom-output-spec.cjs +2 -2
- package/dist/chat-ui/rich-text/dom-output-spec.cjs.map +1 -1
- package/dist/chat-ui/statewire.cjs +3 -0
- package/dist/chat-ui/statewire.cjs.map +1 -1
- package/dist/chat-ui/statewire.d.ts +2 -1
- package/dist/chat-ui/statewire.js +3 -0
- package/dist/chat-ui/statewire.js.map +1 -1
- package/dist/chat-ui/thread/chat-thread-shell.cjs +43 -14
- package/dist/chat-ui/thread/chat-thread-shell.cjs.map +1 -1
- package/dist/chat-ui/thread/chat-thread-shell.d.ts +16 -2
- package/dist/chat-ui/thread/chat-thread-shell.js +35 -6
- package/dist/chat-ui/thread/chat-thread-shell.js.map +1 -1
- package/dist/chat-ui/thread/composer-send-or-stop.cjs +30 -20
- package/dist/chat-ui/thread/composer-send-or-stop.cjs.map +1 -1
- package/dist/chat-ui/thread/composer-send-or-stop.d.ts +8 -0
- package/dist/chat-ui/thread/composer-send-or-stop.js +29 -19
- package/dist/chat-ui/thread/composer-send-or-stop.js.map +1 -1
- package/dist/chat-ui/thread/statewire-history-edge.cjs +20 -21
- package/dist/chat-ui/thread/statewire-history-edge.cjs.map +1 -1
- package/dist/chat-ui/thread/statewire-history-edge.js +3 -4
- package/dist/chat-ui/thread/statewire-history-edge.js.map +1 -1
- package/dist/chat-ui/thread/thread-loading-overlay.cjs +5 -5
- package/dist/chat-ui/thread/thread-loading-overlay.cjs.map +1 -1
- package/dist/collab/client.cjs +40 -3
- package/dist/collab/client.cjs.map +1 -1
- package/dist/collab/client.d.ts +25 -0
- package/dist/collab/client.js +40 -3
- package/dist/collab/client.js.map +1 -1
- package/dist/collab/document-status.cjs +150 -0
- package/dist/collab/document-status.cjs.map +1 -0
- package/dist/collab/document-status.d.ts +68 -0
- package/dist/collab/document-status.js +150 -0
- package/dist/collab/document-status.js.map +1 -0
- package/dist/collab/index.cjs +7 -0
- package/dist/collab/index.cjs.map +1 -1
- package/dist/collab/index.d.ts +6 -1
- package/dist/collab/index.js +7 -0
- package/dist/collab/index.js.map +1 -1
- package/dist/collab/presence-react.cjs +11 -11
- package/dist/collab/presence-react.cjs.map +1 -1
- package/dist/collab/react.cjs +6 -6
- package/dist/collab/react.cjs.map +1 -1
- package/dist/composer/AttachmentContext.cjs +24 -11
- package/dist/composer/AttachmentContext.cjs.map +1 -1
- package/dist/composer/AttachmentContext.js +18 -5
- package/dist/composer/AttachmentContext.js.map +1 -1
- package/dist/composer/ComposerAttachmentPreview.cjs +78 -23
- package/dist/composer/ComposerAttachmentPreview.cjs.map +1 -1
- package/dist/composer/ComposerAttachmentPreview.d.ts +5 -3
- package/dist/composer/ComposerAttachmentPreview.js +79 -24
- package/dist/composer/ComposerAttachmentPreview.js.map +1 -1
- package/dist/composer/ComposerDropZone.cjs +7 -7
- package/dist/composer/ComposerDropZone.cjs.map +1 -1
- package/dist/composer/FileUploadButton.cjs +37 -22
- package/dist/composer/FileUploadButton.cjs.map +1 -1
- package/dist/composer/FileUploadButton.d.ts +6 -0
- package/dist/composer/FileUploadButton.js +34 -19
- package/dist/composer/FileUploadButton.js.map +1 -1
- package/dist/composer/QuoteContext.cjs +8 -8
- package/dist/composer/QuoteContext.cjs.map +1 -1
- package/dist/composer/composer-handoff.cjs +4 -4
- package/dist/composer/composer-handoff.cjs.map +1 -1
- package/dist/composer/useAppendToComposer.cjs +4 -4
- package/dist/composer/useAppendToComposer.cjs.map +1 -1
- package/dist/composer/useAttachFiles.cjs +23 -6
- package/dist/composer/useAttachFiles.cjs.map +1 -1
- package/dist/composer/useAttachFiles.d.ts +15 -7
- package/dist/composer/useAttachFiles.js +22 -5
- package/dist/composer/useAttachFiles.js.map +1 -1
- package/dist/composer/useComposerAttachment.cjs +4 -4
- package/dist/composer/useComposerAttachment.cjs.map +1 -1
- package/dist/composer/useFileUpload.cjs +21 -16
- package/dist/composer/useFileUpload.cjs.map +1 -1
- package/dist/composer/useFileUpload.d.ts +12 -0
- package/dist/composer/useFileUpload.js +12 -7
- package/dist/composer/useFileUpload.js.map +1 -1
- package/dist/composer/useReadComposerDraft.cjs +2 -2
- package/dist/composer/useReadComposerDraft.cjs.map +1 -1
- package/dist/composer/useSendMessage.cjs +4 -4
- package/dist/composer/useSendMessage.cjs.map +1 -1
- package/dist/diagnostics/useAthenaDiagnostics.cjs +4 -4
- package/dist/diagnostics/useAthenaDiagnostics.cjs.map +1 -1
- package/dist/dictation/audio-level-history.cjs +3 -3
- package/dist/dictation/audio-level-history.cjs.map +1 -1
- package/dist/dictation/dictation-controls.cjs +24 -20
- package/dist/dictation/dictation-controls.cjs.map +1 -1
- package/dist/dictation/dictation-controls.d.ts +6 -1
- package/dist/dictation/dictation-controls.js +24 -20
- package/dist/dictation/dictation-controls.js.map +1 -1
- package/dist/dictation/use-athena-dictation-engine.cjs +3 -3
- package/dist/dictation/use-athena-dictation-engine.cjs.map +1 -1
- package/dist/dictation/use-dictation.cjs +22 -22
- package/dist/dictation/use-dictation.cjs.map +1 -1
- package/dist/index.cjs +26 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +15 -3
- package/dist/index.js +26 -2
- package/dist/index.js.map +1 -1
- package/dist/keryx-http/src/receive-only-socket.cjs +40 -0
- package/dist/keryx-http/src/receive-only-socket.cjs.map +1 -0
- package/dist/keryx-http/src/receive-only-socket.d.ts +27 -0
- package/dist/keryx-http/src/receive-only-socket.js +40 -0
- package/dist/keryx-http/src/receive-only-socket.js.map +1 -0
- package/dist/keryx-http/src/update-attributions.cjs +111 -0
- package/dist/keryx-http/src/update-attributions.cjs.map +1 -0
- package/dist/keryx-http/src/update-attributions.d.ts +75 -0
- package/dist/keryx-http/src/update-attributions.js +111 -0
- package/dist/keryx-http/src/update-attributions.js.map +1 -0
- package/dist/lib/owner-document.cjs +6 -6
- package/dist/lib/owner-document.cjs.map +1 -1
- package/dist/lib/use-athena-rest-query.cjs +4 -4
- package/dist/lib/use-athena-rest-query.cjs.map +1 -1
- package/dist/lib/use-document-active.cjs +4 -4
- package/dist/lib/use-document-active.cjs.map +1 -1
- package/dist/lib/use-prefers-reduced-motion.cjs +2 -2
- package/dist/lib/use-prefers-reduced-motion.cjs.map +1 -1
- package/dist/offline/offline-history.cjs +7 -7
- package/dist/offline/offline-history.cjs.map +1 -1
- package/dist/provider/AthenaContext.cjs +3 -3
- package/dist/provider/AthenaContext.cjs.map +1 -1
- package/dist/provider/AthenaProvider.cjs +116 -79
- package/dist/provider/AthenaProvider.cjs.map +1 -1
- package/dist/provider/AthenaProvider.js +40 -3
- package/dist/provider/AthenaProvider.js.map +1 -1
- package/dist/provider/PostHogProvider.cjs +2 -2
- package/dist/provider/PostHogProvider.cjs.map +1 -1
- package/dist/provider/agent-selection-context.cjs +2 -2
- package/dist/provider/agent-selection-context.cjs.map +1 -1
- package/dist/provider/chat-mode-context.cjs +2 -2
- package/dist/provider/chat-mode-context.cjs.map +1 -1
- package/dist/provider/session-persistence-context.cjs +10 -0
- package/dist/provider/session-persistence-context.cjs.map +1 -0
- package/dist/provider/session-persistence-context.d.ts +15 -0
- package/dist/provider/session-persistence-context.js +10 -0
- package/dist/provider/session-persistence-context.js.map +1 -0
- package/dist/provider/statewire-history-context.cjs +4 -4
- package/dist/provider/statewire-history-context.cjs.map +1 -1
- package/dist/provider/statewire-lifecycle-context.cjs +3 -3
- package/dist/provider/statewire-lifecycle-context.cjs.map +1 -1
- package/dist/provider/statewire-window-context.cjs +3 -3
- package/dist/provider/statewire-window-context.cjs.map +1 -1
- package/dist/provider/theme-style-context.cjs +3 -3
- package/dist/provider/theme-style-context.cjs.map +1 -1
- package/dist/react/package.json.cjs +1 -1
- package/dist/react/package.json.js +1 -1
- package/dist/references/src/tool-option-schemas.d.ts +0 -34
- package/dist/runtime/StatewireThreadConfigLaneSync.cjs +10 -10
- package/dist/runtime/StatewireThreadConfigLaneSync.cjs.map +1 -1
- package/dist/runtime/auth-refusal-restart.cjs +7 -7
- package/dist/runtime/auth-refusal-restart.cjs.map +1 -1
- package/dist/runtime/auth.cjs +13 -13
- package/dist/runtime/auth.cjs.map +1 -1
- package/dist/runtime/statewire-lifecycle.cjs +1 -0
- package/dist/runtime/statewire-lifecycle.cjs.map +1 -1
- package/dist/runtime/statewire-lifecycle.d.ts +3 -1
- package/dist/runtime/statewire-lifecycle.js +2 -1
- package/dist/runtime/statewire-lifecycle.js.map +1 -1
- package/dist/runtime/statewire-server-lane-context.cjs +2 -2
- package/dist/runtime/statewire-server-lane-context.cjs.map +1 -1
- package/dist/runtime/statewire-session-lane.cjs +4 -4
- package/dist/runtime/statewire-session-lane.cjs.map +1 -1
- package/dist/runtime/useAthenaStatewireRuntime.cjs +10 -8
- package/dist/runtime/useAthenaStatewireRuntime.cjs.map +1 -1
- package/dist/runtime/useAthenaStatewireRuntime.d.ts +2 -0
- package/dist/runtime/useAthenaStatewireRuntime.js +2 -0
- package/dist/runtime/useAthenaStatewireRuntime.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/threads/Inbox.cjs +8 -8
- package/dist/threads/Inbox.cjs.map +1 -1
- package/dist/threads/SessionList.cjs +9 -9
- package/dist/threads/SessionList.cjs.map +1 -1
- package/dist/threads/SessionsPage.cjs +11 -11
- package/dist/threads/SessionsPage.cjs.map +1 -1
- package/dist/threads/index-triggered-refresh.cjs +10 -10
- package/dist/threads/index-triggered-refresh.cjs.map +1 -1
- package/dist/threads/mark-viewed-thread-read.cjs +12 -12
- package/dist/threads/mark-viewed-thread-read.cjs.map +1 -1
- package/dist/threads/offline-session-list.cjs +3 -3
- package/dist/threads/offline-session-list.cjs.map +1 -1
- package/dist/threads/session-list-tab-share.cjs +5 -5
- package/dist/threads/session-list-tab-share.cjs.map +1 -1
- package/dist/threads/statewire-thread-list.cjs +55 -51
- package/dist/threads/statewire-thread-list.cjs.map +1 -1
- package/dist/threads/statewire-thread-list.js +6 -2
- package/dist/threads/statewire-thread-list.js.map +1 -1
- package/dist/threads/thread-id-context.cjs +5 -5
- package/dist/threads/thread-id-context.cjs.map +1 -1
- package/dist/threads/use-athena-session-attention.cjs +2 -2
- package/dist/threads/use-athena-session-attention.cjs.map +1 -1
- package/dist/threads/use-athena-sessions.cjs +10 -10
- package/dist/threads/use-athena-sessions.cjs.map +1 -1
- package/dist/threads/use-athena-thread-model.cjs +3 -3
- package/dist/threads/use-athena-thread-model.cjs.map +1 -1
- package/dist/threads/use-rest-conversation-history.cjs +3 -3
- package/dist/threads/use-rest-conversation-history.cjs.map +1 -1
- package/dist/threads/use-statewire-conversation-history.cjs +8 -8
- package/dist/threads/use-statewire-conversation-history.cjs.map +1 -1
- package/dist/threads/use-thread-archive.cjs +9 -9
- package/dist/threads/use-thread-archive.cjs.map +1 -1
- package/dist/threads/use-thread-favorite.cjs +2 -2
- package/dist/threads/use-thread-favorite.cjs.map +1 -1
- package/dist/threads/use-thread-field-override.cjs +20 -20
- package/dist/threads/use-thread-field-override.cjs.map +1 -1
- package/dist/threads/use-thread-read-state.cjs +4 -4
- package/dist/threads/use-thread-read-state.cjs.map +1 -1
- package/dist/threads/use-thread-rename.cjs +2 -2
- package/dist/threads/use-thread-rename.cjs.map +1 -1
- package/dist/threads/useAthenaThreadManager.cjs +2 -2
- package/dist/threads/useAthenaThreadManager.cjs.map +1 -1
- package/dist/tools/NestedPtcMessages.cjs +6 -6
- package/dist/tools/NestedPtcMessages.cjs.map +1 -1
- package/dist/tools/append-document-tool-ui.cjs +7 -7
- package/dist/tools/append-document-tool-ui.cjs.map +1 -1
- package/dist/tools/file-tool-uis.cjs +2 -2
- package/dist/tools/file-tool-uis.cjs.map +1 -1
- package/dist/tools/misc-tool-uis.cjs +2 -2
- package/dist/tools/misc-tool-uis.cjs.map +1 -1
- package/dist/tools/primitives.cjs +6 -6
- package/dist/tools/primitives.cjs.map +1 -1
- package/dist/tools/read-asset-tool-ui.cjs +6 -6
- package/dist/tools/read-asset-tool-ui.cjs.map +1 -1
- package/dist/tools/subagent-task-tool-ui.cjs +21 -21
- package/dist/tools/subagent-task-tool-ui.cjs.map +1 -1
- package/dist/tools/test-recording-tool-uis.cjs +16 -16
- package/dist/tools/test-recording-tool-uis.cjs.map +1 -1
- package/dist/tools/todo-plan-store.cjs +4 -4
- package/dist/tools/todo-plan-store.cjs.map +1 -1
- package/dist/tools/tool-appearance.cjs +3 -3
- package/dist/tools/tool-appearance.cjs.map +1 -1
- package/dist/tools/tool-fallback.cjs +14 -14
- package/dist/tools/tool-fallback.cjs.map +1 -1
- package/dist/tools/tool-summary.cjs +0 -2
- package/dist/tools/tool-summary.cjs.map +1 -1
- package/dist/tools/tool-summary.js +0 -2
- package/dist/tools/tool-summary.js.map +1 -1
- package/dist/tools/tool-uis.cjs +74 -74
- package/dist/tools/tool-uis.cjs.map +1 -1
- package/dist/tools/use-elapsed-seconds.cjs +3 -3
- package/dist/tools/use-elapsed-seconds.cjs.map +1 -1
- package/dist/tools/write-todos-tool-ui.cjs +9 -9
- package/dist/tools/write-todos-tool-ui.cjs.map +1 -1
- package/dist/ui/image-viewer.cjs +382 -0
- package/dist/ui/image-viewer.cjs.map +1 -0
- package/dist/ui/image-viewer.d.ts +50 -0
- package/dist/ui/image-viewer.js +382 -0
- package/dist/ui/image-viewer.js.map +1 -0
- package/dist/voice/chat.cjs +6 -0
- package/dist/voice/chat.cjs.map +1 -1
- package/dist/voice/chat.d.ts +1 -1
- package/dist/voice/chat.js +8 -2
- package/dist/voice/livekit-join.cjs +52 -101
- package/dist/voice/livekit-join.cjs.map +1 -1
- package/dist/voice/livekit-join.d.ts +1 -6
- package/dist/voice/livekit-join.js +52 -101
- package/dist/voice/livekit-join.js.map +1 -1
- package/dist/voice/livekit.cjs.map +1 -1
- package/dist/voice/livekit.d.ts +11 -1
- package/dist/voice/livekit.js.map +1 -1
- package/dist/voice/use-athena-voice-session.cjs +34 -34
- package/dist/voice/use-athena-voice-session.cjs.map +1 -1
- package/dist/workbench/ComputerLiveDesktop.cjs +13 -13
- package/dist/workbench/ComputerLiveDesktop.cjs.map +1 -1
- package/dist/workbench/SessionWorkbench.cjs +22 -22
- package/dist/workbench/SessionWorkbench.cjs.map +1 -1
- package/dist/workbench/session-workbench-context.cjs +3 -3
- package/dist/workbench/session-workbench-context.cjs.map +1 -1
- package/dist/workbench/session-workbench-panes.cjs +8 -8
- package/dist/workbench/session-workbench-panes.cjs.map +1 -1
- package/dist/workbench/workbench-layout-context.cjs +3 -3
- package/dist/workbench/workbench-layout-context.cjs.map +1 -1
- package/package.json +2 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
4
|
const react = require("@assistant-ui/react");
|
|
5
|
-
const
|
|
5
|
+
const require$$0 = require("react");
|
|
6
6
|
const statewireHistoryContext = require("../../provider/statewire-history-context.cjs");
|
|
7
7
|
const statewireWindowContext = require("../../provider/statewire-window-context.cjs");
|
|
8
8
|
const threadIdContext = require("../../threads/thread-id-context.cjs");
|
|
@@ -24,11 +24,11 @@ function useMessagesNearViewport({
|
|
|
24
24
|
hasViewport,
|
|
25
25
|
messages
|
|
26
26
|
}) {
|
|
27
|
-
const [nearIds, setNearIds] =
|
|
27
|
+
const [nearIds, setNearIds] = require$$0.useState(NO_MESSAGE_IDS);
|
|
28
28
|
const observable = hasViewport && typeof IntersectionObserver !== "undefined";
|
|
29
|
-
const trackRef =
|
|
30
|
-
const renderedIdsRef =
|
|
31
|
-
|
|
29
|
+
const trackRef = require$$0.useRef(null);
|
|
30
|
+
const renderedIdsRef = require$$0.useRef(NO_MESSAGE_IDS);
|
|
31
|
+
require$$0.useEffect(() => {
|
|
32
32
|
if (!viewport || !observable) return void 0;
|
|
33
33
|
const near = /* @__PURE__ */ new Set();
|
|
34
34
|
const observed = /* @__PURE__ */ new Set();
|
|
@@ -51,12 +51,11 @@ function useMessagesNearViewport({
|
|
|
51
51
|
{ root: viewport, rootMargin: `${HISTORY_EDGE_NEAR_MARGIN_PX}px 0px` }
|
|
52
52
|
);
|
|
53
53
|
const track = () => {
|
|
54
|
-
let dropped = false;
|
|
55
54
|
for (const element of observed) {
|
|
56
55
|
if (element.isConnected) continue;
|
|
57
56
|
intersections.unobserve(element);
|
|
58
57
|
observed.delete(element);
|
|
59
|
-
|
|
58
|
+
near.delete(element);
|
|
60
59
|
}
|
|
61
60
|
const rendered = /* @__PURE__ */ new Set();
|
|
62
61
|
for (const element of viewport.querySelectorAll(MESSAGE_SELECTOR)) {
|
|
@@ -67,7 +66,7 @@ function useMessagesNearViewport({
|
|
|
67
66
|
intersections.observe(element);
|
|
68
67
|
}
|
|
69
68
|
renderedIdsRef.current = rendered;
|
|
70
|
-
|
|
69
|
+
publish();
|
|
71
70
|
};
|
|
72
71
|
trackRef.current = track;
|
|
73
72
|
track();
|
|
@@ -78,11 +77,11 @@ function useMessagesNearViewport({
|
|
|
78
77
|
setNearIds(NO_MESSAGE_IDS);
|
|
79
78
|
};
|
|
80
79
|
}, [viewport, observable]);
|
|
81
|
-
|
|
80
|
+
require$$0.useEffect(() => {
|
|
82
81
|
var _a;
|
|
83
82
|
(_a = trackRef.current) == null ? void 0 : _a.call(trackRef);
|
|
84
83
|
}, [messages]);
|
|
85
|
-
return
|
|
84
|
+
return require$$0.useMemo(() => {
|
|
86
85
|
if (!observable) return void 0;
|
|
87
86
|
return (messageId) => {
|
|
88
87
|
if (viewport === null) return false;
|
|
@@ -110,7 +109,7 @@ function prependedOlderHistory({
|
|
|
110
109
|
(source, index) => index > 0 && (source == null ? void 0 : source.id) === previousOldest
|
|
111
110
|
);
|
|
112
111
|
}
|
|
113
|
-
class KeepReadingPlace extends
|
|
112
|
+
class KeepReadingPlace extends require$$0.Component {
|
|
114
113
|
getSnapshotBeforeUpdate(previous) {
|
|
115
114
|
const { viewport, threadId, messages } = this.props;
|
|
116
115
|
if (viewport === null || viewport !== previous.viewport || threadId !== previous.threadId || messages === previous.messages || !prependedOlderHistory({ previous: previous.messages, next: messages })) {
|
|
@@ -143,7 +142,7 @@ const HistoryEdgeRow = ({
|
|
|
143
142
|
ref: rowRef,
|
|
144
143
|
"data-testid": "thread-history-edge",
|
|
145
144
|
className: cnfast.cn(
|
|
146
|
-
"flex w-full max-w-(--thread-max-width) items-center justify-center py-1 text-xs text-muted-foreground",
|
|
145
|
+
"mx-auto flex w-full max-w-(--thread-max-width) items-center justify-center py-1 text-xs text-muted-foreground",
|
|
147
146
|
className
|
|
148
147
|
),
|
|
149
148
|
children: loading ? /* @__PURE__ */ jsxRuntime.jsx("span", { "data-testid": "thread-history-edge-loading", children: "Loading earlier messages…" }) : canLoadOlder ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -167,11 +166,11 @@ const StatewireHistoryEdge = ({
|
|
|
167
166
|
const providerToolOutputs = statewireWindowContext.useStatewireToolOutputs();
|
|
168
167
|
const toolOutputs = toolOutputsProp ?? providerToolOutputs ?? void 0;
|
|
169
168
|
const messages = react.useAuiState((s) => s.thread.messages);
|
|
170
|
-
const threadId =
|
|
171
|
-
const [nearTop, setNearTop] =
|
|
172
|
-
const [nearTopEpoch, setNearTopEpoch] =
|
|
173
|
-
const nearTopRef =
|
|
174
|
-
const [rowEl, setRowEl] =
|
|
169
|
+
const threadId = require$$0.useContext(threadIdContext.AthenaStatewireThreadIdContext);
|
|
170
|
+
const [nearTop, setNearTop] = require$$0.useState(false);
|
|
171
|
+
const [nearTopEpoch, setNearTopEpoch] = require$$0.useState(0);
|
|
172
|
+
const nearTopRef = require$$0.useRef(false);
|
|
173
|
+
const [rowEl, setRowEl] = require$$0.useState(null);
|
|
175
174
|
const hasViewportStore = react.useThreadViewportStore({ optional: true }) !== null;
|
|
176
175
|
const registeredViewport = react.useThreadViewport({
|
|
177
176
|
optional: true,
|
|
@@ -183,7 +182,7 @@ const StatewireHistoryEdge = ({
|
|
|
183
182
|
hasViewport: hasViewportStore || viewport !== null,
|
|
184
183
|
messages
|
|
185
184
|
});
|
|
186
|
-
const historyStore =
|
|
185
|
+
const historyStore = require$$0.useContext(statewireHistoryContext.StatewireHistoryContext);
|
|
187
186
|
const { hasOlder, canLoadOlder, loading, loadOlder } = useDeepAgentWindowSync.useDeepAgentWindowSync({
|
|
188
187
|
messages,
|
|
189
188
|
toolOutputs,
|
|
@@ -197,18 +196,18 @@ const StatewireHistoryEdge = ({
|
|
|
197
196
|
console.warn(`[StatewireHistoryEdge] ${command} failed:`, error);
|
|
198
197
|
}
|
|
199
198
|
});
|
|
200
|
-
|
|
199
|
+
require$$0.useEffect(() => {
|
|
201
200
|
if (!historyStore || !threadId) return void 0;
|
|
202
201
|
historyStore.set({ threadId, hasOlder, canLoadOlder, loading, loadOlder });
|
|
203
202
|
return void 0;
|
|
204
203
|
}, [historyStore, threadId, hasOlder, canLoadOlder, loading, loadOlder]);
|
|
205
|
-
|
|
204
|
+
require$$0.useEffect(() => {
|
|
206
205
|
if (!historyStore || !threadId) return void 0;
|
|
207
206
|
return () => {
|
|
208
207
|
if (historyStore.get().threadId === threadId) historyStore.set(statewireHistoryContext.NO_STATEWIRE_HISTORY);
|
|
209
208
|
};
|
|
210
209
|
}, [historyStore, threadId]);
|
|
211
|
-
|
|
210
|
+
require$$0.useEffect(() => {
|
|
212
211
|
if (!rowEl || !hasOlder || typeof IntersectionObserver === "undefined") return;
|
|
213
212
|
const observer = new IntersectionObserver(
|
|
214
213
|
(entries) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"statewire-history-edge.cjs","sources":["../../../src/chat-ui/thread/statewire-history-edge.tsx"],"sourcesContent":["import {\n getExternalStoreMessages,\n type ThreadMessage,\n type ThreadViewportState,\n useAuiState,\n useThreadViewport,\n useThreadViewportStore,\n} from \"@assistant-ui/react\";\nimport {\n type DeepAgentHistoryLoadEvent,\n type DeepAgentToolOutputStore,\n isStatewireChannelTeardown,\n useDeepAgentWindowSync,\n} from \"@athenaintel/agent-runtime\";\nimport type { FC } from \"react\";\nimport { Component, useContext, useEffect, useMemo, useRef, useState } from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport {\n NO_STATEWIRE_HISTORY,\n StatewireHistoryContext,\n} from \"../../provider/statewire-history-context\";\nimport { useStatewireToolOutputs } from \"../../provider/statewire-window-context\";\nimport { AthenaStatewireThreadIdContext } from \"../../threads/thread-id-context\";\n\n/** The attribute `ChatThreadShell` stamps on the scroll viewport. */\nexport const THREAD_VIEWPORT_ATTR = \"data-aui-thread-viewport\";\n\n/**\n * How far above the viewport the edge row counts as near: the row sits above\n * the first loaded message, so reaching it means the user has scrolled past\n * everything loaded and the next page should already be on its way. Messages\n * this close to the viewport also count as on screen for cut tool outputs.\n */\nexport const HISTORY_EDGE_NEAR_MARGIN_PX = 1500;\n\n/**\n * Cut tool outputs a transcript reads at once. The reads share the session's\n * command lane with everything the person sends, so a long transcript must\n * not queue dozens of them ahead of a message or a Stop.\n */\nexport const HISTORY_EDGE_TOOL_OUTPUT_CONCURRENCY = 2;\n\n/** What assistant-ui's `MessagePrimitive.Root` stamps on every message. */\nconst MESSAGE_SELECTOR = \"[data-message-id]\";\n\nconst NO_MESSAGE_IDS: ReadonlySet<string> = new Set();\n\nfunction sameIds({ a, b }: { a: ReadonlySet<string>; b: ReadonlySet<string> }): boolean {\n if (a.size !== b.size) return false;\n for (const id of a) if (!b.has(id)) return false;\n return true;\n}\n\n/**\n * Which messages sit within {@link HISTORY_EDGE_NEAR_MARGIN_PX} of the\n * viewport, so cut tool outputs are read for what the person can reach. A\n * thread opens at its newest turn; reading every loaded step's output up\n * front sent dozens of reads, each re-rendering the transcript, for steps\n * nobody had scrolled to.\n *\n * `undefined` (every message counts) where nothing can be observed: no\n * viewport around the row, or no `IntersectionObserver`. A message rendered\n * without a `data-message-id` root (a host's own renderer) cannot be observed\n * either, so it counts as before.\n */\nfunction useMessagesNearViewport({\n viewport,\n hasViewport,\n messages,\n}: {\n viewport: HTMLElement | null;\n /** A viewport is (or will be) registered around the row. */\n hasViewport: boolean;\n /** The converted thread: every change may have mounted or remounted a message. */\n messages: readonly ThreadMessage[];\n}): ((messageId: string) => boolean) | undefined {\n const [nearIds, setNearIds] = useState<ReadonlySet<string>>(NO_MESSAGE_IDS);\n const observable = hasViewport && typeof IntersectionObserver !== \"undefined\";\n const trackRef = useRef<(() => void) | null>(null);\n // Every id a rendered element carries, as of the last scan.\n const renderedIdsRef = useRef<ReadonlySet<string>>(NO_MESSAGE_IDS);\n\n useEffect(() => {\n if (!viewport || !observable) return undefined;\n const near = new Set<Element>();\n const observed = new Set<Element>();\n const publish = () => {\n const ids = new Set<string>();\n for (const element of near) {\n const id = element.getAttribute(\"data-message-id\");\n if (id) ids.add(id);\n }\n setNearIds((previous) => (sameIds({ a: previous, b: ids }) ? previous : ids));\n };\n const intersections = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n if (entry.isIntersecting && entry.target.isConnected) near.add(entry.target);\n else near.delete(entry.target);\n }\n publish();\n },\n { root: viewport, rootMargin: `${HISTORY_EDGE_NEAR_MARGIN_PX}px 0px` },\n );\n // Messages remount when a page folds into them (a new id), so what is\n // observed follows the rendered elements, not the message list.\n const track = () => {\n let dropped = false;\n for (const element of observed) {\n if (element.isConnected) continue;\n intersections.unobserve(element);\n observed.delete(element);\n dropped = near.delete(element) || dropped;\n }\n const rendered = new Set<string>();\n for (const element of viewport.querySelectorAll(MESSAGE_SELECTOR)) {\n const id = element.getAttribute(\"data-message-id\");\n if (id) rendered.add(id);\n if (observed.has(element)) continue;\n observed.add(element);\n intersections.observe(element);\n }\n renderedIdsRef.current = rendered;\n if (dropped) publish();\n };\n trackRef.current = track;\n track();\n return () => {\n trackRef.current = null;\n renderedIdsRef.current = NO_MESSAGE_IDS;\n intersections.disconnect();\n setNearIds(NO_MESSAGE_IDS);\n };\n }, [viewport, observable]);\n\n // A changed message list is the trigger to re-scan: its messages render in\n // the same commit, so their elements are in the DOM by this effect (a\n // query, no layout read).\n useEffect(() => {\n trackRef.current?.();\n }, [messages]);\n\n return useMemo(() => {\n if (!observable) return undefined;\n return (messageId: string) => {\n // Not registered yet: nothing is on screen to read for.\n if (viewport === null) return false;\n return nearIds.has(messageId) || !renderedIdsRef.current.has(messageId);\n };\n }, [nearIds, observable, viewport]);\n}\n\n/** The wire message a converted message was built from first (its oldest source). */\nfunction oldestSourceId(message: ThreadMessage): string | undefined {\n const source = getExternalStoreMessages<{ id?: unknown }>(message)[0];\n return typeof source?.id === \"string\" ? source.id : undefined;\n}\n\n/**\n * Whether older history landed ahead of what was loaded: the old first\n * message now sits further down (a page ahead of it), or the first message's\n * old oldest wire message now follows earlier ones (a page that folded into\n * the first loaded turn). A first message replaced in place — a branch picked\n * on it, an edit — is neither, and a run streaming at the tail never touches\n * the first message.\n */\nfunction prependedOlderHistory({\n previous,\n next,\n}: {\n previous: readonly ThreadMessage[];\n next: readonly ThreadMessage[];\n}): boolean {\n const previousFirst = previous[0];\n const nextFirst = next[0];\n if (previousFirst === undefined || nextFirst === undefined || previousFirst === nextFirst) return false;\n if (previousFirst.id !== nextFirst.id && next.some((message, index) => index > 0 && message.id === previousFirst.id)) {\n return true;\n }\n const previousOldest = oldestSourceId(previousFirst);\n if (previousOldest === undefined || previousOldest === oldestSourceId(nextFirst)) return false;\n return getExternalStoreMessages<{ id?: unknown }>(nextFirst).some(\n (source, index) => index > 0 && source?.id === previousOldest,\n );\n}\n\ninterface KeepReadingPlaceProps {\n viewport: HTMLElement | null;\n threadId: string | null;\n /** The converted thread. */\n messages: readonly ThreadMessage[];\n}\n\n/**\n * Keeps the reader's place when older history lands. Everything a page adds\n * sits above what the person is reading, so their distance from the bottom of\n * the transcript is what must survive. A class for `getSnapshotBeforeUpdate`:\n * the distance is read right before React applies the commit that renders the\n * page — the one moment it is exact, even for a scroll the browser has not\n * reported yet — and restored after it, instantly (never through the\n * viewport's smooth scrolling). Other commits read no layout.\n *\n * The browser's scroll anchoring and assistant-ui's prepend anchor aim at the\n * same position, so whichever ran first leaves this nothing to do; on its own\n * it covers what they miss: a reader at the very top (browsers never anchor\n * at scroll offset 0) and a page that folds into the first loaded turn (that\n * message remounts under a new id, taking the browser's anchor node with it).\n */\nclass KeepReadingPlace extends Component<KeepReadingPlaceProps> {\n getSnapshotBeforeUpdate(previous: Readonly<KeepReadingPlaceProps>): number | null {\n const { viewport, threadId, messages } = this.props;\n if (\n viewport === null ||\n viewport !== previous.viewport ||\n threadId !== previous.threadId ||\n messages === previous.messages ||\n !prependedOlderHistory({ previous: previous.messages, next: messages })\n ) {\n return null;\n }\n return viewport.scrollHeight - viewport.scrollTop;\n }\n\n componentDidUpdate(\n _previous: Readonly<KeepReadingPlaceProps>,\n _state: unknown,\n fromBottom: number | null,\n ): void {\n const { viewport } = this.props;\n if (viewport === null || fromBottom === null) return;\n const top = viewport.scrollHeight - fromBottom;\n if (Math.abs(viewport.scrollTop - top) >= 1) viewport.scrollTo({ top, behavior: \"instant\" });\n }\n\n render(): null {\n return null;\n }\n}\n\nexport interface HistoryEdgeRowProps {\n /** Whether the server holds messages older than the loaded window. */\n hasOlder: boolean;\n /** Whether the next page can be asked for; `false` with `hasOlder` is the connection's loading depth spent. Defaults to `hasOlder`. */\n canLoadOlder?: boolean;\n /** A page of older history is in flight. */\n loading: boolean;\n onLoadOlder: () => void;\n className?: string;\n /** The row element, for the viewport observer. */\n rowRef?: (element: HTMLElement | null) => void;\n}\n\n/**\n * The top edge of the LOADED history: a manual way to load the next page of\n * older messages, and the in-flight state. Renders nothing when the whole\n * transcript is loaded (or the head interest has not resolved).\n */\nexport const HistoryEdgeRow: FC<HistoryEdgeRowProps> = ({\n hasOlder,\n canLoadOlder = hasOlder,\n loading,\n onLoadOlder,\n className,\n rowRef,\n}) => {\n if (!hasOlder) return null;\n return (\n <div\n ref={rowRef}\n data-testid=\"thread-history-edge\"\n className={cn(\n \"flex w-full max-w-(--thread-max-width) items-center justify-center py-1 text-xs text-muted-foreground\",\n className,\n )}\n >\n {loading ? (\n <span data-testid=\"thread-history-edge-loading\">Loading earlier messages…</span>\n ) : canLoadOlder ? (\n <button\n type=\"button\"\n data-testid=\"thread-history-edge-load\"\n onClick={onLoadOlder}\n className=\"rounded-lg px-2.5 py-1 text-xs font-medium text-muted-foreground transition-colors hover:bg-accent hover:text-foreground\"\n >\n Load earlier messages\n </button>\n ) : (\n <span data-testid=\"thread-history-edge-limit\">Earlier messages can't be loaded here</span>\n )}\n </div>\n );\n};\n\nexport interface StatewireHistoryEdgeProps {\n /**\n * The thread's tool-output store (the one its converter substitutes from).\n * Defaults to `AthenaProvider`'s; hosts mounting the runtime themselves pass\n * the store they gave `useDeepAgentRuntime({ toolOutputs })`.\n */\n toolOutputs?: DeepAgentToolOutputStore;\n className?: string;\n /** A page interest resolved (telemetry). */\n onHistoryLoad?: (event: DeepAgentHistoryLoadEvent) => void;\n}\n\n/**\n * The client half of the interest window for a DOM thread — mounted once per\n * thread, inside the scroll viewport above the messages (`ChatThreadShell`'s\n * `beforeMessages` slot):\n *\n * - renders the \"Load earlier messages\" edge row and loads the next page when\n * the row comes near the viewport (scrolling up) or on its button, keeping\n * the reading position when the page lands above the view;\n * - fetches cut tool outputs whole for the cards near the viewport, a few at\n * a time, so they re-render complete through the converter (`toolOutputs`).\n *\n * Inert until the head interest resolves: no row, no reads.\n */\nexport const StatewireHistoryEdge: FC<StatewireHistoryEdgeProps> = ({\n toolOutputs: toolOutputsProp,\n className,\n onHistoryLoad,\n}) => {\n const providerToolOutputs = useStatewireToolOutputs();\n const toolOutputs = toolOutputsProp ?? providerToolOutputs ?? undefined;\n const messages = useAuiState((s) => s.thread.messages);\n const threadId = useContext(AthenaStatewireThreadIdContext);\n const [nearTop, setNearTop] = useState(false);\n const [nearTopEpoch, setNearTopEpoch] = useState(0);\n const nearTopRef = useRef(false);\n const [rowEl, setRowEl] = useState<HTMLElement | null>(null);\n // The scroll viewport the thread registered (assistant-ui's viewport store),\n // known even while the row renders nothing; the row's ancestor otherwise.\n const hasViewportStore = useThreadViewportStore({ optional: true }) !== null;\n const registeredViewport = useThreadViewport({\n optional: true,\n selector: (state: ThreadViewportState) => state.element.viewport,\n });\n const viewport =\n registeredViewport ?? rowEl?.closest<HTMLElement>(`[${THREAD_VIEWPORT_ATTR}]`) ?? null;\n const isMessageMounted = useMessagesNearViewport({\n viewport,\n hasViewport: hasViewportStore || viewport !== null,\n messages,\n });\n const historyStore = useContext(StatewireHistoryContext);\n const { hasOlder, canLoadOlder, loading, loadOlder } = useDeepAgentWindowSync({\n messages,\n toolOutputs,\n nearTop,\n nearTopEpoch,\n isMessageMounted,\n maxConcurrentToolOutputs: HISTORY_EDGE_TOOL_OUTPUT_CONCURRENCY,\n onHistoryLoad,\n onError: (error, command) => {\n // Leaving the thread settles an in-flight read as lost: lifecycle, not a failure.\n if (error instanceof Error && isStatewireChannelTeardown(error)) return;\n console.warn(`[StatewireHistoryEdge] ${command} failed:`, error);\n },\n });\n\n // Other surfaces of the provider (the workbench's Shell pane) read where the\n // history stands; leaving the thread or unmounting withdraws the report.\n useEffect(() => {\n if (!historyStore || !threadId) return undefined;\n historyStore.set({ threadId, hasOlder, canLoadOlder, loading, loadOlder });\n return undefined;\n }, [historyStore, threadId, hasOlder, canLoadOlder, loading, loadOlder]);\n useEffect(() => {\n if (!historyStore || !threadId) return undefined;\n return () => {\n if (historyStore.get().threadId === threadId) historyStore.set(NO_STATEWIRE_HISTORY);\n };\n }, [historyStore, threadId]);\n\n // The row's own visibility is the near-top level: a level, not an edge, so\n // pages chain while the user stays at the top and stop once the prepended\n // content has pushed the row away again.\n useEffect(() => {\n if (!rowEl || !hasOlder || typeof IntersectionObserver === \"undefined\") return;\n const observer = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n const near = entry.isIntersecting;\n if (nearTopRef.current === near) continue;\n nearTopRef.current = near;\n setNearTop(near);\n if (near) setNearTopEpoch((epoch) => epoch + 1);\n }\n },\n {\n root: viewport,\n rootMargin: `${HISTORY_EDGE_NEAR_MARGIN_PX}px 0px`,\n },\n );\n observer.observe(rowEl);\n return () => {\n observer.disconnect();\n nearTopRef.current = false;\n setNearTop(false);\n };\n }, [rowEl, hasOlder, viewport]);\n\n return (\n <>\n <KeepReadingPlace viewport={viewport} threadId={threadId} messages={messages} />\n <HistoryEdgeRow\n rowRef={setRowEl}\n hasOlder={hasOlder}\n canLoadOlder={canLoadOlder}\n loading={loading}\n onLoadOlder={loadOlder}\n className={className}\n />\n </>\n );\n};\n"],"names":["useState","useRef","useEffect","useMemo","getExternalStoreMessages","Component","jsx","cn","useStatewireToolOutputs","useAuiState","useContext","AthenaStatewireThreadIdContext","useThreadViewportStore","useThreadViewport","StatewireHistoryContext","useDeepAgentWindowSync","isStatewireChannelTeardown","NO_STATEWIRE_HISTORY","jsxs","Fragment"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"statewire-history-edge.cjs","sources":["../../../src/chat-ui/thread/statewire-history-edge.tsx"],"sourcesContent":["import {\n getExternalStoreMessages,\n type ThreadMessage,\n type ThreadViewportState,\n useAuiState,\n useThreadViewport,\n useThreadViewportStore,\n} from \"@assistant-ui/react\";\nimport {\n type DeepAgentHistoryLoadEvent,\n type DeepAgentToolOutputStore,\n isStatewireChannelTeardown,\n useDeepAgentWindowSync,\n} from \"@athenaintel/agent-runtime\";\nimport type { FC } from \"react\";\nimport { Component, useContext, useEffect, useMemo, useRef, useState } from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport {\n NO_STATEWIRE_HISTORY,\n StatewireHistoryContext,\n} from \"../../provider/statewire-history-context\";\nimport { useStatewireToolOutputs } from \"../../provider/statewire-window-context\";\nimport { AthenaStatewireThreadIdContext } from \"../../threads/thread-id-context\";\n\n/** The attribute `ChatThreadShell` stamps on the scroll viewport. */\nexport const THREAD_VIEWPORT_ATTR = \"data-aui-thread-viewport\";\n\n/**\n * How far above the viewport the edge row counts as near: the row sits above\n * the first loaded message, so reaching it means the user has scrolled past\n * everything loaded and the next page should already be on its way. Messages\n * this close to the viewport also count as on screen for cut tool outputs.\n */\nexport const HISTORY_EDGE_NEAR_MARGIN_PX = 1500;\n\n/**\n * Cut tool outputs a transcript reads at once. The reads share the session's\n * command lane with everything the person sends, so a long transcript must\n * not queue dozens of them ahead of a message or a Stop.\n */\nexport const HISTORY_EDGE_TOOL_OUTPUT_CONCURRENCY = 2;\n\n/** What assistant-ui's `MessagePrimitive.Root` stamps on every message. */\nconst MESSAGE_SELECTOR = \"[data-message-id]\";\n\nconst NO_MESSAGE_IDS: ReadonlySet<string> = new Set();\n\nfunction sameIds({ a, b }: { a: ReadonlySet<string>; b: ReadonlySet<string> }): boolean {\n if (a.size !== b.size) return false;\n for (const id of a) if (!b.has(id)) return false;\n return true;\n}\n\n/**\n * Which messages sit within {@link HISTORY_EDGE_NEAR_MARGIN_PX} of the\n * viewport, so cut tool outputs are read for what the person can reach. A\n * thread opens at its newest turn; reading every loaded step's output up\n * front sent dozens of reads, each re-rendering the transcript, for steps\n * nobody had scrolled to.\n *\n * `undefined` (every message counts) where nothing can be observed: no\n * viewport around the row, or no `IntersectionObserver`. A message rendered\n * without a `data-message-id` root (a host's own renderer) cannot be observed\n * either, so it counts as before.\n */\nfunction useMessagesNearViewport({\n viewport,\n hasViewport,\n messages,\n}: {\n viewport: HTMLElement | null;\n /** A viewport is (or will be) registered around the row. */\n hasViewport: boolean;\n /** The converted thread: every change may have mounted or remounted a message. */\n messages: readonly ThreadMessage[];\n}): ((messageId: string) => boolean) | undefined {\n const [nearIds, setNearIds] = useState<ReadonlySet<string>>(NO_MESSAGE_IDS);\n const observable = hasViewport && typeof IntersectionObserver !== \"undefined\";\n const trackRef = useRef<(() => void) | null>(null);\n // Every id a rendered element carries, as of the last scan.\n const renderedIdsRef = useRef<ReadonlySet<string>>(NO_MESSAGE_IDS);\n\n useEffect(() => {\n if (!viewport || !observable) return undefined;\n const near = new Set<Element>();\n const observed = new Set<Element>();\n const publish = () => {\n const ids = new Set<string>();\n for (const element of near) {\n const id = element.getAttribute(\"data-message-id\");\n if (id) ids.add(id);\n }\n setNearIds((previous) => (sameIds({ a: previous, b: ids }) ? previous : ids));\n };\n const intersections = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n if (entry.isIntersecting && entry.target.isConnected) near.add(entry.target);\n else near.delete(entry.target);\n }\n publish();\n },\n { root: viewport, rootMargin: `${HISTORY_EDGE_NEAR_MARGIN_PX}px 0px` },\n );\n // A page that folds into a turn gives it a new id: a host keyed by id\n // remounts the turn's element, a host keyed by row (`ChatThreadShell`)\n // keeps it and the element's id changes. So what is observed follows the\n // rendered elements, not the message list, and the near ids are read off\n // those elements again on every scan.\n const track = () => {\n for (const element of observed) {\n if (element.isConnected) continue;\n intersections.unobserve(element);\n observed.delete(element);\n near.delete(element);\n }\n const rendered = new Set<string>();\n for (const element of viewport.querySelectorAll(MESSAGE_SELECTOR)) {\n const id = element.getAttribute(\"data-message-id\");\n if (id) rendered.add(id);\n if (observed.has(element)) continue;\n observed.add(element);\n intersections.observe(element);\n }\n renderedIdsRef.current = rendered;\n publish();\n };\n trackRef.current = track;\n track();\n return () => {\n trackRef.current = null;\n renderedIdsRef.current = NO_MESSAGE_IDS;\n intersections.disconnect();\n setNearIds(NO_MESSAGE_IDS);\n };\n }, [viewport, observable]);\n\n // A changed message list is the trigger to re-scan: its messages render in\n // the same commit, so their elements are in the DOM by this effect (a\n // query, no layout read).\n useEffect(() => {\n trackRef.current?.();\n }, [messages]);\n\n return useMemo(() => {\n if (!observable) return undefined;\n return (messageId: string) => {\n // Not registered yet: nothing is on screen to read for.\n if (viewport === null) return false;\n return nearIds.has(messageId) || !renderedIdsRef.current.has(messageId);\n };\n }, [nearIds, observable, viewport]);\n}\n\n/** The wire message a converted message was built from first (its oldest source). */\nfunction oldestSourceId(message: ThreadMessage): string | undefined {\n const source = getExternalStoreMessages<{ id?: unknown }>(message)[0];\n return typeof source?.id === \"string\" ? source.id : undefined;\n}\n\n/**\n * Whether older history landed ahead of what was loaded: the old first\n * message now sits further down (a page ahead of it), or the first message's\n * old oldest wire message now follows earlier ones (a page that folded into\n * the first loaded turn). A first message replaced in place — a branch picked\n * on it, an edit — is neither, and a run streaming at the tail never touches\n * the first message.\n */\nfunction prependedOlderHistory({\n previous,\n next,\n}: {\n previous: readonly ThreadMessage[];\n next: readonly ThreadMessage[];\n}): boolean {\n const previousFirst = previous[0];\n const nextFirst = next[0];\n if (previousFirst === undefined || nextFirst === undefined || previousFirst === nextFirst) return false;\n if (previousFirst.id !== nextFirst.id && next.some((message, index) => index > 0 && message.id === previousFirst.id)) {\n return true;\n }\n const previousOldest = oldestSourceId(previousFirst);\n if (previousOldest === undefined || previousOldest === oldestSourceId(nextFirst)) return false;\n return getExternalStoreMessages<{ id?: unknown }>(nextFirst).some(\n (source, index) => index > 0 && source?.id === previousOldest,\n );\n}\n\ninterface KeepReadingPlaceProps {\n viewport: HTMLElement | null;\n threadId: string | null;\n /** The converted thread. */\n messages: readonly ThreadMessage[];\n}\n\n/**\n * Keeps the reader's place when older history lands. Everything a page adds\n * sits above what the person is reading, so their distance from the bottom of\n * the transcript is what must survive. A class for `getSnapshotBeforeUpdate`:\n * the distance is read right before React applies the commit that renders the\n * page — the one moment it is exact, even for a scroll the browser has not\n * reported yet — and restored after it, instantly (never through the\n * viewport's smooth scrolling). Other commits read no layout.\n *\n * The browser's scroll anchoring and assistant-ui's prepend anchor aim at the\n * same position, so whichever ran first leaves this nothing to do; on its own\n * it covers what they miss: a reader at the very top (browsers never anchor\n * at scroll offset 0) and a page that folds into the first loaded turn of a\n * host that keys rows by message id (that message remounts under a new id,\n * taking the browser's anchor node with it; `ChatThreadShell` keeps the row).\n */\nclass KeepReadingPlace extends Component<KeepReadingPlaceProps> {\n getSnapshotBeforeUpdate(previous: Readonly<KeepReadingPlaceProps>): number | null {\n const { viewport, threadId, messages } = this.props;\n if (\n viewport === null ||\n viewport !== previous.viewport ||\n threadId !== previous.threadId ||\n messages === previous.messages ||\n !prependedOlderHistory({ previous: previous.messages, next: messages })\n ) {\n return null;\n }\n return viewport.scrollHeight - viewport.scrollTop;\n }\n\n componentDidUpdate(\n _previous: Readonly<KeepReadingPlaceProps>,\n _state: unknown,\n fromBottom: number | null,\n ): void {\n const { viewport } = this.props;\n if (viewport === null || fromBottom === null) return;\n const top = viewport.scrollHeight - fromBottom;\n if (Math.abs(viewport.scrollTop - top) >= 1) viewport.scrollTo({ top, behavior: \"instant\" });\n }\n\n render(): null {\n return null;\n }\n}\n\nexport interface HistoryEdgeRowProps {\n /** Whether the server holds messages older than the loaded window. */\n hasOlder: boolean;\n /** Whether the next page can be asked for; `false` with `hasOlder` is the connection's loading depth spent. Defaults to `hasOlder`. */\n canLoadOlder?: boolean;\n /** A page of older history is in flight. */\n loading: boolean;\n onLoadOlder: () => void;\n className?: string;\n /** The row element, for the viewport observer. */\n rowRef?: (element: HTMLElement | null) => void;\n}\n\n/**\n * The top edge of the LOADED history: a manual way to load the next page of\n * older messages, and the in-flight state. Renders nothing when the whole\n * transcript is loaded (or the head interest has not resolved).\n */\nexport const HistoryEdgeRow: FC<HistoryEdgeRowProps> = ({\n hasOlder,\n canLoadOlder = hasOlder,\n loading,\n onLoadOlder,\n className,\n rowRef,\n}) => {\n if (!hasOlder) return null;\n return (\n <div\n ref={rowRef}\n data-testid=\"thread-history-edge\"\n className={cn(\n \"mx-auto flex w-full max-w-(--thread-max-width) items-center justify-center py-1 text-xs text-muted-foreground\",\n className,\n )}\n >\n {loading ? (\n <span data-testid=\"thread-history-edge-loading\">Loading earlier messages…</span>\n ) : canLoadOlder ? (\n <button\n type=\"button\"\n data-testid=\"thread-history-edge-load\"\n onClick={onLoadOlder}\n className=\"rounded-lg px-2.5 py-1 text-xs font-medium text-muted-foreground transition-colors hover:bg-accent hover:text-foreground\"\n >\n Load earlier messages\n </button>\n ) : (\n <span data-testid=\"thread-history-edge-limit\">Earlier messages can't be loaded here</span>\n )}\n </div>\n );\n};\n\nexport interface StatewireHistoryEdgeProps {\n /**\n * The thread's tool-output store (the one its converter substitutes from).\n * Defaults to `AthenaProvider`'s; hosts mounting the runtime themselves pass\n * the store they gave `useDeepAgentRuntime({ toolOutputs })`.\n */\n toolOutputs?: DeepAgentToolOutputStore;\n className?: string;\n /** A page interest resolved (telemetry). */\n onHistoryLoad?: (event: DeepAgentHistoryLoadEvent) => void;\n}\n\n/**\n * The client half of the interest window for a DOM thread — mounted once per\n * thread, inside the scroll viewport above the messages (`ChatThreadShell`'s\n * `beforeMessages` slot):\n *\n * - renders the \"Load earlier messages\" edge row and loads the next page when\n * the row comes near the viewport (scrolling up) or on its button, keeping\n * the reading position when the page lands above the view;\n * - fetches cut tool outputs whole for the cards near the viewport, a few at\n * a time, so they re-render complete through the converter (`toolOutputs`).\n *\n * Inert until the head interest resolves: no row, no reads.\n */\nexport const StatewireHistoryEdge: FC<StatewireHistoryEdgeProps> = ({\n toolOutputs: toolOutputsProp,\n className,\n onHistoryLoad,\n}) => {\n const providerToolOutputs = useStatewireToolOutputs();\n const toolOutputs = toolOutputsProp ?? providerToolOutputs ?? undefined;\n const messages = useAuiState((s) => s.thread.messages);\n const threadId = useContext(AthenaStatewireThreadIdContext);\n const [nearTop, setNearTop] = useState(false);\n const [nearTopEpoch, setNearTopEpoch] = useState(0);\n const nearTopRef = useRef(false);\n const [rowEl, setRowEl] = useState<HTMLElement | null>(null);\n // The scroll viewport the thread registered (assistant-ui's viewport store),\n // known even while the row renders nothing; the row's ancestor otherwise.\n const hasViewportStore = useThreadViewportStore({ optional: true }) !== null;\n const registeredViewport = useThreadViewport({\n optional: true,\n selector: (state: ThreadViewportState) => state.element.viewport,\n });\n const viewport =\n registeredViewport ?? rowEl?.closest<HTMLElement>(`[${THREAD_VIEWPORT_ATTR}]`) ?? null;\n const isMessageMounted = useMessagesNearViewport({\n viewport,\n hasViewport: hasViewportStore || viewport !== null,\n messages,\n });\n const historyStore = useContext(StatewireHistoryContext);\n const { hasOlder, canLoadOlder, loading, loadOlder } = useDeepAgentWindowSync({\n messages,\n toolOutputs,\n nearTop,\n nearTopEpoch,\n isMessageMounted,\n maxConcurrentToolOutputs: HISTORY_EDGE_TOOL_OUTPUT_CONCURRENCY,\n onHistoryLoad,\n onError: (error, command) => {\n // Leaving the thread settles an in-flight read as lost: lifecycle, not a failure.\n if (error instanceof Error && isStatewireChannelTeardown(error)) return;\n console.warn(`[StatewireHistoryEdge] ${command} failed:`, error);\n },\n });\n\n // Other surfaces of the provider (the workbench's Shell pane) read where the\n // history stands; leaving the thread or unmounting withdraws the report.\n useEffect(() => {\n if (!historyStore || !threadId) return undefined;\n historyStore.set({ threadId, hasOlder, canLoadOlder, loading, loadOlder });\n return undefined;\n }, [historyStore, threadId, hasOlder, canLoadOlder, loading, loadOlder]);\n useEffect(() => {\n if (!historyStore || !threadId) return undefined;\n return () => {\n if (historyStore.get().threadId === threadId) historyStore.set(NO_STATEWIRE_HISTORY);\n };\n }, [historyStore, threadId]);\n\n // The row's own visibility is the near-top level: a level, not an edge, so\n // pages chain while the user stays at the top and stop once the prepended\n // content has pushed the row away again.\n useEffect(() => {\n if (!rowEl || !hasOlder || typeof IntersectionObserver === \"undefined\") return;\n const observer = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n const near = entry.isIntersecting;\n if (nearTopRef.current === near) continue;\n nearTopRef.current = near;\n setNearTop(near);\n if (near) setNearTopEpoch((epoch) => epoch + 1);\n }\n },\n {\n root: viewport,\n rootMargin: `${HISTORY_EDGE_NEAR_MARGIN_PX}px 0px`,\n },\n );\n observer.observe(rowEl);\n return () => {\n observer.disconnect();\n nearTopRef.current = false;\n setNearTop(false);\n };\n }, [rowEl, hasOlder, viewport]);\n\n return (\n <>\n <KeepReadingPlace viewport={viewport} threadId={threadId} messages={messages} />\n <HistoryEdgeRow\n rowRef={setRowEl}\n hasOlder={hasOlder}\n canLoadOlder={canLoadOlder}\n loading={loading}\n onLoadOlder={loadOlder}\n className={className}\n />\n </>\n );\n};\n"],"names":["useState","useRef","useEffect","useMemo","getExternalStoreMessages","Component","jsx","cn","useStatewireToolOutputs","useAuiState","useContext","AthenaStatewireThreadIdContext","useThreadViewportStore","useThreadViewport","StatewireHistoryContext","useDeepAgentWindowSync","isStatewireChannelTeardown","NO_STATEWIRE_HISTORY","jsxs","Fragment"],"mappings":"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"}
|
|
@@ -49,12 +49,11 @@ function useMessagesNearViewport({
|
|
|
49
49
|
{ root: viewport, rootMargin: `${HISTORY_EDGE_NEAR_MARGIN_PX}px 0px` }
|
|
50
50
|
);
|
|
51
51
|
const track = () => {
|
|
52
|
-
let dropped = false;
|
|
53
52
|
for (const element of observed) {
|
|
54
53
|
if (element.isConnected) continue;
|
|
55
54
|
intersections.unobserve(element);
|
|
56
55
|
observed.delete(element);
|
|
57
|
-
|
|
56
|
+
near.delete(element);
|
|
58
57
|
}
|
|
59
58
|
const rendered = /* @__PURE__ */ new Set();
|
|
60
59
|
for (const element of viewport.querySelectorAll(MESSAGE_SELECTOR)) {
|
|
@@ -65,7 +64,7 @@ function useMessagesNearViewport({
|
|
|
65
64
|
intersections.observe(element);
|
|
66
65
|
}
|
|
67
66
|
renderedIdsRef.current = rendered;
|
|
68
|
-
|
|
67
|
+
publish();
|
|
69
68
|
};
|
|
70
69
|
trackRef.current = track;
|
|
71
70
|
track();
|
|
@@ -141,7 +140,7 @@ const HistoryEdgeRow = ({
|
|
|
141
140
|
ref: rowRef,
|
|
142
141
|
"data-testid": "thread-history-edge",
|
|
143
142
|
className: cn(
|
|
144
|
-
"flex w-full max-w-(--thread-max-width) items-center justify-center py-1 text-xs text-muted-foreground",
|
|
143
|
+
"mx-auto flex w-full max-w-(--thread-max-width) items-center justify-center py-1 text-xs text-muted-foreground",
|
|
145
144
|
className
|
|
146
145
|
),
|
|
147
146
|
children: loading ? /* @__PURE__ */ jsx("span", { "data-testid": "thread-history-edge-loading", children: "Loading earlier messages…" }) : canLoadOlder ? /* @__PURE__ */ jsx(
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"statewire-history-edge.js","sources":["../../../src/chat-ui/thread/statewire-history-edge.tsx"],"sourcesContent":["import {\n getExternalStoreMessages,\n type ThreadMessage,\n type ThreadViewportState,\n useAuiState,\n useThreadViewport,\n useThreadViewportStore,\n} from \"@assistant-ui/react\";\nimport {\n type DeepAgentHistoryLoadEvent,\n type DeepAgentToolOutputStore,\n isStatewireChannelTeardown,\n useDeepAgentWindowSync,\n} from \"@athenaintel/agent-runtime\";\nimport type { FC } from \"react\";\nimport { Component, useContext, useEffect, useMemo, useRef, useState } from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport {\n NO_STATEWIRE_HISTORY,\n StatewireHistoryContext,\n} from \"../../provider/statewire-history-context\";\nimport { useStatewireToolOutputs } from \"../../provider/statewire-window-context\";\nimport { AthenaStatewireThreadIdContext } from \"../../threads/thread-id-context\";\n\n/** The attribute `ChatThreadShell` stamps on the scroll viewport. */\nexport const THREAD_VIEWPORT_ATTR = \"data-aui-thread-viewport\";\n\n/**\n * How far above the viewport the edge row counts as near: the row sits above\n * the first loaded message, so reaching it means the user has scrolled past\n * everything loaded and the next page should already be on its way. Messages\n * this close to the viewport also count as on screen for cut tool outputs.\n */\nexport const HISTORY_EDGE_NEAR_MARGIN_PX = 1500;\n\n/**\n * Cut tool outputs a transcript reads at once. The reads share the session's\n * command lane with everything the person sends, so a long transcript must\n * not queue dozens of them ahead of a message or a Stop.\n */\nexport const HISTORY_EDGE_TOOL_OUTPUT_CONCURRENCY = 2;\n\n/** What assistant-ui's `MessagePrimitive.Root` stamps on every message. */\nconst MESSAGE_SELECTOR = \"[data-message-id]\";\n\nconst NO_MESSAGE_IDS: ReadonlySet<string> = new Set();\n\nfunction sameIds({ a, b }: { a: ReadonlySet<string>; b: ReadonlySet<string> }): boolean {\n if (a.size !== b.size) return false;\n for (const id of a) if (!b.has(id)) return false;\n return true;\n}\n\n/**\n * Which messages sit within {@link HISTORY_EDGE_NEAR_MARGIN_PX} of the\n * viewport, so cut tool outputs are read for what the person can reach. A\n * thread opens at its newest turn; reading every loaded step's output up\n * front sent dozens of reads, each re-rendering the transcript, for steps\n * nobody had scrolled to.\n *\n * `undefined` (every message counts) where nothing can be observed: no\n * viewport around the row, or no `IntersectionObserver`. A message rendered\n * without a `data-message-id` root (a host's own renderer) cannot be observed\n * either, so it counts as before.\n */\nfunction useMessagesNearViewport({\n viewport,\n hasViewport,\n messages,\n}: {\n viewport: HTMLElement | null;\n /** A viewport is (or will be) registered around the row. */\n hasViewport: boolean;\n /** The converted thread: every change may have mounted or remounted a message. */\n messages: readonly ThreadMessage[];\n}): ((messageId: string) => boolean) | undefined {\n const [nearIds, setNearIds] = useState<ReadonlySet<string>>(NO_MESSAGE_IDS);\n const observable = hasViewport && typeof IntersectionObserver !== \"undefined\";\n const trackRef = useRef<(() => void) | null>(null);\n // Every id a rendered element carries, as of the last scan.\n const renderedIdsRef = useRef<ReadonlySet<string>>(NO_MESSAGE_IDS);\n\n useEffect(() => {\n if (!viewport || !observable) return undefined;\n const near = new Set<Element>();\n const observed = new Set<Element>();\n const publish = () => {\n const ids = new Set<string>();\n for (const element of near) {\n const id = element.getAttribute(\"data-message-id\");\n if (id) ids.add(id);\n }\n setNearIds((previous) => (sameIds({ a: previous, b: ids }) ? previous : ids));\n };\n const intersections = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n if (entry.isIntersecting && entry.target.isConnected) near.add(entry.target);\n else near.delete(entry.target);\n }\n publish();\n },\n { root: viewport, rootMargin: `${HISTORY_EDGE_NEAR_MARGIN_PX}px 0px` },\n );\n // Messages remount when a page folds into them (a new id), so what is\n // observed follows the rendered elements, not the message list.\n const track = () => {\n let dropped = false;\n for (const element of observed) {\n if (element.isConnected) continue;\n intersections.unobserve(element);\n observed.delete(element);\n dropped = near.delete(element) || dropped;\n }\n const rendered = new Set<string>();\n for (const element of viewport.querySelectorAll(MESSAGE_SELECTOR)) {\n const id = element.getAttribute(\"data-message-id\");\n if (id) rendered.add(id);\n if (observed.has(element)) continue;\n observed.add(element);\n intersections.observe(element);\n }\n renderedIdsRef.current = rendered;\n if (dropped) publish();\n };\n trackRef.current = track;\n track();\n return () => {\n trackRef.current = null;\n renderedIdsRef.current = NO_MESSAGE_IDS;\n intersections.disconnect();\n setNearIds(NO_MESSAGE_IDS);\n };\n }, [viewport, observable]);\n\n // A changed message list is the trigger to re-scan: its messages render in\n // the same commit, so their elements are in the DOM by this effect (a\n // query, no layout read).\n useEffect(() => {\n trackRef.current?.();\n }, [messages]);\n\n return useMemo(() => {\n if (!observable) return undefined;\n return (messageId: string) => {\n // Not registered yet: nothing is on screen to read for.\n if (viewport === null) return false;\n return nearIds.has(messageId) || !renderedIdsRef.current.has(messageId);\n };\n }, [nearIds, observable, viewport]);\n}\n\n/** The wire message a converted message was built from first (its oldest source). */\nfunction oldestSourceId(message: ThreadMessage): string | undefined {\n const source = getExternalStoreMessages<{ id?: unknown }>(message)[0];\n return typeof source?.id === \"string\" ? source.id : undefined;\n}\n\n/**\n * Whether older history landed ahead of what was loaded: the old first\n * message now sits further down (a page ahead of it), or the first message's\n * old oldest wire message now follows earlier ones (a page that folded into\n * the first loaded turn). A first message replaced in place — a branch picked\n * on it, an edit — is neither, and a run streaming at the tail never touches\n * the first message.\n */\nfunction prependedOlderHistory({\n previous,\n next,\n}: {\n previous: readonly ThreadMessage[];\n next: readonly ThreadMessage[];\n}): boolean {\n const previousFirst = previous[0];\n const nextFirst = next[0];\n if (previousFirst === undefined || nextFirst === undefined || previousFirst === nextFirst) return false;\n if (previousFirst.id !== nextFirst.id && next.some((message, index) => index > 0 && message.id === previousFirst.id)) {\n return true;\n }\n const previousOldest = oldestSourceId(previousFirst);\n if (previousOldest === undefined || previousOldest === oldestSourceId(nextFirst)) return false;\n return getExternalStoreMessages<{ id?: unknown }>(nextFirst).some(\n (source, index) => index > 0 && source?.id === previousOldest,\n );\n}\n\ninterface KeepReadingPlaceProps {\n viewport: HTMLElement | null;\n threadId: string | null;\n /** The converted thread. */\n messages: readonly ThreadMessage[];\n}\n\n/**\n * Keeps the reader's place when older history lands. Everything a page adds\n * sits above what the person is reading, so their distance from the bottom of\n * the transcript is what must survive. A class for `getSnapshotBeforeUpdate`:\n * the distance is read right before React applies the commit that renders the\n * page — the one moment it is exact, even for a scroll the browser has not\n * reported yet — and restored after it, instantly (never through the\n * viewport's smooth scrolling). Other commits read no layout.\n *\n * The browser's scroll anchoring and assistant-ui's prepend anchor aim at the\n * same position, so whichever ran first leaves this nothing to do; on its own\n * it covers what they miss: a reader at the very top (browsers never anchor\n * at scroll offset 0) and a page that folds into the first loaded turn (that\n * message remounts under a new id, taking the browser's anchor node with it).\n */\nclass KeepReadingPlace extends Component<KeepReadingPlaceProps> {\n getSnapshotBeforeUpdate(previous: Readonly<KeepReadingPlaceProps>): number | null {\n const { viewport, threadId, messages } = this.props;\n if (\n viewport === null ||\n viewport !== previous.viewport ||\n threadId !== previous.threadId ||\n messages === previous.messages ||\n !prependedOlderHistory({ previous: previous.messages, next: messages })\n ) {\n return null;\n }\n return viewport.scrollHeight - viewport.scrollTop;\n }\n\n componentDidUpdate(\n _previous: Readonly<KeepReadingPlaceProps>,\n _state: unknown,\n fromBottom: number | null,\n ): void {\n const { viewport } = this.props;\n if (viewport === null || fromBottom === null) return;\n const top = viewport.scrollHeight - fromBottom;\n if (Math.abs(viewport.scrollTop - top) >= 1) viewport.scrollTo({ top, behavior: \"instant\" });\n }\n\n render(): null {\n return null;\n }\n}\n\nexport interface HistoryEdgeRowProps {\n /** Whether the server holds messages older than the loaded window. */\n hasOlder: boolean;\n /** Whether the next page can be asked for; `false` with `hasOlder` is the connection's loading depth spent. Defaults to `hasOlder`. */\n canLoadOlder?: boolean;\n /** A page of older history is in flight. */\n loading: boolean;\n onLoadOlder: () => void;\n className?: string;\n /** The row element, for the viewport observer. */\n rowRef?: (element: HTMLElement | null) => void;\n}\n\n/**\n * The top edge of the LOADED history: a manual way to load the next page of\n * older messages, and the in-flight state. Renders nothing when the whole\n * transcript is loaded (or the head interest has not resolved).\n */\nexport const HistoryEdgeRow: FC<HistoryEdgeRowProps> = ({\n hasOlder,\n canLoadOlder = hasOlder,\n loading,\n onLoadOlder,\n className,\n rowRef,\n}) => {\n if (!hasOlder) return null;\n return (\n <div\n ref={rowRef}\n data-testid=\"thread-history-edge\"\n className={cn(\n \"flex w-full max-w-(--thread-max-width) items-center justify-center py-1 text-xs text-muted-foreground\",\n className,\n )}\n >\n {loading ? (\n <span data-testid=\"thread-history-edge-loading\">Loading earlier messages…</span>\n ) : canLoadOlder ? (\n <button\n type=\"button\"\n data-testid=\"thread-history-edge-load\"\n onClick={onLoadOlder}\n className=\"rounded-lg px-2.5 py-1 text-xs font-medium text-muted-foreground transition-colors hover:bg-accent hover:text-foreground\"\n >\n Load earlier messages\n </button>\n ) : (\n <span data-testid=\"thread-history-edge-limit\">Earlier messages can't be loaded here</span>\n )}\n </div>\n );\n};\n\nexport interface StatewireHistoryEdgeProps {\n /**\n * The thread's tool-output store (the one its converter substitutes from).\n * Defaults to `AthenaProvider`'s; hosts mounting the runtime themselves pass\n * the store they gave `useDeepAgentRuntime({ toolOutputs })`.\n */\n toolOutputs?: DeepAgentToolOutputStore;\n className?: string;\n /** A page interest resolved (telemetry). */\n onHistoryLoad?: (event: DeepAgentHistoryLoadEvent) => void;\n}\n\n/**\n * The client half of the interest window for a DOM thread — mounted once per\n * thread, inside the scroll viewport above the messages (`ChatThreadShell`'s\n * `beforeMessages` slot):\n *\n * - renders the \"Load earlier messages\" edge row and loads the next page when\n * the row comes near the viewport (scrolling up) or on its button, keeping\n * the reading position when the page lands above the view;\n * - fetches cut tool outputs whole for the cards near the viewport, a few at\n * a time, so they re-render complete through the converter (`toolOutputs`).\n *\n * Inert until the head interest resolves: no row, no reads.\n */\nexport const StatewireHistoryEdge: FC<StatewireHistoryEdgeProps> = ({\n toolOutputs: toolOutputsProp,\n className,\n onHistoryLoad,\n}) => {\n const providerToolOutputs = useStatewireToolOutputs();\n const toolOutputs = toolOutputsProp ?? providerToolOutputs ?? undefined;\n const messages = useAuiState((s) => s.thread.messages);\n const threadId = useContext(AthenaStatewireThreadIdContext);\n const [nearTop, setNearTop] = useState(false);\n const [nearTopEpoch, setNearTopEpoch] = useState(0);\n const nearTopRef = useRef(false);\n const [rowEl, setRowEl] = useState<HTMLElement | null>(null);\n // The scroll viewport the thread registered (assistant-ui's viewport store),\n // known even while the row renders nothing; the row's ancestor otherwise.\n const hasViewportStore = useThreadViewportStore({ optional: true }) !== null;\n const registeredViewport = useThreadViewport({\n optional: true,\n selector: (state: ThreadViewportState) => state.element.viewport,\n });\n const viewport =\n registeredViewport ?? rowEl?.closest<HTMLElement>(`[${THREAD_VIEWPORT_ATTR}]`) ?? null;\n const isMessageMounted = useMessagesNearViewport({\n viewport,\n hasViewport: hasViewportStore || viewport !== null,\n messages,\n });\n const historyStore = useContext(StatewireHistoryContext);\n const { hasOlder, canLoadOlder, loading, loadOlder } = useDeepAgentWindowSync({\n messages,\n toolOutputs,\n nearTop,\n nearTopEpoch,\n isMessageMounted,\n maxConcurrentToolOutputs: HISTORY_EDGE_TOOL_OUTPUT_CONCURRENCY,\n onHistoryLoad,\n onError: (error, command) => {\n // Leaving the thread settles an in-flight read as lost: lifecycle, not a failure.\n if (error instanceof Error && isStatewireChannelTeardown(error)) return;\n console.warn(`[StatewireHistoryEdge] ${command} failed:`, error);\n },\n });\n\n // Other surfaces of the provider (the workbench's Shell pane) read where the\n // history stands; leaving the thread or unmounting withdraws the report.\n useEffect(() => {\n if (!historyStore || !threadId) return undefined;\n historyStore.set({ threadId, hasOlder, canLoadOlder, loading, loadOlder });\n return undefined;\n }, [historyStore, threadId, hasOlder, canLoadOlder, loading, loadOlder]);\n useEffect(() => {\n if (!historyStore || !threadId) return undefined;\n return () => {\n if (historyStore.get().threadId === threadId) historyStore.set(NO_STATEWIRE_HISTORY);\n };\n }, [historyStore, threadId]);\n\n // The row's own visibility is the near-top level: a level, not an edge, so\n // pages chain while the user stays at the top and stop once the prepended\n // content has pushed the row away again.\n useEffect(() => {\n if (!rowEl || !hasOlder || typeof IntersectionObserver === \"undefined\") return;\n const observer = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n const near = entry.isIntersecting;\n if (nearTopRef.current === near) continue;\n nearTopRef.current = near;\n setNearTop(near);\n if (near) setNearTopEpoch((epoch) => epoch + 1);\n }\n },\n {\n root: viewport,\n rootMargin: `${HISTORY_EDGE_NEAR_MARGIN_PX}px 0px`,\n },\n );\n observer.observe(rowEl);\n return () => {\n observer.disconnect();\n nearTopRef.current = false;\n setNearTop(false);\n };\n }, [rowEl, hasOlder, viewport]);\n\n return (\n <>\n <KeepReadingPlace viewport={viewport} threadId={threadId} messages={messages} />\n <HistoryEdgeRow\n rowRef={setRowEl}\n hasOlder={hasOlder}\n canLoadOlder={canLoadOlder}\n loading={loading}\n onLoadOlder={loadOlder}\n className={className}\n />\n </>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"statewire-history-edge.js","sources":["../../../src/chat-ui/thread/statewire-history-edge.tsx"],"sourcesContent":["import {\n getExternalStoreMessages,\n type ThreadMessage,\n type ThreadViewportState,\n useAuiState,\n useThreadViewport,\n useThreadViewportStore,\n} from \"@assistant-ui/react\";\nimport {\n type DeepAgentHistoryLoadEvent,\n type DeepAgentToolOutputStore,\n isStatewireChannelTeardown,\n useDeepAgentWindowSync,\n} from \"@athenaintel/agent-runtime\";\nimport type { FC } from \"react\";\nimport { Component, useContext, useEffect, useMemo, useRef, useState } from \"react\";\nimport { cn } from \"../../lib/utils\";\nimport {\n NO_STATEWIRE_HISTORY,\n StatewireHistoryContext,\n} from \"../../provider/statewire-history-context\";\nimport { useStatewireToolOutputs } from \"../../provider/statewire-window-context\";\nimport { AthenaStatewireThreadIdContext } from \"../../threads/thread-id-context\";\n\n/** The attribute `ChatThreadShell` stamps on the scroll viewport. */\nexport const THREAD_VIEWPORT_ATTR = \"data-aui-thread-viewport\";\n\n/**\n * How far above the viewport the edge row counts as near: the row sits above\n * the first loaded message, so reaching it means the user has scrolled past\n * everything loaded and the next page should already be on its way. Messages\n * this close to the viewport also count as on screen for cut tool outputs.\n */\nexport const HISTORY_EDGE_NEAR_MARGIN_PX = 1500;\n\n/**\n * Cut tool outputs a transcript reads at once. The reads share the session's\n * command lane with everything the person sends, so a long transcript must\n * not queue dozens of them ahead of a message or a Stop.\n */\nexport const HISTORY_EDGE_TOOL_OUTPUT_CONCURRENCY = 2;\n\n/** What assistant-ui's `MessagePrimitive.Root` stamps on every message. */\nconst MESSAGE_SELECTOR = \"[data-message-id]\";\n\nconst NO_MESSAGE_IDS: ReadonlySet<string> = new Set();\n\nfunction sameIds({ a, b }: { a: ReadonlySet<string>; b: ReadonlySet<string> }): boolean {\n if (a.size !== b.size) return false;\n for (const id of a) if (!b.has(id)) return false;\n return true;\n}\n\n/**\n * Which messages sit within {@link HISTORY_EDGE_NEAR_MARGIN_PX} of the\n * viewport, so cut tool outputs are read for what the person can reach. A\n * thread opens at its newest turn; reading every loaded step's output up\n * front sent dozens of reads, each re-rendering the transcript, for steps\n * nobody had scrolled to.\n *\n * `undefined` (every message counts) where nothing can be observed: no\n * viewport around the row, or no `IntersectionObserver`. A message rendered\n * without a `data-message-id` root (a host's own renderer) cannot be observed\n * either, so it counts as before.\n */\nfunction useMessagesNearViewport({\n viewport,\n hasViewport,\n messages,\n}: {\n viewport: HTMLElement | null;\n /** A viewport is (or will be) registered around the row. */\n hasViewport: boolean;\n /** The converted thread: every change may have mounted or remounted a message. */\n messages: readonly ThreadMessage[];\n}): ((messageId: string) => boolean) | undefined {\n const [nearIds, setNearIds] = useState<ReadonlySet<string>>(NO_MESSAGE_IDS);\n const observable = hasViewport && typeof IntersectionObserver !== \"undefined\";\n const trackRef = useRef<(() => void) | null>(null);\n // Every id a rendered element carries, as of the last scan.\n const renderedIdsRef = useRef<ReadonlySet<string>>(NO_MESSAGE_IDS);\n\n useEffect(() => {\n if (!viewport || !observable) return undefined;\n const near = new Set<Element>();\n const observed = new Set<Element>();\n const publish = () => {\n const ids = new Set<string>();\n for (const element of near) {\n const id = element.getAttribute(\"data-message-id\");\n if (id) ids.add(id);\n }\n setNearIds((previous) => (sameIds({ a: previous, b: ids }) ? previous : ids));\n };\n const intersections = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n if (entry.isIntersecting && entry.target.isConnected) near.add(entry.target);\n else near.delete(entry.target);\n }\n publish();\n },\n { root: viewport, rootMargin: `${HISTORY_EDGE_NEAR_MARGIN_PX}px 0px` },\n );\n // A page that folds into a turn gives it a new id: a host keyed by id\n // remounts the turn's element, a host keyed by row (`ChatThreadShell`)\n // keeps it and the element's id changes. So what is observed follows the\n // rendered elements, not the message list, and the near ids are read off\n // those elements again on every scan.\n const track = () => {\n for (const element of observed) {\n if (element.isConnected) continue;\n intersections.unobserve(element);\n observed.delete(element);\n near.delete(element);\n }\n const rendered = new Set<string>();\n for (const element of viewport.querySelectorAll(MESSAGE_SELECTOR)) {\n const id = element.getAttribute(\"data-message-id\");\n if (id) rendered.add(id);\n if (observed.has(element)) continue;\n observed.add(element);\n intersections.observe(element);\n }\n renderedIdsRef.current = rendered;\n publish();\n };\n trackRef.current = track;\n track();\n return () => {\n trackRef.current = null;\n renderedIdsRef.current = NO_MESSAGE_IDS;\n intersections.disconnect();\n setNearIds(NO_MESSAGE_IDS);\n };\n }, [viewport, observable]);\n\n // A changed message list is the trigger to re-scan: its messages render in\n // the same commit, so their elements are in the DOM by this effect (a\n // query, no layout read).\n useEffect(() => {\n trackRef.current?.();\n }, [messages]);\n\n return useMemo(() => {\n if (!observable) return undefined;\n return (messageId: string) => {\n // Not registered yet: nothing is on screen to read for.\n if (viewport === null) return false;\n return nearIds.has(messageId) || !renderedIdsRef.current.has(messageId);\n };\n }, [nearIds, observable, viewport]);\n}\n\n/** The wire message a converted message was built from first (its oldest source). */\nfunction oldestSourceId(message: ThreadMessage): string | undefined {\n const source = getExternalStoreMessages<{ id?: unknown }>(message)[0];\n return typeof source?.id === \"string\" ? source.id : undefined;\n}\n\n/**\n * Whether older history landed ahead of what was loaded: the old first\n * message now sits further down (a page ahead of it), or the first message's\n * old oldest wire message now follows earlier ones (a page that folded into\n * the first loaded turn). A first message replaced in place — a branch picked\n * on it, an edit — is neither, and a run streaming at the tail never touches\n * the first message.\n */\nfunction prependedOlderHistory({\n previous,\n next,\n}: {\n previous: readonly ThreadMessage[];\n next: readonly ThreadMessage[];\n}): boolean {\n const previousFirst = previous[0];\n const nextFirst = next[0];\n if (previousFirst === undefined || nextFirst === undefined || previousFirst === nextFirst) return false;\n if (previousFirst.id !== nextFirst.id && next.some((message, index) => index > 0 && message.id === previousFirst.id)) {\n return true;\n }\n const previousOldest = oldestSourceId(previousFirst);\n if (previousOldest === undefined || previousOldest === oldestSourceId(nextFirst)) return false;\n return getExternalStoreMessages<{ id?: unknown }>(nextFirst).some(\n (source, index) => index > 0 && source?.id === previousOldest,\n );\n}\n\ninterface KeepReadingPlaceProps {\n viewport: HTMLElement | null;\n threadId: string | null;\n /** The converted thread. */\n messages: readonly ThreadMessage[];\n}\n\n/**\n * Keeps the reader's place when older history lands. Everything a page adds\n * sits above what the person is reading, so their distance from the bottom of\n * the transcript is what must survive. A class for `getSnapshotBeforeUpdate`:\n * the distance is read right before React applies the commit that renders the\n * page — the one moment it is exact, even for a scroll the browser has not\n * reported yet — and restored after it, instantly (never through the\n * viewport's smooth scrolling). Other commits read no layout.\n *\n * The browser's scroll anchoring and assistant-ui's prepend anchor aim at the\n * same position, so whichever ran first leaves this nothing to do; on its own\n * it covers what they miss: a reader at the very top (browsers never anchor\n * at scroll offset 0) and a page that folds into the first loaded turn of a\n * host that keys rows by message id (that message remounts under a new id,\n * taking the browser's anchor node with it; `ChatThreadShell` keeps the row).\n */\nclass KeepReadingPlace extends Component<KeepReadingPlaceProps> {\n getSnapshotBeforeUpdate(previous: Readonly<KeepReadingPlaceProps>): number | null {\n const { viewport, threadId, messages } = this.props;\n if (\n viewport === null ||\n viewport !== previous.viewport ||\n threadId !== previous.threadId ||\n messages === previous.messages ||\n !prependedOlderHistory({ previous: previous.messages, next: messages })\n ) {\n return null;\n }\n return viewport.scrollHeight - viewport.scrollTop;\n }\n\n componentDidUpdate(\n _previous: Readonly<KeepReadingPlaceProps>,\n _state: unknown,\n fromBottom: number | null,\n ): void {\n const { viewport } = this.props;\n if (viewport === null || fromBottom === null) return;\n const top = viewport.scrollHeight - fromBottom;\n if (Math.abs(viewport.scrollTop - top) >= 1) viewport.scrollTo({ top, behavior: \"instant\" });\n }\n\n render(): null {\n return null;\n }\n}\n\nexport interface HistoryEdgeRowProps {\n /** Whether the server holds messages older than the loaded window. */\n hasOlder: boolean;\n /** Whether the next page can be asked for; `false` with `hasOlder` is the connection's loading depth spent. Defaults to `hasOlder`. */\n canLoadOlder?: boolean;\n /** A page of older history is in flight. */\n loading: boolean;\n onLoadOlder: () => void;\n className?: string;\n /** The row element, for the viewport observer. */\n rowRef?: (element: HTMLElement | null) => void;\n}\n\n/**\n * The top edge of the LOADED history: a manual way to load the next page of\n * older messages, and the in-flight state. Renders nothing when the whole\n * transcript is loaded (or the head interest has not resolved).\n */\nexport const HistoryEdgeRow: FC<HistoryEdgeRowProps> = ({\n hasOlder,\n canLoadOlder = hasOlder,\n loading,\n onLoadOlder,\n className,\n rowRef,\n}) => {\n if (!hasOlder) return null;\n return (\n <div\n ref={rowRef}\n data-testid=\"thread-history-edge\"\n className={cn(\n \"mx-auto flex w-full max-w-(--thread-max-width) items-center justify-center py-1 text-xs text-muted-foreground\",\n className,\n )}\n >\n {loading ? (\n <span data-testid=\"thread-history-edge-loading\">Loading earlier messages…</span>\n ) : canLoadOlder ? (\n <button\n type=\"button\"\n data-testid=\"thread-history-edge-load\"\n onClick={onLoadOlder}\n className=\"rounded-lg px-2.5 py-1 text-xs font-medium text-muted-foreground transition-colors hover:bg-accent hover:text-foreground\"\n >\n Load earlier messages\n </button>\n ) : (\n <span data-testid=\"thread-history-edge-limit\">Earlier messages can't be loaded here</span>\n )}\n </div>\n );\n};\n\nexport interface StatewireHistoryEdgeProps {\n /**\n * The thread's tool-output store (the one its converter substitutes from).\n * Defaults to `AthenaProvider`'s; hosts mounting the runtime themselves pass\n * the store they gave `useDeepAgentRuntime({ toolOutputs })`.\n */\n toolOutputs?: DeepAgentToolOutputStore;\n className?: string;\n /** A page interest resolved (telemetry). */\n onHistoryLoad?: (event: DeepAgentHistoryLoadEvent) => void;\n}\n\n/**\n * The client half of the interest window for a DOM thread — mounted once per\n * thread, inside the scroll viewport above the messages (`ChatThreadShell`'s\n * `beforeMessages` slot):\n *\n * - renders the \"Load earlier messages\" edge row and loads the next page when\n * the row comes near the viewport (scrolling up) or on its button, keeping\n * the reading position when the page lands above the view;\n * - fetches cut tool outputs whole for the cards near the viewport, a few at\n * a time, so they re-render complete through the converter (`toolOutputs`).\n *\n * Inert until the head interest resolves: no row, no reads.\n */\nexport const StatewireHistoryEdge: FC<StatewireHistoryEdgeProps> = ({\n toolOutputs: toolOutputsProp,\n className,\n onHistoryLoad,\n}) => {\n const providerToolOutputs = useStatewireToolOutputs();\n const toolOutputs = toolOutputsProp ?? providerToolOutputs ?? undefined;\n const messages = useAuiState((s) => s.thread.messages);\n const threadId = useContext(AthenaStatewireThreadIdContext);\n const [nearTop, setNearTop] = useState(false);\n const [nearTopEpoch, setNearTopEpoch] = useState(0);\n const nearTopRef = useRef(false);\n const [rowEl, setRowEl] = useState<HTMLElement | null>(null);\n // The scroll viewport the thread registered (assistant-ui's viewport store),\n // known even while the row renders nothing; the row's ancestor otherwise.\n const hasViewportStore = useThreadViewportStore({ optional: true }) !== null;\n const registeredViewport = useThreadViewport({\n optional: true,\n selector: (state: ThreadViewportState) => state.element.viewport,\n });\n const viewport =\n registeredViewport ?? rowEl?.closest<HTMLElement>(`[${THREAD_VIEWPORT_ATTR}]`) ?? null;\n const isMessageMounted = useMessagesNearViewport({\n viewport,\n hasViewport: hasViewportStore || viewport !== null,\n messages,\n });\n const historyStore = useContext(StatewireHistoryContext);\n const { hasOlder, canLoadOlder, loading, loadOlder } = useDeepAgentWindowSync({\n messages,\n toolOutputs,\n nearTop,\n nearTopEpoch,\n isMessageMounted,\n maxConcurrentToolOutputs: HISTORY_EDGE_TOOL_OUTPUT_CONCURRENCY,\n onHistoryLoad,\n onError: (error, command) => {\n // Leaving the thread settles an in-flight read as lost: lifecycle, not a failure.\n if (error instanceof Error && isStatewireChannelTeardown(error)) return;\n console.warn(`[StatewireHistoryEdge] ${command} failed:`, error);\n },\n });\n\n // Other surfaces of the provider (the workbench's Shell pane) read where the\n // history stands; leaving the thread or unmounting withdraws the report.\n useEffect(() => {\n if (!historyStore || !threadId) return undefined;\n historyStore.set({ threadId, hasOlder, canLoadOlder, loading, loadOlder });\n return undefined;\n }, [historyStore, threadId, hasOlder, canLoadOlder, loading, loadOlder]);\n useEffect(() => {\n if (!historyStore || !threadId) return undefined;\n return () => {\n if (historyStore.get().threadId === threadId) historyStore.set(NO_STATEWIRE_HISTORY);\n };\n }, [historyStore, threadId]);\n\n // The row's own visibility is the near-top level: a level, not an edge, so\n // pages chain while the user stays at the top and stop once the prepended\n // content has pushed the row away again.\n useEffect(() => {\n if (!rowEl || !hasOlder || typeof IntersectionObserver === \"undefined\") return;\n const observer = new IntersectionObserver(\n (entries) => {\n for (const entry of entries) {\n const near = entry.isIntersecting;\n if (nearTopRef.current === near) continue;\n nearTopRef.current = near;\n setNearTop(near);\n if (near) setNearTopEpoch((epoch) => epoch + 1);\n }\n },\n {\n root: viewport,\n rootMargin: `${HISTORY_EDGE_NEAR_MARGIN_PX}px 0px`,\n },\n );\n observer.observe(rowEl);\n return () => {\n observer.disconnect();\n nearTopRef.current = false;\n setNearTop(false);\n };\n }, [rowEl, hasOlder, viewport]);\n\n return (\n <>\n <KeepReadingPlace viewport={viewport} threadId={threadId} messages={messages} />\n <HistoryEdgeRow\n rowRef={setRowEl}\n hasOlder={hasOlder}\n canLoadOlder={canLoadOlder}\n loading={loading}\n onLoadOlder={loadOlder}\n className={className}\n />\n </>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
|
-
const react
|
|
5
|
-
const
|
|
4
|
+
const react = require("@assistant-ui/react");
|
|
5
|
+
const require$$0 = require("react");
|
|
6
6
|
const threadIdContext = require("../../threads/thread-id-context.cjs");
|
|
7
7
|
const THREAD_LOADING_OVERLAY_TIMEOUT_MS = 15e3;
|
|
8
8
|
const ThreadLoadingOverlay = () => {
|
|
9
9
|
const remoteId = threadIdContext.useAthenaThreadId();
|
|
10
|
-
const [timedOut, setTimedOut] =
|
|
11
|
-
|
|
10
|
+
const [timedOut, setTimedOut] = require$$0.useState(false);
|
|
11
|
+
require$$0.useEffect(() => {
|
|
12
12
|
if (!remoteId) return;
|
|
13
13
|
setTimedOut(false);
|
|
14
14
|
const timer = setTimeout(() => setTimedOut(true), THREAD_LOADING_OVERLAY_TIMEOUT_MS);
|
|
15
15
|
return () => clearTimeout(timer);
|
|
16
16
|
}, [remoteId]);
|
|
17
17
|
if (!remoteId || timedOut) return null;
|
|
18
|
-
return /* @__PURE__ */ jsxRuntime.jsx(react
|
|
18
|
+
return /* @__PURE__ */ jsxRuntime.jsx(react.AuiIf, { condition: (s) => s.thread.isEmpty, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
19
19
|
"div",
|
|
20
20
|
{
|
|
21
21
|
"data-testid": "thread-loading-overlay",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"thread-loading-overlay.cjs","sources":["../../../src/chat-ui/thread/thread-loading-overlay.tsx"],"sourcesContent":["import { AuiIf } from '@assistant-ui/react';\nimport type { FC } from 'react';\nimport { useEffect, useState } from 'react';\nimport { useAthenaThreadId } from '../../threads/thread-id-context';\n\n/** How long the overlay covers an empty thread with server history before giving up. */\nexport const THREAD_LOADING_OVERLAY_TIMEOUT_MS = 15_000;\n\n/**\n * The scrim `AthenaChat` mounts over the thread panel while a thread that\n * has server history (`useAthenaThreadId()` defined) is still empty — the\n * attach has not delivered its snapshot yet. A never-started chat is empty\n * on purpose and gets no scrim; a switch to a thread the snapshot cache\n * holds (a recently visited or hover-prefetched session) mounts with its\n * messages and never shows it either. Gives up after\n * {@link THREAD_LOADING_OVERLAY_TIMEOUT_MS} so a thread that is genuinely\n * empty on the server does not stay covered.\n */\nexport const ThreadLoadingOverlay: FC = () => {\n const remoteId = useAthenaThreadId();\n const [timedOut, setTimedOut] = useState(false);\n\n useEffect(() => {\n if (!remoteId) return;\n setTimedOut(false);\n const timer = setTimeout(() => setTimedOut(true), THREAD_LOADING_OVERLAY_TIMEOUT_MS);\n return () => clearTimeout(timer);\n }, [remoteId]);\n\n if (!remoteId || timedOut) return null;\n\n return (\n <AuiIf condition={(s) => s.thread.isEmpty}>\n <div\n data-testid=\"thread-loading-overlay\"\n role=\"status\"\n aria-label=\"Loading conversation\"\n className=\"absolute inset-0 z-10 flex items-center justify-center bg-background/80\"\n >\n <div className=\"size-5 animate-spin rounded-full border-2 border-muted-foreground border-t-transparent\" />\n </div>\n </AuiIf>\n );\n};\n"],"names":["useAthenaThreadId","useState","useEffect","AuiIf","jsx"],"mappings":";;;;;;AAMO,MAAM,oCAAoC;AAY1C,MAAM,uBAA2B,MAAM;AAC5C,QAAM,WAAWA,gBAAAA,kBAAA;AACjB,QAAM,CAAC,UAAU,WAAW,IAAIC,
|
|
1
|
+
{"version":3,"file":"thread-loading-overlay.cjs","sources":["../../../src/chat-ui/thread/thread-loading-overlay.tsx"],"sourcesContent":["import { AuiIf } from '@assistant-ui/react';\nimport type { FC } from 'react';\nimport { useEffect, useState } from 'react';\nimport { useAthenaThreadId } from '../../threads/thread-id-context';\n\n/** How long the overlay covers an empty thread with server history before giving up. */\nexport const THREAD_LOADING_OVERLAY_TIMEOUT_MS = 15_000;\n\n/**\n * The scrim `AthenaChat` mounts over the thread panel while a thread that\n * has server history (`useAthenaThreadId()` defined) is still empty — the\n * attach has not delivered its snapshot yet. A never-started chat is empty\n * on purpose and gets no scrim; a switch to a thread the snapshot cache\n * holds (a recently visited or hover-prefetched session) mounts with its\n * messages and never shows it either. Gives up after\n * {@link THREAD_LOADING_OVERLAY_TIMEOUT_MS} so a thread that is genuinely\n * empty on the server does not stay covered.\n */\nexport const ThreadLoadingOverlay: FC = () => {\n const remoteId = useAthenaThreadId();\n const [timedOut, setTimedOut] = useState(false);\n\n useEffect(() => {\n if (!remoteId) return;\n setTimedOut(false);\n const timer = setTimeout(() => setTimedOut(true), THREAD_LOADING_OVERLAY_TIMEOUT_MS);\n return () => clearTimeout(timer);\n }, [remoteId]);\n\n if (!remoteId || timedOut) return null;\n\n return (\n <AuiIf condition={(s) => s.thread.isEmpty}>\n <div\n data-testid=\"thread-loading-overlay\"\n role=\"status\"\n aria-label=\"Loading conversation\"\n className=\"absolute inset-0 z-10 flex items-center justify-center bg-background/80\"\n >\n <div className=\"size-5 animate-spin rounded-full border-2 border-muted-foreground border-t-transparent\" />\n </div>\n </AuiIf>\n );\n};\n"],"names":["useAthenaThreadId","useState","useEffect","AuiIf","jsx"],"mappings":";;;;;;AAMO,MAAM,oCAAoC;AAY1C,MAAM,uBAA2B,MAAM;AAC5C,QAAM,WAAWA,gBAAAA,kBAAA;AACjB,QAAM,CAAC,UAAU,WAAW,IAAIC,WAAAA,SAAS,KAAK;AAE9CC,aAAAA,UAAU,MAAM;AACd,QAAI,CAAC,SAAU;AACf,gBAAY,KAAK;AACjB,UAAM,QAAQ,WAAW,MAAM,YAAY,IAAI,GAAG,iCAAiC;AACnF,WAAO,MAAM,aAAa,KAAK;AAAA,EACjC,GAAG,CAAC,QAAQ,CAAC;AAEb,MAAI,CAAC,YAAY,SAAU,QAAO;AAElC,wCACGC,aAAA,EAAM,WAAW,CAAC,MAAM,EAAE,OAAO,SAChC,UAAAC,2BAAAA;AAAAA,IAAC;AAAA,IAAA;AAAA,MACC,eAAY;AAAA,MACZ,MAAK;AAAA,MACL,cAAW;AAAA,MACX,WAAU;AAAA,MAEV,UAAAA,2BAAAA,IAAC,OAAA,EAAI,WAAU,yFAAA,CAAyF;AAAA,IAAA;AAAA,EAAA,GAE5G;AAEJ;;;"}
|
package/dist/collab/client.cjs
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const receiveOnlySocket = require("../keryx-http/src/receive-only-socket.cjs");
|
|
4
|
+
const updateAttributions = require("../keryx-http/src/update-attributions.cjs");
|
|
3
5
|
const websocket = require("@y/websocket");
|
|
4
6
|
const Y = require("@y/y");
|
|
5
7
|
const closePolicy = require("./close-policy.cjs");
|
|
8
|
+
const documentStatus = require("./document-status.cjs");
|
|
6
9
|
const mint = require("./mint.cjs");
|
|
7
10
|
const tokenRefresh = require("./token-refresh.cjs");
|
|
8
11
|
function _interopNamespaceDefault(e) {
|
|
@@ -35,6 +38,15 @@ function resolveMint({ auth, mint: mint$1 }) {
|
|
|
35
38
|
if (!auth) throw new Error("connectGenericDoc needs `auth` or `mint`");
|
|
36
39
|
return ({ assetId, access }) => mint.mintCollabToken({ auth, assetId, access });
|
|
37
40
|
}
|
|
41
|
+
function socketFor({
|
|
42
|
+
grant,
|
|
43
|
+
doc
|
|
44
|
+
}) {
|
|
45
|
+
const Base = globalThis.WebSocket;
|
|
46
|
+
if (typeof Base !== "function") return void 0;
|
|
47
|
+
if (grant.access_type === "r") return receiveOnlySocket.receiveOnlyWebSocket({ Base });
|
|
48
|
+
return updateAttributions.attributingWebSocket({ Base, attributionsFor: () => updateAttributions.docUpdateAttributions(doc) });
|
|
49
|
+
}
|
|
38
50
|
function connectGenericDoc(args) {
|
|
39
51
|
const access = args.access ?? "view";
|
|
40
52
|
const mint2 = resolveMint({ auth: args.auth, mint: args.mint });
|
|
@@ -66,10 +78,19 @@ function connectGenericDoc(args) {
|
|
|
66
78
|
let connectSeq = 0;
|
|
67
79
|
let carriedUpdates = [];
|
|
68
80
|
let localChangesSynced = true;
|
|
81
|
+
let liveGrant = null;
|
|
82
|
+
let readStatusOnConnect = false;
|
|
69
83
|
const notify = () => {
|
|
70
84
|
version += 1;
|
|
71
85
|
for (const listener of listeners) listener();
|
|
72
86
|
};
|
|
87
|
+
const documentStatus$1 = args.readDocumentStatus ? documentStatus.watchDocumentStatus({
|
|
88
|
+
read: args.readDocumentStatus,
|
|
89
|
+
currentGrant: () => liveGrant,
|
|
90
|
+
onChange: () => {
|
|
91
|
+
if (!destroyed) notify();
|
|
92
|
+
}
|
|
93
|
+
}) : null;
|
|
73
94
|
const unconfirmedEdits = () => {
|
|
74
95
|
const all = [...carriedUpdates, ...(provider == null ? void 0 : provider.unconfirmedUpdates) ?? []].map(
|
|
75
96
|
(entry) => entry.ids
|
|
@@ -89,6 +110,7 @@ function connectGenericDoc(args) {
|
|
|
89
110
|
const next = carriedUpdates.length === 0 && ((provider == null ? void 0 : provider.unconfirmedUpdates.length) ?? 0) === 0;
|
|
90
111
|
const changed = next !== localChangesSynced;
|
|
91
112
|
localChangesSynced = next;
|
|
113
|
+
documentStatus$1 == null ? void 0 : documentStatus$1.unconfirmedChanged(!next);
|
|
92
114
|
transportChanged();
|
|
93
115
|
if (changed) notify();
|
|
94
116
|
};
|
|
@@ -109,8 +131,11 @@ function connectGenericDoc(args) {
|
|
|
109
131
|
everConnected = true;
|
|
110
132
|
disconnectedSince = null;
|
|
111
133
|
clearOfflineTimer();
|
|
112
|
-
} else
|
|
113
|
-
disconnectedSince
|
|
134
|
+
} else {
|
|
135
|
+
if (wasConnected || everConnected && disconnectedSince === null) {
|
|
136
|
+
disconnectedSince = Date.now();
|
|
137
|
+
}
|
|
138
|
+
documentStatus$1 == null ? void 0 : documentStatus$1.disconnected();
|
|
114
139
|
}
|
|
115
140
|
transportChanged();
|
|
116
141
|
notify();
|
|
@@ -254,6 +279,7 @@ function connectGenericDoc(args) {
|
|
|
254
279
|
teardownProvider();
|
|
255
280
|
}
|
|
256
281
|
if (destroyed || !connectionEnabled || seq !== connectSeq) return;
|
|
282
|
+
const socket = socketFor({ grant, doc });
|
|
257
283
|
const nextProvider = new websocket.WebsocketProvider(grant.ws_url, `${grant.org}/${grant.doc_id}`, doc, {
|
|
258
284
|
params: {
|
|
259
285
|
yauth: grant.token,
|
|
@@ -263,9 +289,11 @@ function connectGenericDoc(args) {
|
|
|
263
289
|
// BroadcastChannel would sync same-origin clients locally, bypassing the
|
|
264
290
|
// server's permission enforcement (a read-only tab could write into an
|
|
265
291
|
// editor tab's doc). Permissioned docs must round-trip the server.
|
|
266
|
-
disableBc: true
|
|
292
|
+
disableBc: true,
|
|
293
|
+
...socket && { WebSocketPolyfill: socket }
|
|
267
294
|
});
|
|
268
295
|
provider = nextProvider;
|
|
296
|
+
liveGrant = grant;
|
|
269
297
|
nextProvider.unconfirmedUpdates = [...carriedUpdates, ...nextProvider.unconfirmedUpdates];
|
|
270
298
|
carriedUpdates = [];
|
|
271
299
|
refreshLocalChangesSynced();
|
|
@@ -280,10 +308,13 @@ function connectGenericDoc(args) {
|
|
|
280
308
|
void connect();
|
|
281
309
|
return;
|
|
282
310
|
}
|
|
311
|
+
const readStatusNow = event.status === "connected" && (!everConnected || readStatusOnConnect || disconnectedSince !== null && Date.now() - disconnectedSince >= offlineGateAfterMs);
|
|
283
312
|
if (event.status === "connected") {
|
|
284
313
|
consecutiveRemints = 0;
|
|
314
|
+
readStatusOnConnect = false;
|
|
285
315
|
}
|
|
286
316
|
setStatus(event.status);
|
|
317
|
+
if (event.status === "connected") documentStatus$1 == null ? void 0 : documentStatus$1.connected({ readNow: readStatusNow });
|
|
287
318
|
if (event.status === "connected" && lastPresence !== null) {
|
|
288
319
|
nextProvider.awareness.setLocalState(lastPresence);
|
|
289
320
|
}
|
|
@@ -303,6 +334,8 @@ function connectGenericDoc(args) {
|
|
|
303
334
|
const action = closePolicy.classifyClose(event == null ? void 0 : event.code);
|
|
304
335
|
if (action === "remint") {
|
|
305
336
|
consecutiveRemints += 1;
|
|
337
|
+
readStatusOnConnect = true;
|
|
338
|
+
documentStatus$1 == null ? void 0 : documentStatus$1.disconnected();
|
|
306
339
|
teardownProvider();
|
|
307
340
|
if (consecutiveRemints > tokenRefresh.MAX_CONSECUTIVE_REMINTS) {
|
|
308
341
|
setStatus(
|
|
@@ -439,6 +472,9 @@ function connectGenericDoc(args) {
|
|
|
439
472
|
get version() {
|
|
440
473
|
return version;
|
|
441
474
|
},
|
|
475
|
+
get writesRefused() {
|
|
476
|
+
return (documentStatus$1 == null ? void 0 : documentStatus$1.writesRefused) ?? false;
|
|
477
|
+
},
|
|
442
478
|
waitForSync,
|
|
443
479
|
waitForAcknowledged,
|
|
444
480
|
getPresence: () => {
|
|
@@ -494,6 +530,7 @@ function connectGenericDoc(args) {
|
|
|
494
530
|
destroy: () => {
|
|
495
531
|
if (destroyed) return;
|
|
496
532
|
destroyed = true;
|
|
533
|
+
documentStatus$1 == null ? void 0 : documentStatus$1.destroy();
|
|
497
534
|
teardownProvider();
|
|
498
535
|
clearRetryTimer();
|
|
499
536
|
clearOfflineTimer();
|