@athenaintel/react 0.43.0 → 0.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +215 -3
- package/dist/agent-runtime/src/answer-label.cjs +137 -0
- package/dist/agent-runtime/src/answer-label.cjs.map +1 -0
- package/dist/agent-runtime/src/answer-label.d.ts +104 -0
- package/dist/agent-runtime/src/answer-label.js +137 -0
- package/dist/agent-runtime/src/answer-label.js.map +1 -0
- package/dist/agent-runtime/src/answer-rows.cjs +180 -0
- package/dist/agent-runtime/src/answer-rows.cjs.map +1 -0
- package/dist/agent-runtime/src/answer-rows.d.ts +86 -0
- package/dist/agent-runtime/src/answer-rows.js +180 -0
- package/dist/agent-runtime/src/answer-rows.js.map +1 -0
- package/dist/agent-runtime/src/client-tool-bridge.cjs +15 -15
- package/dist/agent-runtime/src/client-tool-bridge.cjs.map +1 -1
- package/dist/agent-runtime/src/conversation-index.cjs +8 -8
- package/dist/agent-runtime/src/conversation-index.cjs.map +1 -1
- package/dist/agent-runtime/src/decision-checks.cjs +207 -0
- package/dist/agent-runtime/src/decision-checks.cjs.map +1 -0
- package/dist/agent-runtime/src/decision-checks.d.ts +142 -0
- package/dist/agent-runtime/src/decision-checks.js +207 -0
- package/dist/agent-runtime/src/decision-checks.js.map +1 -0
- package/dist/agent-runtime/src/desktop-handoff.d.ts +12 -0
- package/dist/agent-runtime/src/errors.cjs +18 -0
- package/dist/agent-runtime/src/errors.cjs.map +1 -1
- package/dist/agent-runtime/src/errors.d.ts +7 -0
- package/dist/agent-runtime/src/errors.js +18 -0
- package/dist/agent-runtime/src/errors.js.map +1 -1
- package/dist/agent-runtime/src/generated/runconfig-contract.cjs +12 -0
- package/dist/agent-runtime/src/generated/runconfig-contract.cjs.map +1 -1
- package/dist/agent-runtime/src/generated/runconfig-contract.d.ts +6 -6
- package/dist/agent-runtime/src/generated/runconfig-contract.js +12 -0
- package/dist/agent-runtime/src/generated/runconfig-contract.js.map +1 -1
- package/dist/agent-runtime/src/handoff-arrival.cjs +60 -0
- package/dist/agent-runtime/src/handoff-arrival.cjs.map +1 -0
- package/dist/agent-runtime/src/handoff-arrival.d.ts +46 -0
- package/dist/agent-runtime/src/handoff-arrival.js +60 -0
- package/dist/agent-runtime/src/handoff-arrival.js.map +1 -0
- package/dist/agent-runtime/src/index.d.ts +14 -8
- package/dist/agent-runtime/src/interrupts.cjs +43 -18
- package/dist/agent-runtime/src/interrupts.cjs.map +1 -1
- package/dist/agent-runtime/src/interrupts.d.ts +19 -2
- package/dist/agent-runtime/src/interrupts.js +28 -3
- package/dist/agent-runtime/src/interrupts.js.map +1 -1
- package/dist/agent-runtime/src/lane-history.cjs +8 -8
- package/dist/agent-runtime/src/lane-history.cjs.map +1 -1
- package/dist/agent-runtime/src/messages.cjs +43 -8
- package/dist/agent-runtime/src/messages.cjs.map +1 -1
- package/dist/agent-runtime/src/messages.d.ts +25 -3
- package/dist/agent-runtime/src/messages.js +43 -8
- package/dist/agent-runtime/src/messages.js.map +1 -1
- package/dist/agent-runtime/src/offline-status.cjs +36 -0
- package/dist/agent-runtime/src/offline-status.cjs.map +1 -0
- package/dist/agent-runtime/src/offline-status.d.ts +118 -3
- package/dist/agent-runtime/src/offline-status.js +36 -0
- package/dist/agent-runtime/src/offline-status.js.map +1 -0
- package/dist/agent-runtime/src/queue.cjs +0 -9
- package/dist/agent-runtime/src/queue.cjs.map +1 -1
- package/dist/agent-runtime/src/queue.js +0 -9
- package/dist/agent-runtime/src/queue.js.map +1 -1
- package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs +9 -9
- package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs.map +1 -1
- package/dist/agent-runtime/src/runtime-catalog.cjs +42 -0
- package/dist/agent-runtime/src/runtime-catalog.cjs.map +1 -0
- package/dist/agent-runtime/src/runtime-catalog.d.ts +35 -0
- package/dist/agent-runtime/src/runtime-catalog.js +42 -0
- package/dist/agent-runtime/src/runtime-catalog.js.map +1 -0
- package/dist/agent-runtime/src/runtime-messages.cjs.map +1 -1
- package/dist/agent-runtime/src/runtime-messages.d.ts +1 -1
- package/dist/agent-runtime/src/runtime-messages.js.map +1 -1
- package/dist/agent-runtime/src/runtime.d.ts +40 -0
- package/dist/agent-runtime/src/statewire-suspended.cjs +3 -3
- package/dist/agent-runtime/src/statewire-suspended.cjs.map +1 -1
- package/dist/agent-runtime/src/subagents.cjs +32 -2
- package/dist/agent-runtime/src/subagents.cjs.map +1 -1
- package/dist/agent-runtime/src/subagents.d.ts +9 -0
- package/dist/agent-runtime/src/subagents.js +30 -0
- package/dist/agent-runtime/src/subagents.js.map +1 -1
- package/dist/agent-runtime/src/thread-driver.cjs +67 -0
- package/dist/agent-runtime/src/thread-driver.cjs.map +1 -0
- package/dist/agent-runtime/src/thread-driver.d.ts +49 -0
- package/dist/agent-runtime/src/thread-driver.js +67 -0
- package/dist/agent-runtime/src/thread-driver.js.map +1 -0
- package/dist/agent-runtime/src/thread-handoff-flow-machine.d.ts +172 -0
- package/dist/agent-runtime/src/thread-handoff-protocol.d.ts +756 -0
- package/dist/agent-runtime/src/thread-handoff-qr.d.ts +11 -0
- package/dist/agent-runtime/src/thread-handoff.d.ts +3 -364
- package/dist/agent-runtime/src/thread-status.cjs +3 -3
- package/dist/agent-runtime/src/thread-status.cjs.map +1 -1
- package/dist/agent-runtime/src/tool-metadata.cjs +210 -25
- package/dist/agent-runtime/src/tool-metadata.cjs.map +1 -1
- package/dist/agent-runtime/src/tool-metadata.d.ts +12 -0
- package/dist/agent-runtime/src/tool-metadata.js +210 -25
- package/dist/agent-runtime/src/tool-metadata.js.map +1 -1
- package/dist/agent-runtime/src/tool-names.cjs +2 -0
- package/dist/agent-runtime/src/tool-names.cjs.map +1 -1
- package/dist/agent-runtime/src/tool-names.d.ts +2 -0
- package/dist/agent-runtime/src/tool-names.js +2 -0
- package/dist/agent-runtime/src/tool-names.js.map +1 -1
- package/dist/agent-runtime/src/types.d.ts +10 -2
- package/dist/agent-runtime/src/use-conversation-list.cjs +11 -11
- package/dist/agent-runtime/src/use-conversation-list.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.cjs +24 -19
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.d.ts +2 -1
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.js +6 -1
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.js.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-config.cjs +14 -14
- package/dist/agent-runtime/src/use-deep-agent-config.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-edit-submit.cjs +6 -6
- package/dist/agent-runtime/src/use-deep-agent-edit-submit.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-runtime.cjs +16 -16
- package/dist/agent-runtime/src/use-deep-agent-runtime.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-thread.cjs +45 -45
- package/dist/agent-runtime/src/use-deep-agent-thread.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-voice.cjs +547 -124
- package/dist/agent-runtime/src/use-deep-agent-voice.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-voice.d.ts +129 -10
- package/dist/agent-runtime/src/use-deep-agent-voice.js +487 -64
- package/dist/agent-runtime/src/use-deep-agent-voice.js.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-window-sync.cjs +26 -26
- package/dist/agent-runtime/src/use-deep-agent-window-sync.cjs.map +1 -1
- package/dist/agent-runtime/src/use-historical-edit-attachments.cjs +4 -4
- package/dist/agent-runtime/src/use-historical-edit-attachments.cjs.map +1 -1
- package/dist/agent-runtime/src/use-thread-handoff-flow.d.ts +28 -26
- package/dist/agent-runtime/src/voice-media.cjs +117 -0
- package/dist/agent-runtime/src/voice-media.cjs.map +1 -0
- package/dist/agent-runtime/src/voice-media.d.ts +49 -0
- package/dist/agent-runtime/src/voice-media.js +117 -0
- package/dist/agent-runtime/src/voice-media.js.map +1 -0
- package/dist/agent-runtime/src/voice-wire-types.d.ts +32 -0
- package/dist/assets/AssetPanel.cjs +11 -11
- package/dist/assets/AssetPanel.cjs.map +1 -1
- package/dist/assets/AthenaAssetEmbed.cjs +11 -9
- package/dist/assets/AthenaAssetEmbed.cjs.map +1 -1
- package/dist/assets/AthenaAssetEmbed.d.ts +7 -0
- package/dist/assets/AthenaAssetEmbed.js +4 -2
- package/dist/assets/AthenaAssetEmbed.js.map +1 -1
- package/dist/assets/AthenaLayout.cjs +16 -16
- package/dist/assets/AthenaLayout.cjs.map +1 -1
- package/dist/assets/use-asset-content.cjs +4 -4
- package/dist/assets/use-asset-content.cjs.map +1 -1
- package/dist/assets/use-asset-embed.cjs +14 -7
- package/dist/assets/use-asset-embed.cjs.map +1 -1
- package/dist/assets/use-asset-embed.d.ts +11 -1
- package/dist/assets/use-asset-embed.js +10 -3
- package/dist/assets/use-asset-embed.js.map +1 -1
- package/dist/auth/AthenaAuthContext.cjs +3 -3
- package/dist/auth/AthenaAuthContext.cjs.map +1 -1
- package/dist/auth/AthenaAuthProvider.cjs +8 -8
- package/dist/auth/AthenaAuthProvider.cjs.map +1 -1
- package/dist/auth/AthenaCredentialSourceContext.cjs +5 -5
- package/dist/auth/AthenaCredentialSourceContext.cjs.map +1 -1
- package/dist/auth/AthenaSSOProvider.cjs +14 -14
- package/dist/auth/AthenaSSOProvider.cjs.map +1 -1
- package/dist/auth/credential-source.cjs +26 -13
- package/dist/auth/credential-source.cjs.map +1 -1
- package/dist/auth/credential-source.d.ts +8 -0
- package/dist/auth/credential-source.js +26 -13
- package/dist/auth/credential-source.js.map +1 -1
- package/dist/catalog/agent-model-options.cjs +25 -17
- package/dist/catalog/agent-model-options.cjs.map +1 -1
- package/dist/catalog/agent-model-options.d.ts +38 -5
- package/dist/catalog/agent-model-options.js +25 -17
- package/dist/catalog/agent-model-options.js.map +1 -1
- package/dist/catalog/channel-refusal.cjs +36 -0
- package/dist/catalog/channel-refusal.cjs.map +1 -0
- package/dist/catalog/channel-refusal.d.ts +29 -0
- package/dist/catalog/channel-refusal.js +36 -0
- package/dist/catalog/channel-refusal.js.map +1 -0
- package/dist/catalog/chat-pickers.cjs +60 -24
- package/dist/catalog/chat-pickers.cjs.map +1 -1
- package/dist/catalog/chat-pickers.d.ts +12 -2
- package/dist/catalog/chat-pickers.js +56 -20
- package/dist/catalog/chat-pickers.js.map +1 -1
- package/dist/catalog/runtime-catalog.cjs +89 -23
- package/dist/catalog/runtime-catalog.cjs.map +1 -1
- package/dist/catalog/runtime-catalog.d.ts +8 -2
- package/dist/catalog/runtime-catalog.js +83 -17
- package/dist/catalog/runtime-catalog.js.map +1 -1
- package/dist/catalog/use-athena-chat-mode.cjs +12 -12
- package/dist/catalog/use-athena-chat-mode.cjs.map +1 -1
- package/dist/chat/AthenaChat.cjs +155 -67
- package/dist/chat/AthenaChat.cjs.map +1 -1
- package/dist/chat/AthenaChat.d.ts +42 -2
- package/dist/chat/AthenaChat.js +106 -18
- package/dist/chat/AthenaChat.js.map +1 -1
- package/dist/chat/AthenaChatErrorBoundary.cjs +3 -3
- package/dist/chat/AthenaChatErrorBoundary.cjs.map +1 -1
- package/dist/chat/DrivingOnChip.cjs +23 -0
- package/dist/chat/DrivingOnChip.cjs.map +1 -0
- package/dist/chat/DrivingOnChip.d.ts +17 -0
- package/dist/chat/DrivingOnChip.js +23 -0
- package/dist/chat/DrivingOnChip.js.map +1 -0
- package/dist/chat/StatewireApprovalCard.cjs +125 -31
- package/dist/chat/StatewireApprovalCard.cjs.map +1 -1
- package/dist/chat/StatewireApprovalCard.d.ts +73 -1
- package/dist/chat/StatewireApprovalCard.js +115 -21
- package/dist/chat/StatewireApprovalCard.js.map +1 -1
- package/dist/chat/StatewireClientToolBridge.cjs +2 -2
- package/dist/chat/StatewireClientToolBridge.cjs.map +1 -1
- package/dist/chat/StatewireQueuedMessages.cjs +25 -63
- package/dist/chat/StatewireQueuedMessages.cjs.map +1 -1
- package/dist/chat/StatewireQueuedMessages.d.ts +11 -13
- package/dist/chat/StatewireQueuedMessages.js +16 -54
- package/dist/chat/StatewireQueuedMessages.js.map +1 -1
- package/dist/chat/WaitingOnYouBanner.cjs +3 -3
- package/dist/chat/WaitingOnYouBanner.cjs.map +1 -1
- package/dist/chat/athena-chat-welcome.cjs +2 -2
- package/dist/chat/athena-chat-welcome.cjs.map +1 -1
- package/dist/chat/athena-citation-links.cjs +5 -5
- package/dist/chat/athena-citation-links.cjs.map +1 -1
- package/dist/chat/athena-composer-controls.cjs +26 -16
- package/dist/chat/athena-composer-controls.cjs.map +1 -1
- package/dist/chat/athena-composer-controls.d.ts +6 -0
- package/dist/chat/athena-composer-controls.js +26 -16
- package/dist/chat/athena-composer-controls.js.map +1 -1
- package/dist/chat/athena-turn-end-status.cjs +42 -0
- package/dist/chat/athena-turn-end-status.cjs.map +1 -0
- package/dist/chat/athena-turn-end-status.d.ts +24 -0
- package/dist/chat/athena-turn-end-status.js +42 -0
- package/dist/chat/athena-turn-end-status.js.map +1 -0
- package/dist/chat/browser-decision-check.cjs +131 -0
- package/dist/chat/browser-decision-check.cjs.map +1 -0
- package/dist/chat/browser-decision-check.d.ts +61 -0
- package/dist/chat/browser-decision-check.js +131 -0
- package/dist/chat/browser-decision-check.js.map +1 -0
- package/dist/chat/chat-outbox-rows.cjs +3 -3
- package/dist/chat/chat-outbox-rows.cjs.map +1 -1
- package/dist/chat/chat-voice-controls.cjs +93 -28
- package/dist/chat/chat-voice-controls.cjs.map +1 -1
- package/dist/chat/chat-voice-controls.d.ts +36 -2
- package/dist/chat/chat-voice-controls.js +89 -24
- package/dist/chat/chat-voice-controls.js.map +1 -1
- package/dist/chat/composer-keyboard-hint.cjs +5 -5
- package/dist/chat/composer-keyboard-hint.cjs.map +1 -1
- package/dist/chat/device-operation.cjs +29 -0
- package/dist/chat/device-operation.cjs.map +1 -0
- package/dist/chat/device-operation.d.ts +34 -0
- package/dist/chat/device-operation.js +29 -0
- package/dist/chat/device-operation.js.map +1 -0
- package/dist/chat/super-grouping/CollapsibleGroup.cjs +14 -14
- package/dist/chat/super-grouping/CollapsibleGroup.cjs.map +1 -1
- package/dist/chat/super-grouping/GroupedMessageParts.cjs +4 -4
- package/dist/chat/super-grouping/GroupedMessageParts.cjs.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingCard.cjs +52 -36
- package/dist/chat/super-grouping/SuperGroupingCard.cjs.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingCard.d.ts +19 -4
- package/dist/chat/super-grouping/SuperGroupingCard.js +29 -13
- package/dist/chat/super-grouping/SuperGroupingCard.js.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingTranscript.cjs +32 -32
- package/dist/chat/super-grouping/SuperGroupingTranscript.cjs.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingTranscript.js +3 -3
- package/dist/chat/super-grouping/SuperGroupingTranscript.js.map +1 -1
- package/dist/chat/super-grouping/ToolTimeline.cjs +73 -40
- package/dist/chat/super-grouping/ToolTimeline.cjs.map +1 -1
- package/dist/chat/super-grouping/ToolTimeline.d.ts +10 -2
- package/dist/chat/super-grouping/ToolTimeline.js +69 -36
- package/dist/chat/super-grouping/ToolTimeline.js.map +1 -1
- package/dist/chat/super-grouping/activity-timeline.cjs +47 -12
- package/dist/chat/super-grouping/activity-timeline.cjs.map +1 -1
- package/dist/chat/super-grouping/activity-timeline.d.ts +21 -0
- package/dist/chat/super-grouping/activity-timeline.js +47 -12
- package/dist/chat/super-grouping/activity-timeline.js.map +1 -1
- package/dist/chat/super-grouping/grouping-function.cjs +4 -0
- package/dist/chat/super-grouping/grouping-function.cjs.map +1 -1
- package/dist/chat/super-grouping/grouping-function.d.ts +7 -0
- package/dist/chat/super-grouping/grouping-function.js +5 -1
- package/dist/chat/super-grouping/grouping-function.js.map +1 -1
- package/dist/chat/super-grouping/index.cjs +6 -0
- package/dist/chat/super-grouping/index.cjs.map +1 -1
- package/dist/chat/super-grouping/index.d.ts +5 -2
- package/dist/chat/super-grouping/index.js +7 -1
- package/dist/chat/super-grouping/index.js.map +1 -1
- package/dist/chat/super-grouping/tool-part-placement.cjs +17 -0
- package/dist/chat/super-grouping/tool-part-placement.cjs.map +1 -0
- package/dist/chat/super-grouping/tool-part-placement.d.ts +22 -0
- package/dist/chat/super-grouping/tool-part-placement.js +17 -0
- package/dist/chat/super-grouping/tool-part-placement.js.map +1 -0
- package/dist/chat/thread-scroll-to-bottom.cjs +2 -2
- package/dist/chat/thread-scroll-to-bottom.cjs.map +1 -1
- package/dist/chat/thread-scroll-to-bottom.d.ts +10 -7
- package/dist/chat/thread-scroll-to-bottom.js +2 -2
- package/dist/chat/thread-scroll-to-bottom.js.map +1 -1
- package/dist/chat/tooltip-icon-button.cjs +2 -2
- package/dist/chat/tooltip-icon-button.cjs.map +1 -1
- package/dist/chat/use-athena-voice-live.cjs +11 -0
- package/dist/chat/use-athena-voice-live.cjs.map +1 -0
- package/dist/chat/use-athena-voice-live.d.ts +11 -0
- package/dist/chat/use-athena-voice-live.js +11 -0
- package/dist/chat/use-athena-voice-live.js.map +1 -0
- package/dist/chat/use-statewire-approval-request.cjs +56 -24
- package/dist/chat/use-statewire-approval-request.cjs.map +1 -1
- package/dist/chat/use-statewire-approval-request.d.ts +33 -4
- package/dist/chat/use-statewire-approval-request.js +41 -9
- package/dist/chat/use-statewire-approval-request.js.map +1 -1
- package/dist/chat-ui/auth/sign-in-card.cjs +2 -2
- package/dist/chat-ui/auth/sign-in-card.cjs.map +1 -1
- package/dist/chat-ui/composer/tiptap-composer.cjs +138 -107
- package/dist/chat-ui/composer/tiptap-composer.cjs.map +1 -1
- package/dist/chat-ui/composer/tiptap-composer.d.ts +20 -4
- package/dist/chat-ui/composer/tiptap-composer.js +85 -54
- package/dist/chat-ui/composer/tiptap-composer.js.map +1 -1
- package/dist/chat-ui/header/conversation-history-panel.cjs +49 -23
- package/dist/chat-ui/header/conversation-history-panel.cjs.map +1 -1
- package/dist/chat-ui/header/conversation-history-panel.d.ts +12 -1
- package/dist/chat-ui/header/conversation-history-panel.js +38 -12
- package/dist/chat-ui/header/conversation-history-panel.js.map +1 -1
- package/dist/chat-ui/index.cjs +18 -0
- package/dist/chat-ui/index.cjs.map +1 -1
- package/dist/chat-ui/index.d.ts +7 -1
- package/dist/chat-ui/index.js +18 -0
- package/dist/chat-ui/index.js.map +1 -1
- package/dist/chat-ui/mentions/mention-chip.cjs +4 -4
- package/dist/chat-ui/mentions/mention-chip.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.cjs +10 -9
- package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.js +3 -2
- package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-list.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-popup.cjs +2 -2
- package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-popup.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/menu-list.cjs +29 -6
- package/dist/chat-ui/mentions/suggestions/components/menu-list.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/menu-list.d.ts +7 -1
- package/dist/chat-ui/mentions/suggestions/components/menu-list.js +25 -2
- package/dist/chat-ui/mentions/suggestions/components/menu-list.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/use-keyboard-navigation.cjs +2 -2
- package/dist/chat-ui/mentions/suggestions/components/use-keyboard-navigation.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/use-menu-navigation.cjs +2 -2
- package/dist/chat-ui/mentions/suggestions/components/use-menu-navigation.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/api-client.cjs +3 -3
- package/dist/chat-ui/mentions/suggestions/data/api-client.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/orchestrator.cjs +56 -2
- package/dist/chat-ui/mentions/suggestions/data/orchestrator.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/orchestrator.d.ts +12 -0
- package/dist/chat-ui/mentions/suggestions/data/orchestrator.js +56 -2
- package/dist/chat-ui/mentions/suggestions/data/orchestrator.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs +24 -3
- package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/sources/index.d.ts +7 -0
- package/dist/chat-ui/mentions/suggestions/data/sources/index.js +24 -3
- package/dist/chat-ui/mentions/suggestions/data/sources/index.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.cjs +35 -13
- package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.d.ts +15 -1
- package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.js +28 -6
- package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/use-menu-items.cjs +9 -6
- package/dist/chat-ui/mentions/suggestions/data/use-menu-items.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/use-menu-items.d.ts +3 -0
- package/dist/chat-ui/mentions/suggestions/data/use-menu-items.js +5 -2
- package/dist/chat-ui/mentions/suggestions/data/use-menu-items.js.map +1 -1
- package/dist/chat-ui/mentions/use-account-workspace-id.cjs +45 -10
- package/dist/chat-ui/mentions/use-account-workspace-id.cjs.map +1 -1
- package/dist/chat-ui/mentions/use-account-workspace-id.d.ts +24 -1
- package/dist/chat-ui/mentions/use-account-workspace-id.js +46 -11
- package/dist/chat-ui/mentions/use-account-workspace-id.js.map +1 -1
- package/dist/chat-ui/mentions/use-member-avatar.cjs +4 -4
- package/dist/chat-ui/mentions/use-member-avatar.cjs.map +1 -1
- package/dist/chat-ui/mentions/use-mention-asset.cjs +3 -3
- package/dist/chat-ui/mentions/use-mention-asset.cjs.map +1 -1
- package/dist/chat-ui/messages/answer-label.cjs +42 -0
- package/dist/chat-ui/messages/answer-label.cjs.map +1 -0
- package/dist/chat-ui/messages/answer-label.d.ts +33 -0
- package/dist/chat-ui/messages/answer-label.js +42 -0
- package/dist/chat-ui/messages/answer-label.js.map +1 -0
- package/dist/chat-ui/messages/arrival-animation.cjs +13 -0
- package/dist/chat-ui/messages/arrival-animation.cjs.map +1 -0
- package/dist/chat-ui/messages/arrival-animation.d.ts +14 -0
- package/dist/chat-ui/messages/arrival-animation.js +13 -0
- package/dist/chat-ui/messages/arrival-animation.js.map +1 -0
- package/dist/chat-ui/messages/continue-pill.cjs +5 -5
- package/dist/chat-ui/messages/continue-pill.cjs.map +1 -1
- package/dist/chat-ui/messages/handoff-arrival-divider.cjs +44 -0
- package/dist/chat-ui/messages/handoff-arrival-divider.cjs.map +1 -0
- package/dist/chat-ui/messages/handoff-arrival-divider.d.ts +17 -0
- package/dist/chat-ui/messages/handoff-arrival-divider.js +44 -0
- package/dist/chat-ui/messages/handoff-arrival-divider.js.map +1 -0
- package/dist/chat-ui/messages/message-actions-config.cjs +3 -3
- package/dist/chat-ui/messages/message-actions-config.cjs.map +1 -1
- package/dist/chat-ui/messages/message-components.cjs +8 -4
- package/dist/chat-ui/messages/message-components.cjs.map +1 -1
- package/dist/chat-ui/messages/message-components.js +5 -1
- package/dist/chat-ui/messages/message-components.js.map +1 -1
- package/dist/chat-ui/messages/message-images.cjs +66 -0
- package/dist/chat-ui/messages/message-images.cjs.map +1 -0
- package/dist/chat-ui/messages/message-images.d.ts +16 -0
- package/dist/chat-ui/messages/message-images.js +66 -0
- package/dist/chat-ui/messages/message-images.js.map +1 -0
- package/dist/chat-ui/messages/user-edit-composer.cjs +2 -2
- package/dist/chat-ui/messages/user-edit-composer.cjs.map +1 -1
- package/dist/chat-ui/messages/wake-marker.cjs +3 -3
- package/dist/chat-ui/messages/wake-marker.cjs.map +1 -1
- package/dist/chat-ui/rich-text/chat-link.cjs +2 -2
- package/dist/chat-ui/rich-text/chat-link.cjs.map +1 -1
- package/dist/chat-ui/rich-text/chat-message-body.cjs +8 -8
- package/dist/chat-ui/rich-text/chat-message-body.cjs.map +1 -1
- package/dist/chat-ui/rich-text/chat-node-views.cjs +6 -6
- package/dist/chat-ui/rich-text/chat-node-views.cjs.map +1 -1
- package/dist/chat-ui/rich-text/dom-output-spec.cjs +2 -2
- package/dist/chat-ui/rich-text/dom-output-spec.cjs.map +1 -1
- package/dist/chat-ui/statewire.cjs +3 -0
- package/dist/chat-ui/statewire.cjs.map +1 -1
- package/dist/chat-ui/statewire.d.ts +2 -1
- package/dist/chat-ui/statewire.js +3 -0
- package/dist/chat-ui/statewire.js.map +1 -1
- package/dist/chat-ui/thread/chat-thread-shell.cjs +43 -14
- package/dist/chat-ui/thread/chat-thread-shell.cjs.map +1 -1
- package/dist/chat-ui/thread/chat-thread-shell.d.ts +16 -2
- package/dist/chat-ui/thread/chat-thread-shell.js +35 -6
- package/dist/chat-ui/thread/chat-thread-shell.js.map +1 -1
- package/dist/chat-ui/thread/composer-send-or-stop.cjs +30 -20
- package/dist/chat-ui/thread/composer-send-or-stop.cjs.map +1 -1
- package/dist/chat-ui/thread/composer-send-or-stop.d.ts +8 -0
- package/dist/chat-ui/thread/composer-send-or-stop.js +29 -19
- package/dist/chat-ui/thread/composer-send-or-stop.js.map +1 -1
- package/dist/chat-ui/thread/statewire-history-edge.cjs +20 -21
- package/dist/chat-ui/thread/statewire-history-edge.cjs.map +1 -1
- package/dist/chat-ui/thread/statewire-history-edge.js +3 -4
- package/dist/chat-ui/thread/statewire-history-edge.js.map +1 -1
- package/dist/chat-ui/thread/thread-loading-overlay.cjs +5 -5
- package/dist/chat-ui/thread/thread-loading-overlay.cjs.map +1 -1
- package/dist/collab/client.cjs +40 -3
- package/dist/collab/client.cjs.map +1 -1
- package/dist/collab/client.d.ts +25 -0
- package/dist/collab/client.js +40 -3
- package/dist/collab/client.js.map +1 -1
- package/dist/collab/document-status.cjs +150 -0
- package/dist/collab/document-status.cjs.map +1 -0
- package/dist/collab/document-status.d.ts +68 -0
- package/dist/collab/document-status.js +150 -0
- package/dist/collab/document-status.js.map +1 -0
- package/dist/collab/index.cjs +7 -0
- package/dist/collab/index.cjs.map +1 -1
- package/dist/collab/index.d.ts +6 -1
- package/dist/collab/index.js +7 -0
- package/dist/collab/index.js.map +1 -1
- package/dist/collab/presence-react.cjs +11 -11
- package/dist/collab/presence-react.cjs.map +1 -1
- package/dist/collab/react.cjs +6 -6
- package/dist/collab/react.cjs.map +1 -1
- package/dist/composer/AttachmentContext.cjs +24 -11
- package/dist/composer/AttachmentContext.cjs.map +1 -1
- package/dist/composer/AttachmentContext.js +18 -5
- package/dist/composer/AttachmentContext.js.map +1 -1
- package/dist/composer/ComposerAttachmentPreview.cjs +78 -23
- package/dist/composer/ComposerAttachmentPreview.cjs.map +1 -1
- package/dist/composer/ComposerAttachmentPreview.d.ts +5 -3
- package/dist/composer/ComposerAttachmentPreview.js +79 -24
- package/dist/composer/ComposerAttachmentPreview.js.map +1 -1
- package/dist/composer/ComposerDropZone.cjs +7 -7
- package/dist/composer/ComposerDropZone.cjs.map +1 -1
- package/dist/composer/FileUploadButton.cjs +37 -22
- package/dist/composer/FileUploadButton.cjs.map +1 -1
- package/dist/composer/FileUploadButton.d.ts +6 -0
- package/dist/composer/FileUploadButton.js +34 -19
- package/dist/composer/FileUploadButton.js.map +1 -1
- package/dist/composer/QuoteContext.cjs +8 -8
- package/dist/composer/QuoteContext.cjs.map +1 -1
- package/dist/composer/composer-handoff.cjs +4 -4
- package/dist/composer/composer-handoff.cjs.map +1 -1
- package/dist/composer/useAppendToComposer.cjs +4 -4
- package/dist/composer/useAppendToComposer.cjs.map +1 -1
- package/dist/composer/useAttachFiles.cjs +23 -6
- package/dist/composer/useAttachFiles.cjs.map +1 -1
- package/dist/composer/useAttachFiles.d.ts +15 -7
- package/dist/composer/useAttachFiles.js +22 -5
- package/dist/composer/useAttachFiles.js.map +1 -1
- package/dist/composer/useComposerAttachment.cjs +4 -4
- package/dist/composer/useComposerAttachment.cjs.map +1 -1
- package/dist/composer/useFileUpload.cjs +21 -16
- package/dist/composer/useFileUpload.cjs.map +1 -1
- package/dist/composer/useFileUpload.d.ts +12 -0
- package/dist/composer/useFileUpload.js +12 -7
- package/dist/composer/useFileUpload.js.map +1 -1
- package/dist/composer/useReadComposerDraft.cjs +2 -2
- package/dist/composer/useReadComposerDraft.cjs.map +1 -1
- package/dist/composer/useSendMessage.cjs +4 -4
- package/dist/composer/useSendMessage.cjs.map +1 -1
- package/dist/diagnostics/useAthenaDiagnostics.cjs +4 -4
- package/dist/diagnostics/useAthenaDiagnostics.cjs.map +1 -1
- package/dist/dictation/audio-level-history.cjs +3 -3
- package/dist/dictation/audio-level-history.cjs.map +1 -1
- package/dist/dictation/dictation-controls.cjs +24 -20
- package/dist/dictation/dictation-controls.cjs.map +1 -1
- package/dist/dictation/dictation-controls.d.ts +6 -1
- package/dist/dictation/dictation-controls.js +24 -20
- package/dist/dictation/dictation-controls.js.map +1 -1
- package/dist/dictation/use-athena-dictation-engine.cjs +3 -3
- package/dist/dictation/use-athena-dictation-engine.cjs.map +1 -1
- package/dist/dictation/use-dictation.cjs +22 -22
- package/dist/dictation/use-dictation.cjs.map +1 -1
- package/dist/index.cjs +26 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +15 -3
- package/dist/index.js +26 -2
- package/dist/index.js.map +1 -1
- package/dist/keryx-http/src/receive-only-socket.cjs +40 -0
- package/dist/keryx-http/src/receive-only-socket.cjs.map +1 -0
- package/dist/keryx-http/src/receive-only-socket.d.ts +27 -0
- package/dist/keryx-http/src/receive-only-socket.js +40 -0
- package/dist/keryx-http/src/receive-only-socket.js.map +1 -0
- package/dist/keryx-http/src/update-attributions.cjs +111 -0
- package/dist/keryx-http/src/update-attributions.cjs.map +1 -0
- package/dist/keryx-http/src/update-attributions.d.ts +75 -0
- package/dist/keryx-http/src/update-attributions.js +111 -0
- package/dist/keryx-http/src/update-attributions.js.map +1 -0
- package/dist/lib/owner-document.cjs +6 -6
- package/dist/lib/owner-document.cjs.map +1 -1
- package/dist/lib/use-athena-rest-query.cjs +4 -4
- package/dist/lib/use-athena-rest-query.cjs.map +1 -1
- package/dist/lib/use-document-active.cjs +4 -4
- package/dist/lib/use-document-active.cjs.map +1 -1
- package/dist/lib/use-prefers-reduced-motion.cjs +2 -2
- package/dist/lib/use-prefers-reduced-motion.cjs.map +1 -1
- package/dist/offline/offline-history.cjs +7 -7
- package/dist/offline/offline-history.cjs.map +1 -1
- package/dist/provider/AthenaContext.cjs +3 -3
- package/dist/provider/AthenaContext.cjs.map +1 -1
- package/dist/provider/AthenaProvider.cjs +116 -79
- package/dist/provider/AthenaProvider.cjs.map +1 -1
- package/dist/provider/AthenaProvider.js +40 -3
- package/dist/provider/AthenaProvider.js.map +1 -1
- package/dist/provider/PostHogProvider.cjs +2 -2
- package/dist/provider/PostHogProvider.cjs.map +1 -1
- package/dist/provider/agent-selection-context.cjs +2 -2
- package/dist/provider/agent-selection-context.cjs.map +1 -1
- package/dist/provider/chat-mode-context.cjs +2 -2
- package/dist/provider/chat-mode-context.cjs.map +1 -1
- package/dist/provider/session-persistence-context.cjs +10 -0
- package/dist/provider/session-persistence-context.cjs.map +1 -0
- package/dist/provider/session-persistence-context.d.ts +15 -0
- package/dist/provider/session-persistence-context.js +10 -0
- package/dist/provider/session-persistence-context.js.map +1 -0
- package/dist/provider/statewire-history-context.cjs +4 -4
- package/dist/provider/statewire-history-context.cjs.map +1 -1
- package/dist/provider/statewire-lifecycle-context.cjs +3 -3
- package/dist/provider/statewire-lifecycle-context.cjs.map +1 -1
- package/dist/provider/statewire-window-context.cjs +3 -3
- package/dist/provider/statewire-window-context.cjs.map +1 -1
- package/dist/provider/theme-style-context.cjs +3 -3
- package/dist/provider/theme-style-context.cjs.map +1 -1
- package/dist/react/package.json.cjs +1 -1
- package/dist/react/package.json.js +1 -1
- package/dist/runtime/StatewireThreadConfigLaneSync.cjs +10 -10
- package/dist/runtime/StatewireThreadConfigLaneSync.cjs.map +1 -1
- package/dist/runtime/auth-refusal-restart.cjs +7 -7
- package/dist/runtime/auth-refusal-restart.cjs.map +1 -1
- package/dist/runtime/auth.cjs +13 -13
- package/dist/runtime/auth.cjs.map +1 -1
- package/dist/runtime/statewire-lifecycle.cjs +1 -0
- package/dist/runtime/statewire-lifecycle.cjs.map +1 -1
- package/dist/runtime/statewire-lifecycle.d.ts +3 -1
- package/dist/runtime/statewire-lifecycle.js +2 -1
- package/dist/runtime/statewire-lifecycle.js.map +1 -1
- package/dist/runtime/statewire-server-lane-context.cjs +2 -2
- package/dist/runtime/statewire-server-lane-context.cjs.map +1 -1
- package/dist/runtime/statewire-session-lane.cjs +4 -4
- package/dist/runtime/statewire-session-lane.cjs.map +1 -1
- package/dist/runtime/useAthenaStatewireRuntime.cjs +10 -8
- package/dist/runtime/useAthenaStatewireRuntime.cjs.map +1 -1
- package/dist/runtime/useAthenaStatewireRuntime.d.ts +2 -0
- package/dist/runtime/useAthenaStatewireRuntime.js +2 -0
- package/dist/runtime/useAthenaStatewireRuntime.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/threads/Inbox.cjs +8 -8
- package/dist/threads/Inbox.cjs.map +1 -1
- package/dist/threads/SessionList.cjs +9 -9
- package/dist/threads/SessionList.cjs.map +1 -1
- package/dist/threads/SessionsPage.cjs +11 -11
- package/dist/threads/SessionsPage.cjs.map +1 -1
- package/dist/threads/index-triggered-refresh.cjs +10 -10
- package/dist/threads/index-triggered-refresh.cjs.map +1 -1
- package/dist/threads/mark-viewed-thread-read.cjs +12 -12
- package/dist/threads/mark-viewed-thread-read.cjs.map +1 -1
- package/dist/threads/offline-session-list.cjs +3 -3
- package/dist/threads/offline-session-list.cjs.map +1 -1
- package/dist/threads/session-list-tab-share.cjs +5 -5
- package/dist/threads/session-list-tab-share.cjs.map +1 -1
- package/dist/threads/statewire-thread-list.cjs +51 -51
- package/dist/threads/statewire-thread-list.cjs.map +1 -1
- package/dist/threads/thread-id-context.cjs +5 -5
- package/dist/threads/thread-id-context.cjs.map +1 -1
- package/dist/threads/use-athena-session-attention.cjs +2 -2
- package/dist/threads/use-athena-session-attention.cjs.map +1 -1
- package/dist/threads/use-athena-sessions.cjs +10 -10
- package/dist/threads/use-athena-sessions.cjs.map +1 -1
- package/dist/threads/use-athena-thread-model.cjs +3 -3
- package/dist/threads/use-athena-thread-model.cjs.map +1 -1
- package/dist/threads/use-rest-conversation-history.cjs +3 -3
- package/dist/threads/use-rest-conversation-history.cjs.map +1 -1
- package/dist/threads/use-statewire-conversation-history.cjs +8 -8
- package/dist/threads/use-statewire-conversation-history.cjs.map +1 -1
- package/dist/threads/use-thread-archive.cjs +9 -9
- package/dist/threads/use-thread-archive.cjs.map +1 -1
- package/dist/threads/use-thread-favorite.cjs +2 -2
- package/dist/threads/use-thread-favorite.cjs.map +1 -1
- package/dist/threads/use-thread-field-override.cjs +20 -20
- package/dist/threads/use-thread-field-override.cjs.map +1 -1
- package/dist/threads/use-thread-read-state.cjs +4 -4
- package/dist/threads/use-thread-read-state.cjs.map +1 -1
- package/dist/threads/use-thread-rename.cjs +2 -2
- package/dist/threads/use-thread-rename.cjs.map +1 -1
- package/dist/threads/useAthenaThreadManager.cjs +2 -2
- package/dist/threads/useAthenaThreadManager.cjs.map +1 -1
- package/dist/tools/NestedPtcMessages.cjs +6 -6
- package/dist/tools/NestedPtcMessages.cjs.map +1 -1
- package/dist/tools/append-document-tool-ui.cjs +7 -7
- package/dist/tools/append-document-tool-ui.cjs.map +1 -1
- package/dist/tools/file-tool-uis.cjs +2 -2
- package/dist/tools/file-tool-uis.cjs.map +1 -1
- package/dist/tools/misc-tool-uis.cjs +2 -2
- package/dist/tools/misc-tool-uis.cjs.map +1 -1
- package/dist/tools/primitives.cjs +6 -6
- package/dist/tools/primitives.cjs.map +1 -1
- package/dist/tools/read-asset-tool-ui.cjs +6 -6
- package/dist/tools/read-asset-tool-ui.cjs.map +1 -1
- package/dist/tools/subagent-task-tool-ui.cjs +21 -21
- package/dist/tools/subagent-task-tool-ui.cjs.map +1 -1
- package/dist/tools/test-recording-tool-uis.cjs +16 -16
- package/dist/tools/test-recording-tool-uis.cjs.map +1 -1
- package/dist/tools/todo-plan-store.cjs +4 -4
- package/dist/tools/todo-plan-store.cjs.map +1 -1
- package/dist/tools/tool-appearance.cjs +3 -3
- package/dist/tools/tool-appearance.cjs.map +1 -1
- package/dist/tools/tool-fallback.cjs +14 -14
- package/dist/tools/tool-fallback.cjs.map +1 -1
- package/dist/tools/tool-uis.cjs +74 -74
- package/dist/tools/tool-uis.cjs.map +1 -1
- package/dist/tools/use-elapsed-seconds.cjs +3 -3
- package/dist/tools/use-elapsed-seconds.cjs.map +1 -1
- package/dist/tools/write-todos-tool-ui.cjs +9 -9
- package/dist/tools/write-todos-tool-ui.cjs.map +1 -1
- package/dist/ui/image-viewer.cjs +382 -0
- package/dist/ui/image-viewer.cjs.map +1 -0
- package/dist/ui/image-viewer.d.ts +50 -0
- package/dist/ui/image-viewer.js +382 -0
- package/dist/ui/image-viewer.js.map +1 -0
- package/dist/voice/chat.cjs +6 -0
- package/dist/voice/chat.cjs.map +1 -1
- package/dist/voice/chat.d.ts +1 -1
- package/dist/voice/chat.js +8 -2
- package/dist/voice/livekit-join.cjs +52 -101
- package/dist/voice/livekit-join.cjs.map +1 -1
- package/dist/voice/livekit-join.d.ts +1 -6
- package/dist/voice/livekit-join.js +52 -101
- package/dist/voice/livekit-join.js.map +1 -1
- package/dist/voice/livekit.cjs.map +1 -1
- package/dist/voice/livekit.d.ts +11 -1
- package/dist/voice/livekit.js.map +1 -1
- package/dist/voice/use-athena-voice-session.cjs +34 -34
- package/dist/voice/use-athena-voice-session.cjs.map +1 -1
- package/dist/workbench/ComputerLiveDesktop.cjs +13 -13
- package/dist/workbench/ComputerLiveDesktop.cjs.map +1 -1
- package/dist/workbench/SessionWorkbench.cjs +22 -22
- package/dist/workbench/SessionWorkbench.cjs.map +1 -1
- package/dist/workbench/session-workbench-context.cjs +3 -3
- package/dist/workbench/session-workbench-context.cjs.map +1 -1
- package/dist/workbench/session-workbench-panes.cjs +8 -8
- package/dist/workbench/session-workbench-panes.cjs.map +1 -1
- package/dist/workbench/workbench-layout-context.cjs +3 -3
- package/dist/workbench/workbench-layout-context.cjs.map +1 -1
- package/package.json +2 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const reactQuery = require("@tanstack/react-query");
|
|
4
|
-
const
|
|
4
|
+
const require$$0 = require("react");
|
|
5
5
|
const credentialRenewal = require("../runtime/credential-renewal.cjs");
|
|
6
6
|
const api = require("./api.cjs");
|
|
7
7
|
const conversationListFetcher = require("./conversation-list-fetcher.cjs");
|
|
@@ -15,7 +15,7 @@ function useRestConversationHistory({
|
|
|
15
15
|
enabled = true,
|
|
16
16
|
pageSize = 50
|
|
17
17
|
}) {
|
|
18
|
-
const fetchPage =
|
|
18
|
+
const fetchPage = require$$0.useMemo(
|
|
19
19
|
() => conversationListFetcher.createRestConversationListFetcher({ backendUrl, getAuth }),
|
|
20
20
|
[backendUrl, getAuth]
|
|
21
21
|
);
|
|
@@ -54,7 +54,7 @@ function useRestConversationHistory({
|
|
|
54
54
|
onServerTruth: ({ threadId, isFavorited }) => patchConversation(threadId, { isFavorited })
|
|
55
55
|
});
|
|
56
56
|
const favoriteOverrides = favorite.overrides;
|
|
57
|
-
const conversations =
|
|
57
|
+
const conversations = require$$0.useMemo(
|
|
58
58
|
() => useThreadFavorite.withFavoriteOverrides(list.conversations, favoriteOverrides),
|
|
59
59
|
[list.conversations, favoriteOverrides]
|
|
60
60
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-rest-conversation-history.cjs","sources":["../../src/threads/use-rest-conversation-history.ts"],"sourcesContent":["import {\n type ConversationSummary,\n useConversationList,\n} from '@athenaintel/agent-runtime';\nimport { useMutation } from '@tanstack/react-query';\nimport { useMemo } from 'react';\nimport { type CredentialResolver, withCredentialRenewal } from '../runtime/credential-renewal';\nimport { archiveThread, setThreadReadState } from './api';\nimport { createRestConversationListFetcher } from './conversation-list-fetcher';\nimport { useThreadFavorite, withFavoriteOverrides } from './use-thread-favorite';\n\nexport type RestConversationAuth = {\n apiKey?: string;\n token?: string | null;\n};\n\nexport interface UseRestConversationHistoryOptions {\n backendUrl: string;\n /** Non-secret identity included in the query cache boundary. */\n principalId: string;\n /** Resolved per request; called with `{ force: true }` when the host refuses the token. */\n getAuth: CredentialResolver<RestConversationAuth>;\n search?: string;\n enabled?: boolean;\n pageSize?: number;\n}\n\n/**\n * One inclusive, paginated conversation controller for satellite clients.\n * No app/channel filter is applied: authorization determines the user's rows,\n * while origin and automation metadata remain visible for UI filtering.\n */\nexport function useRestConversationHistory({\n backendUrl,\n principalId,\n getAuth,\n search,\n enabled = true,\n pageSize = 50,\n}: UseRestConversationHistoryOptions) {\n const fetchPage = useMemo(\n () => createRestConversationListFetcher({ backendUrl, getAuth }),\n [backendUrl, getAuth],\n );\n const list = useConversationList({\n fetchPage,\n filter: search?.trim() ? { search: search.trim() } : {},\n pageSize,\n scopeKey: `${backendUrl}::${principalId || 'unknown-principal'}`,\n enabled: enabled && principalId.length > 0,\n });\n\n const archive = useMutation({\n mutationKey: ['conversation-history', 'archive', backendUrl, principalId],\n mutationFn: async (threadId: string) => {\n await withCredentialRenewal(getAuth, (auth) => archiveThread(backendUrl, auth, threadId));\n return threadId;\n },\n onSuccess: (threadId) => list.removeConversation(threadId),\n });\n\n const readState = useMutation({\n mutationKey: ['conversation-history', 'read-state', backendUrl, principalId],\n mutationFn: async ({\n threadId,\n isUnread,\n }: {\n threadId: string;\n isUnread: boolean;\n }) =>\n withCredentialRenewal(getAuth, (auth) =>\n setThreadReadState(backendUrl, auth, { threadId, isUnread }),\n ),\n onSuccess: (result) =>\n list.patchConversation(result.thread_id, { isUnread: result.is_unread }),\n });\n\n // The pin flips optimistically and the server's answer is patched into the\n // page; the override drops once the page reports it.\n const patchConversation = list.patchConversation;\n const favorite = useThreadFavorite({\n backendUrl,\n principalId,\n getAuth,\n rows: list.conversations,\n onServerTruth: ({ threadId, isFavorited }) => patchConversation(threadId, { isFavorited }),\n });\n const favoriteOverrides = favorite.overrides;\n const conversations = useMemo(\n () => withFavoriteOverrides(list.conversations, favoriteOverrides),\n [list.conversations, favoriteOverrides],\n );\n\n return {\n ...list,\n conversations,\n archiveConversation: archive.mutate,\n archivePending: archive.isPending,\n setConversationReadState: readState.mutate,\n readStatePending: readState.isPending,\n /** Pin or unpin a conversation; read-only on a backend without the route (`favoriteToggleAvailable`). */\n setConversationFavorited: favorite.setFavorited,\n favoritePending: favorite.isPending,\n /** The conversations whose pin toggle is in flight. */\n favoritePendingThreadIds: favorite.pendingThreadIds,\n /** `false` once the backend answered 404 / 405 to the favorite route. */\n favoriteToggleAvailable: favorite.isAvailable,\n };\n}\n\nconst GENERIC_TITLES = new Set([\n 'new chat',\n 'new conversation',\n 'untitled',\n 'untitled conversation',\n]);\n\n/** Prefer a useful server title, then a normalized last-message preview. */\nexport function conversationDisplayTitle(\n conversation: Pick<ConversationSummary, 'title' | 'preview'>,\n): string {\n const title = conversation.title.trim();\n if (title && !GENERIC_TITLES.has(title.toLowerCase())) return title;\n const preview = conversation.preview?.replace(/\\s+/g, ' ').trim();\n if (preview) return preview.length > 80 ? `${preview.slice(0, 77)}…` : preview;\n return 'Untitled conversation';\n}\n"],"names":["useMemo","createRestConversationListFetcher","useConversationList","useMutation","withCredentialRenewal","archiveThread","setThreadReadState","useThreadFavorite","withFavoriteOverrides"],"mappings":";;;;;;;;;AAgCO,SAAS,2BAA2B;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,WAAW;AACb,GAAsC;AACpC,QAAM,YAAYA,
|
|
1
|
+
{"version":3,"file":"use-rest-conversation-history.cjs","sources":["../../src/threads/use-rest-conversation-history.ts"],"sourcesContent":["import {\n type ConversationSummary,\n useConversationList,\n} from '@athenaintel/agent-runtime';\nimport { useMutation } from '@tanstack/react-query';\nimport { useMemo } from 'react';\nimport { type CredentialResolver, withCredentialRenewal } from '../runtime/credential-renewal';\nimport { archiveThread, setThreadReadState } from './api';\nimport { createRestConversationListFetcher } from './conversation-list-fetcher';\nimport { useThreadFavorite, withFavoriteOverrides } from './use-thread-favorite';\n\nexport type RestConversationAuth = {\n apiKey?: string;\n token?: string | null;\n};\n\nexport interface UseRestConversationHistoryOptions {\n backendUrl: string;\n /** Non-secret identity included in the query cache boundary. */\n principalId: string;\n /** Resolved per request; called with `{ force: true }` when the host refuses the token. */\n getAuth: CredentialResolver<RestConversationAuth>;\n search?: string;\n enabled?: boolean;\n pageSize?: number;\n}\n\n/**\n * One inclusive, paginated conversation controller for satellite clients.\n * No app/channel filter is applied: authorization determines the user's rows,\n * while origin and automation metadata remain visible for UI filtering.\n */\nexport function useRestConversationHistory({\n backendUrl,\n principalId,\n getAuth,\n search,\n enabled = true,\n pageSize = 50,\n}: UseRestConversationHistoryOptions) {\n const fetchPage = useMemo(\n () => createRestConversationListFetcher({ backendUrl, getAuth }),\n [backendUrl, getAuth],\n );\n const list = useConversationList({\n fetchPage,\n filter: search?.trim() ? { search: search.trim() } : {},\n pageSize,\n scopeKey: `${backendUrl}::${principalId || 'unknown-principal'}`,\n enabled: enabled && principalId.length > 0,\n });\n\n const archive = useMutation({\n mutationKey: ['conversation-history', 'archive', backendUrl, principalId],\n mutationFn: async (threadId: string) => {\n await withCredentialRenewal(getAuth, (auth) => archiveThread(backendUrl, auth, threadId));\n return threadId;\n },\n onSuccess: (threadId) => list.removeConversation(threadId),\n });\n\n const readState = useMutation({\n mutationKey: ['conversation-history', 'read-state', backendUrl, principalId],\n mutationFn: async ({\n threadId,\n isUnread,\n }: {\n threadId: string;\n isUnread: boolean;\n }) =>\n withCredentialRenewal(getAuth, (auth) =>\n setThreadReadState(backendUrl, auth, { threadId, isUnread }),\n ),\n onSuccess: (result) =>\n list.patchConversation(result.thread_id, { isUnread: result.is_unread }),\n });\n\n // The pin flips optimistically and the server's answer is patched into the\n // page; the override drops once the page reports it.\n const patchConversation = list.patchConversation;\n const favorite = useThreadFavorite({\n backendUrl,\n principalId,\n getAuth,\n rows: list.conversations,\n onServerTruth: ({ threadId, isFavorited }) => patchConversation(threadId, { isFavorited }),\n });\n const favoriteOverrides = favorite.overrides;\n const conversations = useMemo(\n () => withFavoriteOverrides(list.conversations, favoriteOverrides),\n [list.conversations, favoriteOverrides],\n );\n\n return {\n ...list,\n conversations,\n archiveConversation: archive.mutate,\n archivePending: archive.isPending,\n setConversationReadState: readState.mutate,\n readStatePending: readState.isPending,\n /** Pin or unpin a conversation; read-only on a backend without the route (`favoriteToggleAvailable`). */\n setConversationFavorited: favorite.setFavorited,\n favoritePending: favorite.isPending,\n /** The conversations whose pin toggle is in flight. */\n favoritePendingThreadIds: favorite.pendingThreadIds,\n /** `false` once the backend answered 404 / 405 to the favorite route. */\n favoriteToggleAvailable: favorite.isAvailable,\n };\n}\n\nconst GENERIC_TITLES = new Set([\n 'new chat',\n 'new conversation',\n 'untitled',\n 'untitled conversation',\n]);\n\n/** Prefer a useful server title, then a normalized last-message preview. */\nexport function conversationDisplayTitle(\n conversation: Pick<ConversationSummary, 'title' | 'preview'>,\n): string {\n const title = conversation.title.trim();\n if (title && !GENERIC_TITLES.has(title.toLowerCase())) return title;\n const preview = conversation.preview?.replace(/\\s+/g, ' ').trim();\n if (preview) return preview.length > 80 ? `${preview.slice(0, 77)}…` : preview;\n return 'Untitled conversation';\n}\n"],"names":["useMemo","createRestConversationListFetcher","useConversationList","useMutation","withCredentialRenewal","archiveThread","setThreadReadState","useThreadFavorite","withFavoriteOverrides"],"mappings":";;;;;;;;;AAgCO,SAAS,2BAA2B;AAAA,EACzC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU;AAAA,EACV,WAAW;AACb,GAAsC;AACpC,QAAM,YAAYA,WAAAA;AAAAA,IAChB,MAAMC,0DAAkC,EAAE,YAAY,SAAS;AAAA,IAC/D,CAAC,YAAY,OAAO;AAAA,EAAA;AAEtB,QAAM,OAAOC,oBAAAA,oBAAoB;AAAA,IAC/B;AAAA,IACA,SAAQ,iCAAQ,UAAS,EAAE,QAAQ,OAAO,KAAA,EAAK,IAAM,CAAA;AAAA,IACrD;AAAA,IACA,UAAU,GAAG,UAAU,KAAK,eAAe,mBAAmB;AAAA,IAC9D,SAAS,WAAW,YAAY,SAAS;AAAA,EAAA,CAC1C;AAED,QAAM,UAAUC,WAAAA,YAAY;AAAA,IAC1B,aAAa,CAAC,wBAAwB,WAAW,YAAY,WAAW;AAAA,IACxE,YAAY,OAAO,aAAqB;AACtC,YAAMC,kBAAAA,sBAAsB,SAAS,CAAC,SAASC,IAAAA,cAAc,YAAY,MAAM,QAAQ,CAAC;AACxF,aAAO;AAAA,IACT;AAAA,IACA,WAAW,CAAC,aAAa,KAAK,mBAAmB,QAAQ;AAAA,EAAA,CAC1D;AAED,QAAM,YAAYF,WAAAA,YAAY;AAAA,IAC5B,aAAa,CAAC,wBAAwB,cAAc,YAAY,WAAW;AAAA,IAC3E,YAAY,OAAO;AAAA,MACjB;AAAA,MACA;AAAA,IAAA,MAKAC,kBAAAA;AAAAA,MAAsB;AAAA,MAAS,CAAC,SAC9BE,IAAAA,mBAAmB,YAAY,MAAM,EAAE,UAAU,UAAU;AAAA,IAAA;AAAA,IAE/D,WAAW,CAAC,WACV,KAAK,kBAAkB,OAAO,WAAW,EAAE,UAAU,OAAO,UAAA,CAAW;AAAA,EAAA,CAC1E;AAID,QAAM,oBAAoB,KAAK;AAC/B,QAAM,WAAWC,kBAAAA,kBAAkB;AAAA,IACjC;AAAA,IACA;AAAA,IACA;AAAA,IACA,MAAM,KAAK;AAAA,IACX,eAAe,CAAC,EAAE,UAAU,YAAA,MAAkB,kBAAkB,UAAU,EAAE,YAAA,CAAa;AAAA,EAAA,CAC1F;AACD,QAAM,oBAAoB,SAAS;AACnC,QAAM,gBAAgBP,WAAAA;AAAAA,IACpB,MAAMQ,wCAAsB,KAAK,eAAe,iBAAiB;AAAA,IACjE,CAAC,KAAK,eAAe,iBAAiB;AAAA,EAAA;AAGxC,SAAO;AAAA,IACL,GAAG;AAAA,IACH;AAAA,IACA,qBAAqB,QAAQ;AAAA,IAC7B,gBAAgB,QAAQ;AAAA,IACxB,0BAA0B,UAAU;AAAA,IACpC,kBAAkB,UAAU;AAAA;AAAA,IAE5B,0BAA0B,SAAS;AAAA,IACnC,iBAAiB,SAAS;AAAA;AAAA,IAE1B,0BAA0B,SAAS;AAAA;AAAA,IAEnC,yBAAyB,SAAS;AAAA,EAAA;AAEtC;AAEA,MAAM,qCAAqB,IAAI;AAAA,EAC7B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAGM,SAAS,yBACd,cACQ;;AACR,QAAM,QAAQ,aAAa,MAAM,KAAA;AACjC,MAAI,SAAS,CAAC,eAAe,IAAI,MAAM,YAAA,CAAa,EAAG,QAAO;AAC9D,QAAM,WAAU,kBAAa,YAAb,mBAAsB,QAAQ,QAAQ,KAAK;AAC3D,MAAI,QAAS,QAAO,QAAQ,SAAS,KAAK,GAAG,QAAQ,MAAM,GAAG,EAAE,CAAC,MAAM;AACvE,SAAO;AACT;;;"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const reactQuery = require("@tanstack/react-query");
|
|
4
|
-
const
|
|
4
|
+
const require$$0 = require("react");
|
|
5
5
|
const credentialRenewal = require("../runtime/credential-renewal.cjs");
|
|
6
6
|
const api = require("./api.cjs");
|
|
7
7
|
const useRestConversationHistory = require("./use-rest-conversation-history.cjs");
|
|
@@ -91,11 +91,11 @@ function useStatewireConversationHistory({
|
|
|
91
91
|
search,
|
|
92
92
|
enabled: enabled && principalId.length > 0 && usesRestHistory
|
|
93
93
|
});
|
|
94
|
-
const [readOverrides, setReadOverrides] =
|
|
94
|
+
const [readOverrides, setReadOverrides] = require$$0.useState(
|
|
95
95
|
{}
|
|
96
96
|
);
|
|
97
|
-
const [archivedThreadIds, setArchivedThreadIds] =
|
|
98
|
-
|
|
97
|
+
const [archivedThreadIds, setArchivedThreadIds] = require$$0.useState(() => /* @__PURE__ */ new Set());
|
|
98
|
+
require$$0.useEffect(() => {
|
|
99
99
|
if (index.entries === null || archivedThreadIds.size === 0) return;
|
|
100
100
|
const visibleIds = new Set(index.entries.map((entry) => entry.thread_id));
|
|
101
101
|
setArchivedThreadIds((current) => {
|
|
@@ -105,7 +105,7 @@ function useStatewireConversationHistory({
|
|
|
105
105
|
return next.size === current.size ? current : next;
|
|
106
106
|
});
|
|
107
107
|
}, [archivedThreadIds.size, index.entries]);
|
|
108
|
-
const sourceConversations =
|
|
108
|
+
const sourceConversations = require$$0.useMemo(
|
|
109
109
|
() => conversationHistorySource({
|
|
110
110
|
indexEntries: index.entries,
|
|
111
111
|
restConversations: legacyHistory.conversations,
|
|
@@ -129,7 +129,7 @@ function useStatewireConversationHistory({
|
|
|
129
129
|
onServerTruth: ({ threadId, isFavorited }) => patchLegacyConversation(threadId, { isFavorited })
|
|
130
130
|
});
|
|
131
131
|
const favoriteOverrides = favorite.overrides;
|
|
132
|
-
const conversations =
|
|
132
|
+
const conversations = require$$0.useMemo(
|
|
133
133
|
() => useThreadFavorite.withFavoriteOverrides(sourceConversations, favoriteOverrides).map(
|
|
134
134
|
(conversation) => ({
|
|
135
135
|
...conversation,
|
|
@@ -223,11 +223,11 @@ function useStatewireConversationHistory({
|
|
|
223
223
|
});
|
|
224
224
|
}
|
|
225
225
|
});
|
|
226
|
-
const refresh =
|
|
226
|
+
const refresh = require$$0.useCallback(
|
|
227
227
|
() => refreshMutation.mutateAsync(),
|
|
228
228
|
[refreshMutation.mutateAsync]
|
|
229
229
|
);
|
|
230
|
-
const fetchNextPage =
|
|
230
|
+
const fetchNextPage = require$$0.useCallback(
|
|
231
231
|
() => loadMoreMutation.mutateAsync(),
|
|
232
232
|
[loadMoreMutation.mutateAsync]
|
|
233
233
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-statewire-conversation-history.cjs","sources":["../../src/threads/use-statewire-conversation-history.ts"],"sourcesContent":["import {\n\ttype ConversationIndexEntry,\n\ttype ConversationSummary,\n\ttype UseConversationIndexOptions,\n\tuseConversationIndex,\n} from \"@athenaintel/agent-runtime\";\nimport { useMutation } from \"@tanstack/react-query\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport {\n\ttype CredentialResolver,\n\twithCredentialRenewal,\n} from \"../runtime/credential-renewal\";\nimport { archiveThread, setThreadReadState } from \"./api\";\nimport {\n\ttype RestConversationAuth,\n\tuseRestConversationHistory,\n} from \"./use-rest-conversation-history\";\nimport { useThreadFavorite, withFavoriteOverrides } from \"./use-thread-favorite\";\n\nexport interface UseStatewireConversationHistoryOptions {\n\tbackendUrl: string;\n\tconversationIndexBaseUrl: string;\n\t/** The workspace being viewed; the index is one instance per (workspace, user). */\n\tworkspaceId: string;\n\tprincipalId: string;\n\t/** Resolved per request; called with `{ force: true }` when the host refuses the token. */\n\tgetAuth: CredentialResolver<RestConversationAuth>;\n\theaders: UseConversationIndexOptions[\"headers\"];\n\tsearch?: string;\n\tenabled?: boolean;\n\tsse?: boolean;\n}\n\n/** Convert the replicated wire row into the shared cross-surface contract. */\nexport function conversationSummaryFromIndexEntry(\n\tentry: ConversationIndexEntry,\n): ConversationSummary {\n\treturn {\n\t\tthreadId: entry.thread_id,\n\t\ttitle: entry.title,\n\t\tupdatedAt: entry.updated_at,\n\t\tcreatedAt: null,\n\t\tstate: entry.state,\n\t\truntime: entry.runtime,\n\t\tsourceChannel: entry.start_channel,\n\t\tassetType: entry.asset_type,\n\t\tassetId: entry.asset_id ?? null,\n\t\tappId: entry.app_id ?? null,\n\t\ttriggerType: entry.trigger_type ?? null,\n\t\tpreview: entry.last_message_preview ?? null,\n\t\tmessageCount: entry.message_count ?? null,\n\t\tisUnread: entry.is_unread ?? false,\n\t\tsessionStatus: entry.session_status ?? null,\n\t\trunStatus: entry.run_status ?? null,\n\t};\n}\n\nexport function conversationHistorySource({\n\tindexEntries,\n\trestConversations,\n\tsupportsStatewirePaging,\n\thasSearch,\n}: {\n\tindexEntries: readonly ConversationIndexEntry[] | null;\n\trestConversations: readonly ConversationSummary[];\n\tsupportsStatewirePaging: boolean;\n\thasSearch: boolean;\n}): ConversationSummary[] {\n\t// Search is server-backed so it covers the user's entire authorized history,\n\t// including rows older than the Statewire live window. An empty query uses\n\t// Statewire as the render source; REST only supplements rolling old hosts.\n\tif (hasSearch) return [...restConversations];\n\tconst statewireItems = (indexEntries ?? []).map(\n\t\tconversationSummaryFromIndexEntry,\n\t);\n\tif (supportsStatewirePaging) return statewireItems;\n\tconst statewireIds = new Set(statewireItems.map((item) => item.threadId));\n\treturn [\n\t\t...statewireItems,\n\t\t...restConversations.filter(\n\t\t\t(conversation) => !statewireIds.has(conversation.threadId),\n\t\t),\n\t];\n}\n\nexport function shouldUseRestConversationHistory({\n\thasSearch,\n\tindexEntries,\n\tsupportsStatewirePaging,\n\tconnectionStatus,\n}: {\n\thasSearch: boolean;\n\tindexEntries: readonly ConversationIndexEntry[] | null;\n\tsupportsStatewirePaging: boolean;\n\tconnectionStatus: string;\n}): boolean {\n\tif (hasSearch) return true;\n\tif (supportsStatewirePaging) return false;\n\t// An old host is identifiable once its snapshot arrives. A transport that\n\t// fails or is parked before any snapshot also needs the independent REST\n\t// path; otherwise entries stays null and the history panel loads forever.\n\treturn (\n\t\tindexEntries !== null ||\n\t\tconnectionStatus === \"reconnecting\" ||\n\t\tconnectionStatus === \"gone\"\n\t);\n}\n\n/**\n * Inclusive satellite conversation history backed by the user's Pinned\n * Statewire instance. The replicated window is the render source; refreshes,\n * pagination, thread creation, lifecycle changes, and title changes arrive on\n * that same channel. A non-empty search deliberately uses the authorized REST\n * list endpoint so matches are not limited to the replicated newest window.\n */\nexport function useStatewireConversationHistory({\n\tbackendUrl,\n\tconversationIndexBaseUrl,\n\tworkspaceId,\n\tprincipalId,\n\tgetAuth,\n\theaders,\n\tsearch,\n\tenabled = true,\n\tsse = false,\n}: UseStatewireConversationHistoryOptions) {\n\tconst index = useConversationIndex({\n\t\tbaseUrl: conversationIndexBaseUrl,\n\t\tworkspaceId: workspaceId || \"pending-workspace\",\n\t\tuserId: principalId || \"pending-user\",\n\t\theaders,\n\t\tenabled: enabled && workspaceId.length > 0 && principalId.length > 0,\n\t\tsse,\n\t});\n\t// Rolling deploy compatibility: the pre-paging index snapshot has no\n\t// total_count. It still renders live rows immediately, while the old REST\n\t// pager remains available only until the upgraded host activates.\n\tconst supportsStatewirePaging = index.totalCount !== null;\n\tconst normalizedSearch = search?.trim().toLowerCase() ?? \"\";\n\tconst hasSearch = normalizedSearch.length > 0;\n\tconst usesRestHistory = shouldUseRestConversationHistory({\n\t\thasSearch,\n\t\tindexEntries: index.entries,\n\t\tsupportsStatewirePaging,\n\t\tconnectionStatus: index.connection.status,\n\t});\n\tconst legacyHistory = useRestConversationHistory({\n\t\tbackendUrl,\n\t\tprincipalId,\n\t\tgetAuth,\n\t\tsearch,\n\t\tenabled: enabled && principalId.length > 0 && usesRestHistory,\n\t});\n\tconst [readOverrides, setReadOverrides] = useState<Record<string, boolean>>(\n\t\t{},\n\t);\n\tconst [archivedThreadIds, setArchivedThreadIds] = useState<\n\t\tReadonlySet<string>\n\t>(() => new Set());\n\n\tuseEffect(() => {\n\t\tif (index.entries === null || archivedThreadIds.size === 0) return;\n\t\tconst visibleIds = new Set(index.entries.map((entry) => entry.thread_id));\n\t\tsetArchivedThreadIds((current) => {\n\t\t\tconst next = new Set(\n\t\t\t\t[...current].filter((threadId) => visibleIds.has(threadId)),\n\t\t\t);\n\t\t\treturn next.size === current.size ? current : next;\n\t\t});\n\t}, [archivedThreadIds.size, index.entries]);\n\n\tconst sourceConversations = useMemo(\n\t\t() =>\n\t\t\tconversationHistorySource({\n\t\t\t\tindexEntries: index.entries,\n\t\t\t\trestConversations: legacyHistory.conversations,\n\t\t\t\tsupportsStatewirePaging,\n\t\t\t\thasSearch,\n\t\t\t}).filter((conversation) => !archivedThreadIds.has(conversation.threadId)),\n\t\t[\n\t\t\tarchivedThreadIds,\n\t\t\tindex.entries,\n\t\t\tlegacyHistory.conversations,\n\t\t\thasSearch,\n\t\t\tsupportsStatewirePaging,\n\t\t],\n\t);\n\t// The pin flips optimistically over both sources; the Statewire index\n\t// pushes the confirmed value, the REST page is patched with it, and the\n\t// override drops once the rendered source reports it.\n\tconst patchLegacyConversation = legacyHistory.patchConversation;\n\tconst favorite = useThreadFavorite({\n\t\tbackendUrl,\n\t\tprincipalId,\n\t\tgetAuth,\n\t\trows: sourceConversations,\n\t\tonServerTruth: ({ threadId, isFavorited }) =>\n\t\t\tpatchLegacyConversation(threadId, { isFavorited }),\n\t});\n\tconst favoriteOverrides = favorite.overrides;\n\n\tconst conversations = useMemo(\n\t\t() =>\n\t\t\twithFavoriteOverrides(sourceConversations, favoriteOverrides).map(\n\t\t\t\t(conversation) => ({\n\t\t\t\t\t...conversation,\n\t\t\t\t\tisUnread:\n\t\t\t\t\t\treadOverrides[conversation.threadId] ?? conversation.isUnread,\n\t\t\t\t}),\n\t\t\t),\n\t\t[sourceConversations, favoriteOverrides, readOverrides],\n\t);\n\n\tconst refreshMutation = useMutation({\n\t\tmutationKey: [\n\t\t\t\"conversation-index\",\n\t\t\t\"refresh\",\n\t\t\tconversationIndexBaseUrl,\n\t\t\tprincipalId,\n\t\t],\n\t\tmutationFn: () =>\n\t\t\tusesRestHistory ? legacyHistory.refresh() : index.refresh(),\n\t});\n\tconst loadMoreMutation = useMutation({\n\t\tmutationKey: [\n\t\t\t\"conversation-index\",\n\t\t\t\"load-more\",\n\t\t\tconversationIndexBaseUrl,\n\t\t\tprincipalId,\n\t\t],\n\t\tmutationFn: () =>\n\t\t\tusesRestHistory ? legacyHistory.fetchNextPage() : index.loadMore(),\n\t});\n\tconst archive = useMutation({\n\t\tmutationKey: [\"conversation-history\", \"archive\", backendUrl, principalId],\n\t\tmutationFn: async (threadId: string) => {\n\t\t\tawait withCredentialRenewal(getAuth, (auth) =>\n\t\t\t\tarchiveThread(backendUrl, auth, threadId),\n\t\t\t);\n\t\t\treturn threadId;\n\t\t},\n\t\tonMutate: (threadId) => {\n\t\t\tsetArchivedThreadIds((current) => new Set(current).add(threadId));\n\t\t},\n\t\tonError: (_error, threadId) => {\n\t\t\tsetArchivedThreadIds((current) => {\n\t\t\t\tconst next = new Set(current);\n\t\t\t\tnext.delete(threadId);\n\t\t\t\treturn next;\n\t\t\t});\n\t\t},\n\t\tonSuccess: () => {\n\t\t\trefreshMutation.mutate();\n\t\t},\n\t});\n\tconst readState = useMutation({\n\t\tmutationKey: [\n\t\t\t\"conversation-history\",\n\t\t\t\"read-state\",\n\t\t\tbackendUrl,\n\t\t\tprincipalId,\n\t\t],\n\t\tmutationFn: async ({\n\t\t\tthreadId,\n\t\t\tisUnread,\n\t\t}: {\n\t\t\tthreadId: string;\n\t\t\tisUnread: boolean;\n\t\t}) =>\n\t\t\twithCredentialRenewal(getAuth, (auth) =>\n\t\t\t\tsetThreadReadState(backendUrl, auth, { threadId, isUnread }),\n\t\t\t),\n\t\tonMutate: ({ threadId, isUnread }) => {\n\t\t\tconst previous = readOverrides[threadId];\n\t\t\tsetReadOverrides((current) => ({ ...current, [threadId]: isUnread }));\n\t\t\treturn { previous, threadId };\n\t\t},\n\t\tonError: (_error, _variables, context) => {\n\t\t\tif (!context) return;\n\t\t\tsetReadOverrides((current) => {\n\t\t\t\tconst next = { ...current };\n\t\t\t\tif (context.previous === undefined) delete next[context.threadId];\n\t\t\t\telse next[context.threadId] = context.previous;\n\t\t\t\treturn next;\n\t\t\t});\n\t\t},\n\t\tonSuccess: (result) => {\n\t\t\tsetReadOverrides((current) => ({\n\t\t\t\t...current,\n\t\t\t\t[result.thread_id]: result.is_unread,\n\t\t\t}));\n\t\t\trefreshMutation.mutate(undefined, {\n\t\t\t\tonSettled: () => {\n\t\t\t\t\tsetReadOverrides((current) => {\n\t\t\t\t\t\tconst next = { ...current };\n\t\t\t\t\t\tdelete next[result.thread_id];\n\t\t\t\t\t\treturn next;\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t});\n\n\tconst refresh = useCallback(\n\t\t() => refreshMutation.mutateAsync(),\n\t\t[refreshMutation.mutateAsync],\n\t);\n\tconst fetchNextPage = useCallback(\n\t\t() => loadMoreMutation.mutateAsync(),\n\t\t[loadMoreMutation.mutateAsync],\n\t);\n\n\treturn {\n\t\tconversations,\n\t\ttotalCount: usesRestHistory ? legacyHistory.totalCount : index.totalCount,\n\t\tisLoading:\n\t\t\tenabled &&\n\t\t\t(usesRestHistory\n\t\t\t\t? !legacyHistory.hasResolvedFirstPage\n\t\t\t\t: index.entries === null),\n\t\tisFetching:\n\t\t\trefreshMutation.isPending ||\n\t\t\tloadMoreMutation.isPending ||\n\t\t\tlegacyHistory.isFetching,\n\t\tisRefreshing: refreshMutation.isPending,\n\t\thasResolvedFirstPage: usesRestHistory\n\t\t\t? legacyHistory.hasResolvedFirstPage\n\t\t\t: index.entries !== null,\n\t\thasNextPage: usesRestHistory\n\t\t\t? legacyHistory.hasNextPage\n\t\t\t: index.hasNextPage,\n\t\tisFetchingNextPage: loadMoreMutation.isPending,\n\t\tfetchNextPage,\n\t\trefresh,\n\t\tarchiveConversation: archive.mutate,\n\t\tarchivePending: archive.isPending,\n\t\tsetConversationReadState: readState.mutate,\n\t\treadStatePending: readState.isPending,\n\t\t/** Pin or unpin a conversation; read-only on a backend without the route (`favoriteToggleAvailable`). */\n\t\tsetConversationFavorited: favorite.setFavorited,\n\t\tfavoritePending: favorite.isPending,\n\t\t/** The conversations whose pin toggle is in flight. */\n\t\tfavoritePendingThreadIds: favorite.pendingThreadIds,\n\t\t/** `false` once the backend answered 404 / 405 to the favorite route. */\n\t\tfavoriteToggleAvailable: favorite.isAvailable,\n\t\tconnection: index.connection,\n\t};\n}\n"],"names":["useConversationIndex","useRestConversationHistory","useState","useEffect","useMemo","useThreadFavorite","withFavoriteOverrides","useMutation","withCredentialRenewal","archiveThread","setThreadReadState","useCallback"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"use-statewire-conversation-history.cjs","sources":["../../src/threads/use-statewire-conversation-history.ts"],"sourcesContent":["import {\n\ttype ConversationIndexEntry,\n\ttype ConversationSummary,\n\ttype UseConversationIndexOptions,\n\tuseConversationIndex,\n} from \"@athenaintel/agent-runtime\";\nimport { useMutation } from \"@tanstack/react-query\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport {\n\ttype CredentialResolver,\n\twithCredentialRenewal,\n} from \"../runtime/credential-renewal\";\nimport { archiveThread, setThreadReadState } from \"./api\";\nimport {\n\ttype RestConversationAuth,\n\tuseRestConversationHistory,\n} from \"./use-rest-conversation-history\";\nimport { useThreadFavorite, withFavoriteOverrides } from \"./use-thread-favorite\";\n\nexport interface UseStatewireConversationHistoryOptions {\n\tbackendUrl: string;\n\tconversationIndexBaseUrl: string;\n\t/** The workspace being viewed; the index is one instance per (workspace, user). */\n\tworkspaceId: string;\n\tprincipalId: string;\n\t/** Resolved per request; called with `{ force: true }` when the host refuses the token. */\n\tgetAuth: CredentialResolver<RestConversationAuth>;\n\theaders: UseConversationIndexOptions[\"headers\"];\n\tsearch?: string;\n\tenabled?: boolean;\n\tsse?: boolean;\n}\n\n/** Convert the replicated wire row into the shared cross-surface contract. */\nexport function conversationSummaryFromIndexEntry(\n\tentry: ConversationIndexEntry,\n): ConversationSummary {\n\treturn {\n\t\tthreadId: entry.thread_id,\n\t\ttitle: entry.title,\n\t\tupdatedAt: entry.updated_at,\n\t\tcreatedAt: null,\n\t\tstate: entry.state,\n\t\truntime: entry.runtime,\n\t\tsourceChannel: entry.start_channel,\n\t\tassetType: entry.asset_type,\n\t\tassetId: entry.asset_id ?? null,\n\t\tappId: entry.app_id ?? null,\n\t\ttriggerType: entry.trigger_type ?? null,\n\t\tpreview: entry.last_message_preview ?? null,\n\t\tmessageCount: entry.message_count ?? null,\n\t\tisUnread: entry.is_unread ?? false,\n\t\tsessionStatus: entry.session_status ?? null,\n\t\trunStatus: entry.run_status ?? null,\n\t};\n}\n\nexport function conversationHistorySource({\n\tindexEntries,\n\trestConversations,\n\tsupportsStatewirePaging,\n\thasSearch,\n}: {\n\tindexEntries: readonly ConversationIndexEntry[] | null;\n\trestConversations: readonly ConversationSummary[];\n\tsupportsStatewirePaging: boolean;\n\thasSearch: boolean;\n}): ConversationSummary[] {\n\t// Search is server-backed so it covers the user's entire authorized history,\n\t// including rows older than the Statewire live window. An empty query uses\n\t// Statewire as the render source; REST only supplements rolling old hosts.\n\tif (hasSearch) return [...restConversations];\n\tconst statewireItems = (indexEntries ?? []).map(\n\t\tconversationSummaryFromIndexEntry,\n\t);\n\tif (supportsStatewirePaging) return statewireItems;\n\tconst statewireIds = new Set(statewireItems.map((item) => item.threadId));\n\treturn [\n\t\t...statewireItems,\n\t\t...restConversations.filter(\n\t\t\t(conversation) => !statewireIds.has(conversation.threadId),\n\t\t),\n\t];\n}\n\nexport function shouldUseRestConversationHistory({\n\thasSearch,\n\tindexEntries,\n\tsupportsStatewirePaging,\n\tconnectionStatus,\n}: {\n\thasSearch: boolean;\n\tindexEntries: readonly ConversationIndexEntry[] | null;\n\tsupportsStatewirePaging: boolean;\n\tconnectionStatus: string;\n}): boolean {\n\tif (hasSearch) return true;\n\tif (supportsStatewirePaging) return false;\n\t// An old host is identifiable once its snapshot arrives. A transport that\n\t// fails or is parked before any snapshot also needs the independent REST\n\t// path; otherwise entries stays null and the history panel loads forever.\n\treturn (\n\t\tindexEntries !== null ||\n\t\tconnectionStatus === \"reconnecting\" ||\n\t\tconnectionStatus === \"gone\"\n\t);\n}\n\n/**\n * Inclusive satellite conversation history backed by the user's Pinned\n * Statewire instance. The replicated window is the render source; refreshes,\n * pagination, thread creation, lifecycle changes, and title changes arrive on\n * that same channel. A non-empty search deliberately uses the authorized REST\n * list endpoint so matches are not limited to the replicated newest window.\n */\nexport function useStatewireConversationHistory({\n\tbackendUrl,\n\tconversationIndexBaseUrl,\n\tworkspaceId,\n\tprincipalId,\n\tgetAuth,\n\theaders,\n\tsearch,\n\tenabled = true,\n\tsse = false,\n}: UseStatewireConversationHistoryOptions) {\n\tconst index = useConversationIndex({\n\t\tbaseUrl: conversationIndexBaseUrl,\n\t\tworkspaceId: workspaceId || \"pending-workspace\",\n\t\tuserId: principalId || \"pending-user\",\n\t\theaders,\n\t\tenabled: enabled && workspaceId.length > 0 && principalId.length > 0,\n\t\tsse,\n\t});\n\t// Rolling deploy compatibility: the pre-paging index snapshot has no\n\t// total_count. It still renders live rows immediately, while the old REST\n\t// pager remains available only until the upgraded host activates.\n\tconst supportsStatewirePaging = index.totalCount !== null;\n\tconst normalizedSearch = search?.trim().toLowerCase() ?? \"\";\n\tconst hasSearch = normalizedSearch.length > 0;\n\tconst usesRestHistory = shouldUseRestConversationHistory({\n\t\thasSearch,\n\t\tindexEntries: index.entries,\n\t\tsupportsStatewirePaging,\n\t\tconnectionStatus: index.connection.status,\n\t});\n\tconst legacyHistory = useRestConversationHistory({\n\t\tbackendUrl,\n\t\tprincipalId,\n\t\tgetAuth,\n\t\tsearch,\n\t\tenabled: enabled && principalId.length > 0 && usesRestHistory,\n\t});\n\tconst [readOverrides, setReadOverrides] = useState<Record<string, boolean>>(\n\t\t{},\n\t);\n\tconst [archivedThreadIds, setArchivedThreadIds] = useState<\n\t\tReadonlySet<string>\n\t>(() => new Set());\n\n\tuseEffect(() => {\n\t\tif (index.entries === null || archivedThreadIds.size === 0) return;\n\t\tconst visibleIds = new Set(index.entries.map((entry) => entry.thread_id));\n\t\tsetArchivedThreadIds((current) => {\n\t\t\tconst next = new Set(\n\t\t\t\t[...current].filter((threadId) => visibleIds.has(threadId)),\n\t\t\t);\n\t\t\treturn next.size === current.size ? current : next;\n\t\t});\n\t}, [archivedThreadIds.size, index.entries]);\n\n\tconst sourceConversations = useMemo(\n\t\t() =>\n\t\t\tconversationHistorySource({\n\t\t\t\tindexEntries: index.entries,\n\t\t\t\trestConversations: legacyHistory.conversations,\n\t\t\t\tsupportsStatewirePaging,\n\t\t\t\thasSearch,\n\t\t\t}).filter((conversation) => !archivedThreadIds.has(conversation.threadId)),\n\t\t[\n\t\t\tarchivedThreadIds,\n\t\t\tindex.entries,\n\t\t\tlegacyHistory.conversations,\n\t\t\thasSearch,\n\t\t\tsupportsStatewirePaging,\n\t\t],\n\t);\n\t// The pin flips optimistically over both sources; the Statewire index\n\t// pushes the confirmed value, the REST page is patched with it, and the\n\t// override drops once the rendered source reports it.\n\tconst patchLegacyConversation = legacyHistory.patchConversation;\n\tconst favorite = useThreadFavorite({\n\t\tbackendUrl,\n\t\tprincipalId,\n\t\tgetAuth,\n\t\trows: sourceConversations,\n\t\tonServerTruth: ({ threadId, isFavorited }) =>\n\t\t\tpatchLegacyConversation(threadId, { isFavorited }),\n\t});\n\tconst favoriteOverrides = favorite.overrides;\n\n\tconst conversations = useMemo(\n\t\t() =>\n\t\t\twithFavoriteOverrides(sourceConversations, favoriteOverrides).map(\n\t\t\t\t(conversation) => ({\n\t\t\t\t\t...conversation,\n\t\t\t\t\tisUnread:\n\t\t\t\t\t\treadOverrides[conversation.threadId] ?? conversation.isUnread,\n\t\t\t\t}),\n\t\t\t),\n\t\t[sourceConversations, favoriteOverrides, readOverrides],\n\t);\n\n\tconst refreshMutation = useMutation({\n\t\tmutationKey: [\n\t\t\t\"conversation-index\",\n\t\t\t\"refresh\",\n\t\t\tconversationIndexBaseUrl,\n\t\t\tprincipalId,\n\t\t],\n\t\tmutationFn: () =>\n\t\t\tusesRestHistory ? legacyHistory.refresh() : index.refresh(),\n\t});\n\tconst loadMoreMutation = useMutation({\n\t\tmutationKey: [\n\t\t\t\"conversation-index\",\n\t\t\t\"load-more\",\n\t\t\tconversationIndexBaseUrl,\n\t\t\tprincipalId,\n\t\t],\n\t\tmutationFn: () =>\n\t\t\tusesRestHistory ? legacyHistory.fetchNextPage() : index.loadMore(),\n\t});\n\tconst archive = useMutation({\n\t\tmutationKey: [\"conversation-history\", \"archive\", backendUrl, principalId],\n\t\tmutationFn: async (threadId: string) => {\n\t\t\tawait withCredentialRenewal(getAuth, (auth) =>\n\t\t\t\tarchiveThread(backendUrl, auth, threadId),\n\t\t\t);\n\t\t\treturn threadId;\n\t\t},\n\t\tonMutate: (threadId) => {\n\t\t\tsetArchivedThreadIds((current) => new Set(current).add(threadId));\n\t\t},\n\t\tonError: (_error, threadId) => {\n\t\t\tsetArchivedThreadIds((current) => {\n\t\t\t\tconst next = new Set(current);\n\t\t\t\tnext.delete(threadId);\n\t\t\t\treturn next;\n\t\t\t});\n\t\t},\n\t\tonSuccess: () => {\n\t\t\trefreshMutation.mutate();\n\t\t},\n\t});\n\tconst readState = useMutation({\n\t\tmutationKey: [\n\t\t\t\"conversation-history\",\n\t\t\t\"read-state\",\n\t\t\tbackendUrl,\n\t\t\tprincipalId,\n\t\t],\n\t\tmutationFn: async ({\n\t\t\tthreadId,\n\t\t\tisUnread,\n\t\t}: {\n\t\t\tthreadId: string;\n\t\t\tisUnread: boolean;\n\t\t}) =>\n\t\t\twithCredentialRenewal(getAuth, (auth) =>\n\t\t\t\tsetThreadReadState(backendUrl, auth, { threadId, isUnread }),\n\t\t\t),\n\t\tonMutate: ({ threadId, isUnread }) => {\n\t\t\tconst previous = readOverrides[threadId];\n\t\t\tsetReadOverrides((current) => ({ ...current, [threadId]: isUnread }));\n\t\t\treturn { previous, threadId };\n\t\t},\n\t\tonError: (_error, _variables, context) => {\n\t\t\tif (!context) return;\n\t\t\tsetReadOverrides((current) => {\n\t\t\t\tconst next = { ...current };\n\t\t\t\tif (context.previous === undefined) delete next[context.threadId];\n\t\t\t\telse next[context.threadId] = context.previous;\n\t\t\t\treturn next;\n\t\t\t});\n\t\t},\n\t\tonSuccess: (result) => {\n\t\t\tsetReadOverrides((current) => ({\n\t\t\t\t...current,\n\t\t\t\t[result.thread_id]: result.is_unread,\n\t\t\t}));\n\t\t\trefreshMutation.mutate(undefined, {\n\t\t\t\tonSettled: () => {\n\t\t\t\t\tsetReadOverrides((current) => {\n\t\t\t\t\t\tconst next = { ...current };\n\t\t\t\t\t\tdelete next[result.thread_id];\n\t\t\t\t\t\treturn next;\n\t\t\t\t\t});\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t});\n\n\tconst refresh = useCallback(\n\t\t() => refreshMutation.mutateAsync(),\n\t\t[refreshMutation.mutateAsync],\n\t);\n\tconst fetchNextPage = useCallback(\n\t\t() => loadMoreMutation.mutateAsync(),\n\t\t[loadMoreMutation.mutateAsync],\n\t);\n\n\treturn {\n\t\tconversations,\n\t\ttotalCount: usesRestHistory ? legacyHistory.totalCount : index.totalCount,\n\t\tisLoading:\n\t\t\tenabled &&\n\t\t\t(usesRestHistory\n\t\t\t\t? !legacyHistory.hasResolvedFirstPage\n\t\t\t\t: index.entries === null),\n\t\tisFetching:\n\t\t\trefreshMutation.isPending ||\n\t\t\tloadMoreMutation.isPending ||\n\t\t\tlegacyHistory.isFetching,\n\t\tisRefreshing: refreshMutation.isPending,\n\t\thasResolvedFirstPage: usesRestHistory\n\t\t\t? legacyHistory.hasResolvedFirstPage\n\t\t\t: index.entries !== null,\n\t\thasNextPage: usesRestHistory\n\t\t\t? legacyHistory.hasNextPage\n\t\t\t: index.hasNextPage,\n\t\tisFetchingNextPage: loadMoreMutation.isPending,\n\t\tfetchNextPage,\n\t\trefresh,\n\t\tarchiveConversation: archive.mutate,\n\t\tarchivePending: archive.isPending,\n\t\tsetConversationReadState: readState.mutate,\n\t\treadStatePending: readState.isPending,\n\t\t/** Pin or unpin a conversation; read-only on a backend without the route (`favoriteToggleAvailable`). */\n\t\tsetConversationFavorited: favorite.setFavorited,\n\t\tfavoritePending: favorite.isPending,\n\t\t/** The conversations whose pin toggle is in flight. */\n\t\tfavoritePendingThreadIds: favorite.pendingThreadIds,\n\t\t/** `false` once the backend answered 404 / 405 to the favorite route. */\n\t\tfavoriteToggleAvailable: favorite.isAvailable,\n\t\tconnection: index.connection,\n\t};\n}\n"],"names":["useConversationIndex","useRestConversationHistory","useState","useEffect","useMemo","useThreadFavorite","withFavoriteOverrides","useMutation","withCredentialRenewal","archiveThread","setThreadReadState","useCallback"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const reactQuery = require("@tanstack/react-query");
|
|
4
|
-
const
|
|
4
|
+
const require$$0 = require("react");
|
|
5
5
|
const credentialRenewal = require("../runtime/credential-renewal.cjs");
|
|
6
6
|
const api = require("./api.cjs");
|
|
7
7
|
const EMPTY_IDS = /* @__PURE__ */ new Set();
|
|
@@ -23,7 +23,7 @@ function useThreadArchive({
|
|
|
23
23
|
onArchived
|
|
24
24
|
}) {
|
|
25
25
|
const scope = archiveScope(backendUrl, principalId);
|
|
26
|
-
const [state, setState] =
|
|
26
|
+
const [state, setState] = require$$0.useState(() => ({
|
|
27
27
|
scope,
|
|
28
28
|
hidden: EMPTY_IDS,
|
|
29
29
|
pending: EMPTY_IDS
|
|
@@ -33,14 +33,14 @@ function useThreadArchive({
|
|
|
33
33
|
}
|
|
34
34
|
const hiddenThreadIds = state.scope === scope ? state.hidden : EMPTY_IDS;
|
|
35
35
|
const pendingThreadIds = state.scope === scope ? state.pending : EMPTY_IDS;
|
|
36
|
-
const [unavailableBackend, setUnavailableBackend] =
|
|
37
|
-
const scopeRef =
|
|
36
|
+
const [unavailableBackend, setUnavailableBackend] = require$$0.useState(null);
|
|
37
|
+
const scopeRef = require$$0.useRef(scope);
|
|
38
38
|
scopeRef.current = scope;
|
|
39
|
-
const onArchivedRef =
|
|
39
|
+
const onArchivedRef = require$$0.useRef(onArchived);
|
|
40
40
|
onArchivedRef.current = onArchived;
|
|
41
|
-
const inFlightRef =
|
|
41
|
+
const inFlightRef = require$$0.useRef(/* @__PURE__ */ new Set());
|
|
42
42
|
const writeKey = (write) => `${write.scope}::${write.threadId}`;
|
|
43
|
-
const update =
|
|
43
|
+
const update = require$$0.useCallback(
|
|
44
44
|
(forScope, patch) => {
|
|
45
45
|
setState((current) => {
|
|
46
46
|
const base = current.scope === forScope ? current : { scope: forScope, hidden: EMPTY_IDS, pending: EMPTY_IDS };
|
|
@@ -85,7 +85,7 @@ function useThreadArchive({
|
|
|
85
85
|
}
|
|
86
86
|
});
|
|
87
87
|
const mutate = mutation.mutate;
|
|
88
|
-
const archive =
|
|
88
|
+
const archive = require$$0.useCallback(
|
|
89
89
|
(threadId) => {
|
|
90
90
|
if (!threadId) return;
|
|
91
91
|
const write = { threadId, scope: scopeRef.current };
|
|
@@ -101,7 +101,7 @@ function useThreadArchive({
|
|
|
101
101
|
},
|
|
102
102
|
[mutate, update]
|
|
103
103
|
);
|
|
104
|
-
const release =
|
|
104
|
+
const release = require$$0.useCallback(
|
|
105
105
|
(threadIds) => {
|
|
106
106
|
if (threadIds.length === 0) return;
|
|
107
107
|
update(scopeRef.current, (current) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-thread-archive.cjs","sources":["../../src/threads/use-thread-archive.ts"],"sourcesContent":["/**\n * The archive action behind `SessionList`: one TanStack mutation over\n * `POST /api/conversations/threads/archive` with an optimistic hidden set.\n *\n * The row leaves the list the moment the user asks and stays hidden until\n * the caller reports that neither list source (the fetched page, the pushed\n * conversation index) lists it any more (`release`) — the page is patched on\n * the server's answer, but the index may still carry the row until the\n * publish that follows the commit lands. A failure drops the id and the row\n * comes back from the still-cached page. A 405, or a 404 that does not name\n * the thread, marks the route unavailable — the backend predates it, or has\n * no checkpointer — so the UI withdraws the action; a 404 for a thread that\n * is gone is a per-row failure (`isThreadArchiveUnavailableError`).\n *\n * One write per thread at a time: a second `archive` for a thread whose\n * write is in flight is a no-op (the guard is synchronous, so two calls in\n * one tick send one request). Everything is scoped to `(backendUrl,\n * principalId)`: a credential swap discards the hidden and pending sets, and\n * an answer for the previous identity is ignored when it lands, so a same-id\n * row under the new identity is never removed and the new user is never\n * moved off their active thread by the old user's archive.\n */\nimport { useMutation } from '@tanstack/react-query';\nimport { useCallback, useRef, useState } from 'react';\nimport { type CredentialResolver, withCredentialRenewal } from '../runtime/credential-renewal';\nimport { archiveThread, isThreadArchiveUnavailableError } from './api';\nimport type { RestConversationAuth } from './use-rest-conversation-history';\n\nexport interface UseThreadArchiveOptions {\n backendUrl: string;\n /** Non-secret identity in the mutation key (as the other thread writes key). */\n principalId: string;\n /** Resolved per request; called with `{ force: true }` when the host refuses the token. */\n getAuth: CredentialResolver<RestConversationAuth>;\n /** The server confirmed the archive: patch the caches, leave the thread if it is active. */\n onArchived?: (threadId: string) => void;\n}\n\nexport interface ThreadArchive {\n /** Threads hidden from the rows: asked to archive, not yet forgotten by every source. */\n hiddenThreadIds: ReadonlySet<string>;\n /** Archive a thread; a no-op while that thread's write is in flight. */\n archive: (threadId: string) => void;\n /** Drop hidden ids the caller has seen every source forget (never while their write is in flight). */\n release: (threadIds: readonly string[]) => void;\n /** True while any archive is in flight. */\n isPending: boolean;\n /** The threads whose archive is in flight — the action disables itself for these. */\n pendingThreadIds: ReadonlySet<string>;\n /** `false` once the backend answered that it has no archive route. */\n isAvailable: boolean;\n}\n\ninterface ScopedArchiveState {\n scope: string;\n hidden: ReadonlySet<string>;\n pending: ReadonlySet<string>;\n}\n\ninterface ArchiveWrite {\n threadId: string;\n /** The identity the write was issued for; an answer for another one is ignored. */\n scope: string;\n}\n\nconst EMPTY_IDS: ReadonlySet<string> = new Set();\n\nfunction archiveScope(backendUrl: string, principalId: string): string {\n return `${backendUrl}::${principalId}`;\n}\n\nfunction withId(ids: ReadonlySet<string>, threadId: string, present: boolean): ReadonlySet<string> {\n if (ids.has(threadId) === present) return ids;\n const next = new Set(ids);\n if (present) next.add(threadId);\n else next.delete(threadId);\n return next;\n}\n\n/** Backends already warned about, so an older agora logs one line per page load, not one per click. */\nconst warnedUnavailableBackends = new Set<string>();\n\n/** Test seam: forget which backends were warned about. */\nexport function resetThreadArchiveUnavailableWarnings(): void {\n warnedUnavailableBackends.clear();\n}\n\nexport function useThreadArchive({\n backendUrl,\n principalId,\n getAuth,\n onArchived,\n}: UseThreadArchiveOptions): ThreadArchive {\n const scope = archiveScope(backendUrl, principalId);\n const [state, setState] = useState<ScopedArchiveState>(() => ({\n scope,\n hidden: EMPTY_IDS,\n pending: EMPTY_IDS,\n }));\n // An identity swap discards everything held for the previous identity\n // (derived-state reset during render; see `useThreadFieldOverride`).\n if (state.scope !== scope) {\n setState({ scope, hidden: EMPTY_IDS, pending: EMPTY_IDS });\n }\n const hiddenThreadIds = state.scope === scope ? state.hidden : EMPTY_IDS;\n const pendingThreadIds = state.scope === scope ? state.pending : EMPTY_IDS;\n // The route is a property of the backend, not of who is asking.\n const [unavailableBackend, setUnavailableBackend] = useState<string | null>(null);\n\n const scopeRef = useRef(scope);\n scopeRef.current = scope;\n const onArchivedRef = useRef(onArchived);\n onArchivedRef.current = onArchived;\n // Writes in flight, keyed by identity and thread: the synchronous guard\n // behind the one-write-per-thread rule. A previous identity's entries are\n // left to expire with their answers (which the scope guard drops).\n const inFlightRef = useRef<Set<string>>(new Set());\n const writeKey = (write: ArchiveWrite) => `${write.scope}::${write.threadId}`;\n\n const update = useCallback(\n (forScope: string, patch: (current: ScopedArchiveState) => ScopedArchiveState) => {\n setState((current) => {\n const base: ScopedArchiveState =\n current.scope === forScope ? current : { scope: forScope, hidden: EMPTY_IDS, pending: EMPTY_IDS };\n const next = patch(base);\n return next === base && current.scope === forScope ? current : next;\n });\n },\n [],\n );\n\n const mutation = useMutation({\n mutationKey: ['conversation-history', 'archive', backendUrl, principalId],\n mutationFn: async (write: ArchiveWrite) => {\n await withCredentialRenewal(getAuth, (auth) => archiveThread(backendUrl, auth, write.threadId));\n },\n onSuccess: (_result, write) => {\n inFlightRef.current.delete(writeKey(write));\n if (scopeRef.current !== write.scope) return;\n update(write.scope, (current) => ({\n ...current,\n pending: withId(current.pending, write.threadId, false),\n }));\n onArchivedRef.current?.(write.threadId);\n },\n onError: (error, write) => {\n inFlightRef.current.delete(writeKey(write));\n if (isThreadArchiveUnavailableError(error)) {\n setUnavailableBackend(backendUrl);\n if (!warnedUnavailableBackends.has(backendUrl)) {\n warnedUnavailableBackends.add(backendUrl);\n console.warn(\n '[AthenaSDK] This backend has no POST /api/conversations/threads/archive route (older agora, or no checkpointer); sessions cannot be archived from here.',\n );\n }\n }\n if (scopeRef.current !== write.scope) return;\n // The row comes back from the still-cached page.\n update(write.scope, (current) => ({\n ...current,\n pending: withId(current.pending, write.threadId, false),\n hidden: withId(current.hidden, write.threadId, false),\n }));\n },\n });\n const mutate = mutation.mutate;\n\n const archive = useCallback(\n (threadId: string) => {\n if (!threadId) return;\n const write: ArchiveWrite = { threadId, scope: scopeRef.current };\n const key = writeKey(write);\n if (inFlightRef.current.has(key)) return;\n inFlightRef.current.add(key);\n update(write.scope, (current) => ({\n ...current,\n pending: withId(current.pending, threadId, true),\n hidden: withId(current.hidden, threadId, true),\n }));\n mutate(write);\n },\n [mutate, update],\n );\n\n const release = useCallback(\n (threadIds: readonly string[]) => {\n if (threadIds.length === 0) return;\n update(scopeRef.current, (current) => {\n // A hidden row with a write in flight stays hidden whatever the\n // sources say: they have not seen the archive yet.\n const releasable = threadIds.filter(\n (threadId) => current.hidden.has(threadId) && !current.pending.has(threadId),\n );\n if (releasable.length === 0) return current;\n const hidden = new Set(current.hidden);\n for (const threadId of releasable) hidden.delete(threadId);\n return { ...current, hidden };\n });\n },\n [update],\n );\n\n return {\n hiddenThreadIds,\n archive,\n release,\n isPending: pendingThreadIds.size > 0,\n pendingThreadIds,\n isAvailable: unavailableBackend !== backendUrl,\n };\n}\n"],"names":["useState","useRef","useCallback","useMutation","withCredentialRenewal","archiveThread","isThreadArchiveUnavailableError"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"use-thread-archive.cjs","sources":["../../src/threads/use-thread-archive.ts"],"sourcesContent":["/**\n * The archive action behind `SessionList`: one TanStack mutation over\n * `POST /api/conversations/threads/archive` with an optimistic hidden set.\n *\n * The row leaves the list the moment the user asks and stays hidden until\n * the caller reports that neither list source (the fetched page, the pushed\n * conversation index) lists it any more (`release`) — the page is patched on\n * the server's answer, but the index may still carry the row until the\n * publish that follows the commit lands. A failure drops the id and the row\n * comes back from the still-cached page. A 405, or a 404 that does not name\n * the thread, marks the route unavailable — the backend predates it, or has\n * no checkpointer — so the UI withdraws the action; a 404 for a thread that\n * is gone is a per-row failure (`isThreadArchiveUnavailableError`).\n *\n * One write per thread at a time: a second `archive` for a thread whose\n * write is in flight is a no-op (the guard is synchronous, so two calls in\n * one tick send one request). Everything is scoped to `(backendUrl,\n * principalId)`: a credential swap discards the hidden and pending sets, and\n * an answer for the previous identity is ignored when it lands, so a same-id\n * row under the new identity is never removed and the new user is never\n * moved off their active thread by the old user's archive.\n */\nimport { useMutation } from '@tanstack/react-query';\nimport { useCallback, useRef, useState } from 'react';\nimport { type CredentialResolver, withCredentialRenewal } from '../runtime/credential-renewal';\nimport { archiveThread, isThreadArchiveUnavailableError } from './api';\nimport type { RestConversationAuth } from './use-rest-conversation-history';\n\nexport interface UseThreadArchiveOptions {\n backendUrl: string;\n /** Non-secret identity in the mutation key (as the other thread writes key). */\n principalId: string;\n /** Resolved per request; called with `{ force: true }` when the host refuses the token. */\n getAuth: CredentialResolver<RestConversationAuth>;\n /** The server confirmed the archive: patch the caches, leave the thread if it is active. */\n onArchived?: (threadId: string) => void;\n}\n\nexport interface ThreadArchive {\n /** Threads hidden from the rows: asked to archive, not yet forgotten by every source. */\n hiddenThreadIds: ReadonlySet<string>;\n /** Archive a thread; a no-op while that thread's write is in flight. */\n archive: (threadId: string) => void;\n /** Drop hidden ids the caller has seen every source forget (never while their write is in flight). */\n release: (threadIds: readonly string[]) => void;\n /** True while any archive is in flight. */\n isPending: boolean;\n /** The threads whose archive is in flight — the action disables itself for these. */\n pendingThreadIds: ReadonlySet<string>;\n /** `false` once the backend answered that it has no archive route. */\n isAvailable: boolean;\n}\n\ninterface ScopedArchiveState {\n scope: string;\n hidden: ReadonlySet<string>;\n pending: ReadonlySet<string>;\n}\n\ninterface ArchiveWrite {\n threadId: string;\n /** The identity the write was issued for; an answer for another one is ignored. */\n scope: string;\n}\n\nconst EMPTY_IDS: ReadonlySet<string> = new Set();\n\nfunction archiveScope(backendUrl: string, principalId: string): string {\n return `${backendUrl}::${principalId}`;\n}\n\nfunction withId(ids: ReadonlySet<string>, threadId: string, present: boolean): ReadonlySet<string> {\n if (ids.has(threadId) === present) return ids;\n const next = new Set(ids);\n if (present) next.add(threadId);\n else next.delete(threadId);\n return next;\n}\n\n/** Backends already warned about, so an older agora logs one line per page load, not one per click. */\nconst warnedUnavailableBackends = new Set<string>();\n\n/** Test seam: forget which backends were warned about. */\nexport function resetThreadArchiveUnavailableWarnings(): void {\n warnedUnavailableBackends.clear();\n}\n\nexport function useThreadArchive({\n backendUrl,\n principalId,\n getAuth,\n onArchived,\n}: UseThreadArchiveOptions): ThreadArchive {\n const scope = archiveScope(backendUrl, principalId);\n const [state, setState] = useState<ScopedArchiveState>(() => ({\n scope,\n hidden: EMPTY_IDS,\n pending: EMPTY_IDS,\n }));\n // An identity swap discards everything held for the previous identity\n // (derived-state reset during render; see `useThreadFieldOverride`).\n if (state.scope !== scope) {\n setState({ scope, hidden: EMPTY_IDS, pending: EMPTY_IDS });\n }\n const hiddenThreadIds = state.scope === scope ? state.hidden : EMPTY_IDS;\n const pendingThreadIds = state.scope === scope ? state.pending : EMPTY_IDS;\n // The route is a property of the backend, not of who is asking.\n const [unavailableBackend, setUnavailableBackend] = useState<string | null>(null);\n\n const scopeRef = useRef(scope);\n scopeRef.current = scope;\n const onArchivedRef = useRef(onArchived);\n onArchivedRef.current = onArchived;\n // Writes in flight, keyed by identity and thread: the synchronous guard\n // behind the one-write-per-thread rule. A previous identity's entries are\n // left to expire with their answers (which the scope guard drops).\n const inFlightRef = useRef<Set<string>>(new Set());\n const writeKey = (write: ArchiveWrite) => `${write.scope}::${write.threadId}`;\n\n const update = useCallback(\n (forScope: string, patch: (current: ScopedArchiveState) => ScopedArchiveState) => {\n setState((current) => {\n const base: ScopedArchiveState =\n current.scope === forScope ? current : { scope: forScope, hidden: EMPTY_IDS, pending: EMPTY_IDS };\n const next = patch(base);\n return next === base && current.scope === forScope ? current : next;\n });\n },\n [],\n );\n\n const mutation = useMutation({\n mutationKey: ['conversation-history', 'archive', backendUrl, principalId],\n mutationFn: async (write: ArchiveWrite) => {\n await withCredentialRenewal(getAuth, (auth) => archiveThread(backendUrl, auth, write.threadId));\n },\n onSuccess: (_result, write) => {\n inFlightRef.current.delete(writeKey(write));\n if (scopeRef.current !== write.scope) return;\n update(write.scope, (current) => ({\n ...current,\n pending: withId(current.pending, write.threadId, false),\n }));\n onArchivedRef.current?.(write.threadId);\n },\n onError: (error, write) => {\n inFlightRef.current.delete(writeKey(write));\n if (isThreadArchiveUnavailableError(error)) {\n setUnavailableBackend(backendUrl);\n if (!warnedUnavailableBackends.has(backendUrl)) {\n warnedUnavailableBackends.add(backendUrl);\n console.warn(\n '[AthenaSDK] This backend has no POST /api/conversations/threads/archive route (older agora, or no checkpointer); sessions cannot be archived from here.',\n );\n }\n }\n if (scopeRef.current !== write.scope) return;\n // The row comes back from the still-cached page.\n update(write.scope, (current) => ({\n ...current,\n pending: withId(current.pending, write.threadId, false),\n hidden: withId(current.hidden, write.threadId, false),\n }));\n },\n });\n const mutate = mutation.mutate;\n\n const archive = useCallback(\n (threadId: string) => {\n if (!threadId) return;\n const write: ArchiveWrite = { threadId, scope: scopeRef.current };\n const key = writeKey(write);\n if (inFlightRef.current.has(key)) return;\n inFlightRef.current.add(key);\n update(write.scope, (current) => ({\n ...current,\n pending: withId(current.pending, threadId, true),\n hidden: withId(current.hidden, threadId, true),\n }));\n mutate(write);\n },\n [mutate, update],\n );\n\n const release = useCallback(\n (threadIds: readonly string[]) => {\n if (threadIds.length === 0) return;\n update(scopeRef.current, (current) => {\n // A hidden row with a write in flight stays hidden whatever the\n // sources say: they have not seen the archive yet.\n const releasable = threadIds.filter(\n (threadId) => current.hidden.has(threadId) && !current.pending.has(threadId),\n );\n if (releasable.length === 0) return current;\n const hidden = new Set(current.hidden);\n for (const threadId of releasable) hidden.delete(threadId);\n return { ...current, hidden };\n });\n },\n [update],\n );\n\n return {\n hiddenThreadIds,\n archive,\n release,\n isPending: pendingThreadIds.size > 0,\n pendingThreadIds,\n isAvailable: unavailableBackend !== backendUrl,\n };\n}\n"],"names":["useState","useRef","useCallback","useMutation","withCredentialRenewal","archiveThread","isThreadArchiveUnavailableError"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const
|
|
3
|
+
const require$$0 = require("react");
|
|
4
4
|
const api = require("./api.cjs");
|
|
5
5
|
const useThreadFieldOverride = require("./use-thread-field-override.cjs");
|
|
6
6
|
const FAVORITE_UNAVAILABLE_WARNING = "[AthenaSDK] This backend has no POST /api/conversations/threads/favorite route yet; session pins stay read-only until it deploys.";
|
|
@@ -28,7 +28,7 @@ function useThreadFavorite({
|
|
|
28
28
|
onServerTruth: onServerTruth ? ({ threadId, value }) => onServerTruth({ threadId, isFavorited: value }) : void 0
|
|
29
29
|
});
|
|
30
30
|
const set = field.set;
|
|
31
|
-
const setFavorited =
|
|
31
|
+
const setFavorited = require$$0.useCallback(
|
|
32
32
|
({ threadId, isFavorited }) => set({ threadId, value: isFavorited }),
|
|
33
33
|
[set]
|
|
34
34
|
);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-thread-favorite.cjs","sources":["../../src/threads/use-thread-favorite.ts"],"sourcesContent":["/**\n * The pin toggle behind `SessionList` and the conversation-history hooks:\n * `useThreadFieldOverride` over `POST /api/conversations/threads/favorite`\n * (see that module for the optimistic-override, rollback, serialization and\n * identity-scoping contract). A 404 / 405 marks the toggle unavailable — the\n * backend predates the route — so the UI falls back to the read-only pin\n * instead of failing on every click.\n */\nimport { useCallback } from 'react';\nimport type { CredentialResolver } from '../runtime/credential-renewal';\nimport { isThreadFavoriteUnavailableError, setThreadFavorite } from './api';\nimport type { RestConversationAuth } from './use-rest-conversation-history';\nimport {\n resetThreadFieldUnavailableWarnings,\n type ThreadFieldTarget,\n useThreadFieldOverride,\n} from './use-thread-field-override';\n\nexport interface ThreadFavoriteTarget {\n threadId: string;\n isFavorited: boolean;\n}\n\n/** The two fields the override layer reads and writes on a list row. */\nexport interface FavoriteRow {\n threadId: string;\n isFavorited?: boolean;\n}\n\nexport interface UseThreadFavoriteOptions {\n backendUrl: string;\n /** Non-secret identity in the mutation key (as the read-state mutation keys). */\n principalId: string;\n /** Resolved per request; called with `{ force: true }` when the host refuses the token. */\n getAuth: CredentialResolver<RestConversationAuth>;\n /**\n * The rows as the list sources currently report them, BEFORE overrides. An\n * override is dropped once its row reports the same value.\n */\n rows: readonly FavoriteRow[];\n /** Write the server's answer into the list caches (`patchConversation`). */\n onServerTruth?: (result: ThreadFavoriteTarget) => void;\n}\n\nexport interface ThreadFavoriteToggle {\n /** Optimistic, then server-confirmed, values layered over the list sources, keyed by thread id. */\n overrides: Readonly<Record<string, boolean>>;\n /**\n * Pin or unpin a thread. Flips the row at once; while that thread's write\n * is in flight the call only records the desired value (see module doc).\n */\n setFavorited: (target: ThreadFavoriteTarget) => void;\n /** True while any toggle is in flight. */\n isPending: boolean;\n /** The threads whose toggle is in flight — a pin control disables itself for these. */\n pendingThreadIds: ReadonlySet<string>;\n /**\n * `false` once the backend answered 404 / 405: the route is not deployed\n * there, and the UI shows the read-only pin instead of a toggle.\n */\n isAvailable: boolean;\n}\n\n/** Test seam: forget which backends were warned about (shared with the other field writes). */\nexport const resetThreadFavoriteUnavailableWarnings = resetThreadFieldUnavailableWarnings;\n\nconst FAVORITE_UNAVAILABLE_WARNING =\n '[AthenaSDK] This backend has no POST /api/conversations/threads/favorite route yet; session pins stay read-only until it deploys.';\n\nconst readFavorite = (row: FavoriteRow): boolean => row.isFavorited ?? false;\n\nexport function useThreadFavorite({\n backendUrl,\n principalId,\n getAuth,\n rows,\n onServerTruth,\n}: UseThreadFavoriteOptions): ThreadFavoriteToggle {\n const field = useThreadFieldOverride<boolean, FavoriteRow>({\n field: 'favorite',\n backendUrl,\n principalId,\n getAuth,\n rows,\n readRow: readFavorite,\n write: async (auth, { threadId, value }) => {\n const result = await setThreadFavorite(backendUrl, auth, { threadId, isFavorited: value });\n return { threadId: result.thread_id, value: result.is_favorited };\n },\n isUnavailableError: isThreadFavoriteUnavailableError,\n unavailableWarning: FAVORITE_UNAVAILABLE_WARNING,\n onServerTruth: onServerTruth\n ? ({ threadId, value }: ThreadFieldTarget<boolean>) =>\n onServerTruth({ threadId, isFavorited: value })\n : undefined,\n });\n const set = field.set;\n const setFavorited = useCallback(\n ({ threadId, isFavorited }: ThreadFavoriteTarget) => set({ threadId, value: isFavorited }),\n [set],\n );\n return {\n overrides: field.overrides,\n setFavorited,\n isPending: field.isPending,\n pendingThreadIds: field.pendingThreadIds,\n isAvailable: field.isAvailable,\n };\n}\n\n/** The row with its override applied, or the row itself when it has none. */\nexport function withFavoriteOverride<T extends FavoriteRow>(\n row: T,\n overrides: Readonly<Record<string, boolean>>,\n): T {\n const override = overrides[row.threadId];\n return override === undefined || override === row.isFavorited\n ? row\n : { ...row, isFavorited: override };\n}\n\n/** Every row with its override applied. */\nexport function withFavoriteOverrides<T extends FavoriteRow>(\n rows: readonly T[],\n overrides: Readonly<Record<string, boolean>>,\n): T[] {\n return rows.map((row) => withFavoriteOverride(row, overrides));\n}\n"],"names":["useThreadFieldOverride","setThreadFavorite","isThreadFavoriteUnavailableError","useCallback"],"mappings":";;;;;AAkEA,MAAM,+BACJ;AAEF,MAAM,eAAe,CAAC,QAA8B,IAAI,eAAe;AAEhE,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAmD;AACjD,QAAM,QAAQA,uBAAAA,uBAA6C;AAAA,IACzD,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT,OAAO,OAAO,MAAM,EAAE,UAAU,YAAY;AAC1C,YAAM,SAAS,MAAMC,IAAAA,kBAAkB,YAAY,MAAM,EAAE,UAAU,aAAa,OAAO;AACzF,aAAO,EAAE,UAAU,OAAO,WAAW,OAAO,OAAO,aAAA;AAAA,IACrD;AAAA,IACA,oBAAoBC,IAAAA;AAAAA,IACpB,oBAAoB;AAAA,IACpB,eAAe,gBACX,CAAC,EAAE,UAAU,MAAA,MACX,cAAc,EAAE,UAAU,aAAa,MAAA,CAAO,IAChD;AAAA,EAAA,CACL;AACD,QAAM,MAAM,MAAM;AAClB,QAAM,eAAeC,
|
|
1
|
+
{"version":3,"file":"use-thread-favorite.cjs","sources":["../../src/threads/use-thread-favorite.ts"],"sourcesContent":["/**\n * The pin toggle behind `SessionList` and the conversation-history hooks:\n * `useThreadFieldOverride` over `POST /api/conversations/threads/favorite`\n * (see that module for the optimistic-override, rollback, serialization and\n * identity-scoping contract). A 404 / 405 marks the toggle unavailable — the\n * backend predates the route — so the UI falls back to the read-only pin\n * instead of failing on every click.\n */\nimport { useCallback } from 'react';\nimport type { CredentialResolver } from '../runtime/credential-renewal';\nimport { isThreadFavoriteUnavailableError, setThreadFavorite } from './api';\nimport type { RestConversationAuth } from './use-rest-conversation-history';\nimport {\n resetThreadFieldUnavailableWarnings,\n type ThreadFieldTarget,\n useThreadFieldOverride,\n} from './use-thread-field-override';\n\nexport interface ThreadFavoriteTarget {\n threadId: string;\n isFavorited: boolean;\n}\n\n/** The two fields the override layer reads and writes on a list row. */\nexport interface FavoriteRow {\n threadId: string;\n isFavorited?: boolean;\n}\n\nexport interface UseThreadFavoriteOptions {\n backendUrl: string;\n /** Non-secret identity in the mutation key (as the read-state mutation keys). */\n principalId: string;\n /** Resolved per request; called with `{ force: true }` when the host refuses the token. */\n getAuth: CredentialResolver<RestConversationAuth>;\n /**\n * The rows as the list sources currently report them, BEFORE overrides. An\n * override is dropped once its row reports the same value.\n */\n rows: readonly FavoriteRow[];\n /** Write the server's answer into the list caches (`patchConversation`). */\n onServerTruth?: (result: ThreadFavoriteTarget) => void;\n}\n\nexport interface ThreadFavoriteToggle {\n /** Optimistic, then server-confirmed, values layered over the list sources, keyed by thread id. */\n overrides: Readonly<Record<string, boolean>>;\n /**\n * Pin or unpin a thread. Flips the row at once; while that thread's write\n * is in flight the call only records the desired value (see module doc).\n */\n setFavorited: (target: ThreadFavoriteTarget) => void;\n /** True while any toggle is in flight. */\n isPending: boolean;\n /** The threads whose toggle is in flight — a pin control disables itself for these. */\n pendingThreadIds: ReadonlySet<string>;\n /**\n * `false` once the backend answered 404 / 405: the route is not deployed\n * there, and the UI shows the read-only pin instead of a toggle.\n */\n isAvailable: boolean;\n}\n\n/** Test seam: forget which backends were warned about (shared with the other field writes). */\nexport const resetThreadFavoriteUnavailableWarnings = resetThreadFieldUnavailableWarnings;\n\nconst FAVORITE_UNAVAILABLE_WARNING =\n '[AthenaSDK] This backend has no POST /api/conversations/threads/favorite route yet; session pins stay read-only until it deploys.';\n\nconst readFavorite = (row: FavoriteRow): boolean => row.isFavorited ?? false;\n\nexport function useThreadFavorite({\n backendUrl,\n principalId,\n getAuth,\n rows,\n onServerTruth,\n}: UseThreadFavoriteOptions): ThreadFavoriteToggle {\n const field = useThreadFieldOverride<boolean, FavoriteRow>({\n field: 'favorite',\n backendUrl,\n principalId,\n getAuth,\n rows,\n readRow: readFavorite,\n write: async (auth, { threadId, value }) => {\n const result = await setThreadFavorite(backendUrl, auth, { threadId, isFavorited: value });\n return { threadId: result.thread_id, value: result.is_favorited };\n },\n isUnavailableError: isThreadFavoriteUnavailableError,\n unavailableWarning: FAVORITE_UNAVAILABLE_WARNING,\n onServerTruth: onServerTruth\n ? ({ threadId, value }: ThreadFieldTarget<boolean>) =>\n onServerTruth({ threadId, isFavorited: value })\n : undefined,\n });\n const set = field.set;\n const setFavorited = useCallback(\n ({ threadId, isFavorited }: ThreadFavoriteTarget) => set({ threadId, value: isFavorited }),\n [set],\n );\n return {\n overrides: field.overrides,\n setFavorited,\n isPending: field.isPending,\n pendingThreadIds: field.pendingThreadIds,\n isAvailable: field.isAvailable,\n };\n}\n\n/** The row with its override applied, or the row itself when it has none. */\nexport function withFavoriteOverride<T extends FavoriteRow>(\n row: T,\n overrides: Readonly<Record<string, boolean>>,\n): T {\n const override = overrides[row.threadId];\n return override === undefined || override === row.isFavorited\n ? row\n : { ...row, isFavorited: override };\n}\n\n/** Every row with its override applied. */\nexport function withFavoriteOverrides<T extends FavoriteRow>(\n rows: readonly T[],\n overrides: Readonly<Record<string, boolean>>,\n): T[] {\n return rows.map((row) => withFavoriteOverride(row, overrides));\n}\n"],"names":["useThreadFieldOverride","setThreadFavorite","isThreadFavoriteUnavailableError","useCallback"],"mappings":";;;;;AAkEA,MAAM,+BACJ;AAEF,MAAM,eAAe,CAAC,QAA8B,IAAI,eAAe;AAEhE,SAAS,kBAAkB;AAAA,EAChC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAmD;AACjD,QAAM,QAAQA,uBAAAA,uBAA6C;AAAA,IACzD,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,SAAS;AAAA,IACT,OAAO,OAAO,MAAM,EAAE,UAAU,YAAY;AAC1C,YAAM,SAAS,MAAMC,IAAAA,kBAAkB,YAAY,MAAM,EAAE,UAAU,aAAa,OAAO;AACzF,aAAO,EAAE,UAAU,OAAO,WAAW,OAAO,OAAO,aAAA;AAAA,IACrD;AAAA,IACA,oBAAoBC,IAAAA;AAAAA,IACpB,oBAAoB;AAAA,IACpB,eAAe,gBACX,CAAC,EAAE,UAAU,MAAA,MACX,cAAc,EAAE,UAAU,aAAa,MAAA,CAAO,IAChD;AAAA,EAAA,CACL;AACD,QAAM,MAAM,MAAM;AAClB,QAAM,eAAeC,WAAAA;AAAAA,IACnB,CAAC,EAAE,UAAU,kBAAwC,IAAI,EAAE,UAAU,OAAO,aAAa;AAAA,IACzF,CAAC,GAAG;AAAA,EAAA;AAEN,SAAO;AAAA,IACL,WAAW,MAAM;AAAA,IACjB;AAAA,IACA,WAAW,MAAM;AAAA,IACjB,kBAAkB,MAAM;AAAA,IACxB,aAAa,MAAM;AAAA,EAAA;AAEvB;AAGO,SAAS,qBACd,KACA,WACG;AACH,QAAM,WAAW,UAAU,IAAI,QAAQ;AACvC,SAAO,aAAa,UAAa,aAAa,IAAI,cAC9C,MACA,EAAE,GAAG,KAAK,aAAa,SAAA;AAC7B;AAGO,SAAS,sBACd,MACA,WACK;AACL,SAAO,KAAK,IAAI,CAAC,QAAQ,qBAAqB,KAAK,SAAS,CAAC;AAC/D;;;;"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const reactQuery = require("@tanstack/react-query");
|
|
4
|
-
const
|
|
4
|
+
const require$$0 = require("react");
|
|
5
5
|
const credentialRenewal = require("../runtime/credential-renewal.cjs");
|
|
6
6
|
const EMPTY_PENDING = /* @__PURE__ */ new Set();
|
|
7
7
|
function fieldScope(backendUrl, principalId) {
|
|
@@ -30,7 +30,7 @@ function useThreadFieldOverride({
|
|
|
30
30
|
equals = strictEquals
|
|
31
31
|
}) {
|
|
32
32
|
const scope = fieldScope(backendUrl, principalId);
|
|
33
|
-
const [state, setState] =
|
|
33
|
+
const [state, setState] = require$$0.useState(() => ({
|
|
34
34
|
scope,
|
|
35
35
|
overrides: {},
|
|
36
36
|
pending: EMPTY_PENDING
|
|
@@ -38,36 +38,36 @@ function useThreadFieldOverride({
|
|
|
38
38
|
if (state.scope !== scope) {
|
|
39
39
|
setState({ scope, overrides: {}, pending: EMPTY_PENDING });
|
|
40
40
|
}
|
|
41
|
-
const emptyOverridesRef =
|
|
41
|
+
const emptyOverridesRef = require$$0.useRef(Object.freeze({}));
|
|
42
42
|
const overrides = state.scope === scope ? state.overrides : emptyOverridesRef.current;
|
|
43
43
|
const pendingThreadIds = state.scope === scope ? state.pending : EMPTY_PENDING;
|
|
44
|
-
const [unavailableBackend, setUnavailableBackend] =
|
|
45
|
-
const scopeRef =
|
|
44
|
+
const [unavailableBackend, setUnavailableBackend] = require$$0.useState(null);
|
|
45
|
+
const scopeRef = require$$0.useRef(scope);
|
|
46
46
|
scopeRef.current = scope;
|
|
47
|
-
const overridesRef =
|
|
47
|
+
const overridesRef = require$$0.useRef(overrides);
|
|
48
48
|
overridesRef.current = overrides;
|
|
49
|
-
const readRowRef =
|
|
49
|
+
const readRowRef = require$$0.useRef(readRow);
|
|
50
50
|
readRowRef.current = readRow;
|
|
51
|
-
const writeRef =
|
|
51
|
+
const writeRef = require$$0.useRef(write);
|
|
52
52
|
writeRef.current = write;
|
|
53
|
-
const isUnavailableErrorRef =
|
|
53
|
+
const isUnavailableErrorRef = require$$0.useRef(isUnavailableError);
|
|
54
54
|
isUnavailableErrorRef.current = isUnavailableError;
|
|
55
|
-
const unavailableWarningRef =
|
|
55
|
+
const unavailableWarningRef = require$$0.useRef(unavailableWarning);
|
|
56
56
|
unavailableWarningRef.current = unavailableWarning;
|
|
57
|
-
const onServerTruthRef =
|
|
57
|
+
const onServerTruthRef = require$$0.useRef(onServerTruth);
|
|
58
58
|
onServerTruthRef.current = onServerTruth;
|
|
59
|
-
const equalsRef =
|
|
59
|
+
const equalsRef = require$$0.useRef(equals);
|
|
60
60
|
equalsRef.current = equals;
|
|
61
|
-
const inFlightRef =
|
|
62
|
-
const queuedRef =
|
|
63
|
-
const seqRef =
|
|
64
|
-
const bookkeepingScopeRef =
|
|
61
|
+
const inFlightRef = require$$0.useRef(/* @__PURE__ */ new Map());
|
|
62
|
+
const queuedRef = require$$0.useRef(/* @__PURE__ */ new Map());
|
|
63
|
+
const seqRef = require$$0.useRef(0);
|
|
64
|
+
const bookkeepingScopeRef = require$$0.useRef(scope);
|
|
65
65
|
if (bookkeepingScopeRef.current !== scope) {
|
|
66
66
|
bookkeepingScopeRef.current = scope;
|
|
67
67
|
inFlightRef.current = /* @__PURE__ */ new Map();
|
|
68
68
|
queuedRef.current = /* @__PURE__ */ new Map();
|
|
69
69
|
}
|
|
70
|
-
const update =
|
|
70
|
+
const update = require$$0.useCallback(
|
|
71
71
|
(forScope, patch) => {
|
|
72
72
|
setState((current) => {
|
|
73
73
|
const base = current.scope === forScope ? current : { scope: forScope, overrides: {}, pending: EMPTY_PENDING };
|
|
@@ -77,7 +77,7 @@ function useThreadFieldOverride({
|
|
|
77
77
|
},
|
|
78
78
|
[]
|
|
79
79
|
);
|
|
80
|
-
|
|
80
|
+
require$$0.useEffect(() => {
|
|
81
81
|
const caughtUp = Object.keys(overrides).filter((threadId) => {
|
|
82
82
|
if (pendingThreadIds.has(threadId)) return false;
|
|
83
83
|
const row = rows.find((candidate) => candidate.threadId === threadId);
|
|
@@ -155,9 +155,9 @@ function useThreadFieldOverride({
|
|
|
155
155
|
}));
|
|
156
156
|
mutate({ ...write2, scope: forScope, seq });
|
|
157
157
|
}
|
|
158
|
-
const startWriteRef =
|
|
158
|
+
const startWriteRef = require$$0.useRef(startWrite);
|
|
159
159
|
startWriteRef.current = startWrite;
|
|
160
|
-
const set =
|
|
160
|
+
const set = require$$0.useCallback(
|
|
161
161
|
({ threadId, value }) => {
|
|
162
162
|
const forScope = scopeRef.current;
|
|
163
163
|
const previous = overridesRef.current[threadId];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-thread-field-override.cjs","sources":["../../src/threads/use-thread-field-override.ts"],"sourcesContent":["/**\n * The optimistic per-thread field write behind the pin (`useThreadFavorite`)\n * and the rename (`useThreadRename`): one TanStack mutation over a REST\n * route with an override map layered over the list rows.\n *\n * Why overrides rather than a cache patch alone: a row's field is folded from\n * two sources — the fetched page and the pushed conversation index — and a\n * push that predates the write would clobber a patched page. The override\n * sits over both until the sources report the same value, then drops away so\n * they own the field again (a later write from another client is never\n * masked). A failure restores the previous value; a 404 / 405 marks the\n * write unavailable — the backend predates the route — so the UI withdraws\n * the control instead of failing on every use.\n *\n * Same-thread writes are serialized: while one is in flight, a further write\n * for that thread flips the row at once but only records the desired value,\n * and at most one follow-up write is sent — with that value — once the\n * in-flight one has answered. Two independent writes for one thread never\n * race, so the server cannot end on an earlier request's value.\n *\n * Everything the hook holds is scoped to `(backendUrl, principalId)`: a\n * credential swap under the same list reads an empty override map, and a\n * write that was in flight for the previous identity is ignored when it\n * answers, so a same-id row under the new identity never inherits the old\n * one's value.\n */\nimport { useMutation } from '@tanstack/react-query';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { type CredentialResolver, withCredentialRenewal } from '../runtime/credential-renewal';\nimport type { RestConversationAuth } from './use-rest-conversation-history';\n\nexport interface ThreadFieldTarget<T> {\n threadId: string;\n value: T;\n}\n\n/** The one field every row must carry: its identity. */\nexport interface ThreadFieldRow {\n threadId: string;\n}\n\nexport interface UseThreadFieldOverrideOptions<T, R extends ThreadFieldRow> {\n /** Names the field: part of the mutation key and of the one-per-backend warning. */\n field: string;\n backendUrl: string;\n /** Non-secret identity in the mutation key (as the read-state mutation keys). */\n principalId: string;\n /** Resolved per request; called with `{ force: true }` when the host refuses the token. */\n getAuth: CredentialResolver<RestConversationAuth>;\n /**\n * The rows as the list sources currently report them, BEFORE overrides. An\n * override is dropped once its row reports the same value.\n */\n rows: readonly R[];\n /** The field as a source row reports it; `undefined` when the row does not carry it. */\n readRow: (row: R) => T | undefined;\n /** The write; resolves to the server's truth after it. */\n write: (auth: RestConversationAuth, target: ThreadFieldTarget<T>) => Promise<ThreadFieldTarget<T>>;\n /** True for the rejection that means the backend has no such route (404 / 405). */\n isUnavailableError: (error: unknown) => boolean;\n /** Logged once per backend when the route is found missing. */\n unavailableWarning: string;\n /** Write the server's answer into the list caches (`patchConversation`). */\n onServerTruth?: (truth: ThreadFieldTarget<T>) => void;\n /** Value equality (default `===`). */\n equals?: (a: T, b: T) => boolean;\n}\n\nexport interface ThreadFieldOverride<T> {\n /** Optimistic, then server-confirmed, values layered over the list sources, keyed by thread id. */\n overrides: Readonly<Record<string, T>>;\n /**\n * Write the field. Flips the row at once; while that thread's write is in\n * flight the call only records the desired value (see module doc).\n */\n set: (target: ThreadFieldTarget<T>) => void;\n /** True while any write is in flight. */\n isPending: boolean;\n /** The threads whose write is in flight — a control disables itself for these. */\n pendingThreadIds: ReadonlySet<string>;\n /**\n * `false` once the backend answered 404 / 405: the route is not deployed\n * there, and the UI withdraws the control.\n */\n isAvailable: boolean;\n}\n\n/** The hook's state, tagged with the identity it belongs to. */\ninterface ScopedFieldState<T> {\n scope: string;\n overrides: Record<string, T>;\n pending: ReadonlySet<string>;\n}\n\ninterface FieldWrite<T> extends ThreadFieldTarget<T> {\n /** The override before this chain of writes began; `undefined` restores the source value. */\n previous: T | undefined;\n /** The identity the write was issued for; an answer for another one is ignored. */\n scope: string;\n /** This thread's write generation; an answer for an older one is ignored. */\n seq: number;\n}\n\nconst EMPTY_PENDING: ReadonlySet<string> = new Set();\n\nfunction fieldScope(backendUrl: string, principalId: string): string {\n return `${backendUrl}::${principalId}`;\n}\n\nfunction withPending(pending: ReadonlySet<string>, threadId: string, isPending: boolean): ReadonlySet<string> {\n if (pending.has(threadId) === isPending) return pending;\n const next = new Set(pending);\n if (isPending) next.add(threadId);\n else next.delete(threadId);\n return next;\n}\n\nconst strictEquals = <T,>(a: T, b: T): boolean => a === b;\n\n/** `(field, backend)` pairs already warned about, so an older agora logs one line per page load, not one per use. */\nconst warnedUnavailableBackends = new Set<string>();\n\n/** Test seam: forget which backends were warned about. */\nexport function resetThreadFieldUnavailableWarnings(): void {\n warnedUnavailableBackends.clear();\n}\n\nexport function useThreadFieldOverride<T, R extends ThreadFieldRow>({\n field,\n backendUrl,\n principalId,\n getAuth,\n rows,\n readRow,\n write,\n isUnavailableError,\n unavailableWarning,\n onServerTruth,\n equals = strictEquals,\n}: UseThreadFieldOverrideOptions<T, R>): ThreadFieldOverride<T> {\n const scope = fieldScope(backendUrl, principalId);\n const [state, setState] = useState<ScopedFieldState<T>>(() => ({\n scope,\n overrides: {},\n pending: EMPTY_PENDING,\n }));\n // An identity swap discards everything held for the previous identity —\n // overrides AND pending rows — rather than merely hiding it: a round trip\n // back to that identity must not revive a row pinned for a write whose\n // answer has since been dropped (it would stay disabled for good). Setting\n // state during render is React's derived-state reset; the render re-runs\n // with the empty state before anything is committed.\n if (state.scope !== scope) {\n setState({ scope, overrides: {}, pending: EMPTY_PENDING });\n }\n const emptyOverridesRef = useRef<Readonly<Record<string, T>>>(Object.freeze({}) as Record<string, T>);\n const overrides = state.scope === scope ? state.overrides : emptyOverridesRef.current;\n const pendingThreadIds = state.scope === scope ? state.pending : EMPTY_PENDING;\n // The backend the route was found missing on. The route is a property of\n // the backend, not of who is asking, so this is keyed by backend alone; a\n // different backend is presumed to have it until it says otherwise.\n const [unavailableBackend, setUnavailableBackend] = useState<string | null>(null);\n\n const scopeRef = useRef(scope);\n scopeRef.current = scope;\n const overridesRef = useRef(overrides);\n overridesRef.current = overrides;\n // The per-render option closures ride refs so a consumer's fresh functions\n // never re-key the mutation or the caught-up effect.\n const readRowRef = useRef(readRow);\n readRowRef.current = readRow;\n const writeRef = useRef(write);\n writeRef.current = write;\n const isUnavailableErrorRef = useRef(isUnavailableError);\n isUnavailableErrorRef.current = isUnavailableError;\n const unavailableWarningRef = useRef(unavailableWarning);\n unavailableWarningRef.current = unavailableWarning;\n const onServerTruthRef = useRef(onServerTruth);\n onServerTruthRef.current = onServerTruth;\n const equalsRef = useRef(equals);\n equalsRef.current = equals;\n // Per-thread write bookkeeping for the CURRENT identity: the generation of\n // the write in flight, and the value a further write asked for meanwhile.\n const inFlightRef = useRef<Map<string, number>>(new Map());\n const queuedRef = useRef<Map<string, T>>(new Map());\n const seqRef = useRef(0);\n const bookkeepingScopeRef = useRef(scope);\n if (bookkeepingScopeRef.current !== scope) {\n // The previous identity's writes are abandoned with its state: their\n // answers are dropped by the scope guard below, and nothing queued\n // behind them is sent.\n bookkeepingScopeRef.current = scope;\n inFlightRef.current = new Map();\n queuedRef.current = new Map();\n }\n\n const update = useCallback(\n (forScope: string, patch: (current: ScopedFieldState<T>) => ScopedFieldState<T>) => {\n setState((current) => {\n const base: ScopedFieldState<T> =\n current.scope === forScope\n ? current\n : { scope: forScope, overrides: {}, pending: EMPTY_PENDING };\n const next = patch(base);\n return next === base && current.scope === forScope ? current : next;\n });\n },\n [],\n );\n\n useEffect(() => {\n const caughtUp = Object.keys(overrides).filter((threadId) => {\n // A row with a write in flight keeps its override whatever the sources\n // say: the first write of a chain patches the page with a value the\n // user has since moved away from, and the row must not flash it.\n if (pendingThreadIds.has(threadId)) return false;\n const row = rows.find((candidate) => candidate.threadId === threadId);\n if (row === undefined) return false;\n const reported = readRowRef.current(row);\n const override = overrides[threadId];\n return reported !== undefined && override !== undefined && equalsRef.current(reported, override);\n });\n if (caughtUp.length === 0) return;\n update(scope, (current) => {\n const next = { ...current.overrides };\n for (const threadId of caughtUp) delete next[threadId];\n return { ...current, overrides: next };\n });\n }, [overrides, pendingThreadIds, rows, scope, update]);\n\n const mutation = useMutation({\n mutationKey: ['conversation-history', field, backendUrl, principalId],\n mutationFn: async ({ threadId, value }: FieldWrite<T>) =>\n withCredentialRenewal(getAuth, (auth) => writeRef.current(auth, { threadId, value })),\n onError: (error, write) => {\n if (isUnavailableErrorRef.current(error)) {\n setUnavailableBackend(backendUrl);\n const warnKey = `${field}::${backendUrl}`;\n if (!warnedUnavailableBackends.has(warnKey)) {\n warnedUnavailableBackends.add(warnKey);\n console.warn(unavailableWarningRef.current);\n }\n }\n if (!isCurrentWrite(write)) return;\n inFlightRef.current.delete(write.threadId);\n // Whatever was asked for meanwhile is dropped with the failure: the row\n // goes back to what it showed before the chain began.\n queuedRef.current.delete(write.threadId);\n update(write.scope, (current) => {\n const overridesNext = { ...current.overrides };\n if (write.previous === undefined) delete overridesNext[write.threadId];\n else overridesNext[write.threadId] = write.previous;\n return {\n ...current,\n overrides: overridesNext,\n pending: withPending(current.pending, write.threadId, false),\n };\n });\n },\n onSuccess: (truth, write) => {\n if (!isCurrentWrite(write)) return;\n inFlightRef.current.delete(write.threadId);\n const queued = queuedRef.current.get(write.threadId);\n const hadQueued = queuedRef.current.has(write.threadId);\n queuedRef.current.delete(write.threadId);\n onServerTruthRef.current?.(truth);\n if (hadQueued && queued !== undefined && !equalsRef.current(queued, truth.value)) {\n // The row already shows the value asked for meanwhile; the server\n // does not have it yet, so send it now — one write, the latest value.\n startWrite(write.scope, {\n threadId: write.threadId,\n value: queued,\n previous: truth.value,\n });\n return;\n }\n update(write.scope, (current) => ({\n ...current,\n overrides: { ...current.overrides, [truth.threadId]: truth.value },\n pending: withPending(current.pending, truth.threadId, false),\n }));\n },\n });\n const mutate = mutation.mutate;\n\n /** True when the answer belongs to the current identity and to this thread's latest write. */\n function isCurrentWrite(write: FieldWrite<T>): boolean {\n return (\n scopeRef.current === write.scope && inFlightRef.current.get(write.threadId) === write.seq\n );\n }\n\n function startWrite(forScope: string, write: Omit<FieldWrite<T>, 'scope' | 'seq'>): void {\n const seq = ++seqRef.current;\n inFlightRef.current.set(write.threadId, seq);\n update(forScope, (current) => ({\n ...current,\n pending: withPending(current.pending, write.threadId, true),\n }));\n mutate({ ...write, scope: forScope, seq });\n }\n\n const startWriteRef = useRef(startWrite);\n startWriteRef.current = startWrite;\n\n const set = useCallback(\n ({ threadId, value }: ThreadFieldTarget<T>) => {\n const forScope = scopeRef.current;\n const previous = overridesRef.current[threadId];\n // The row flips at once whether the write goes out now or after the\n // one in flight.\n update(forScope, (current) => ({\n ...current,\n overrides: { ...current.overrides, [threadId]: value },\n }));\n if (inFlightRef.current.has(threadId)) {\n queuedRef.current.set(threadId, value);\n return;\n }\n startWriteRef.current(forScope, { threadId, value, previous });\n },\n [update],\n );\n\n return {\n overrides,\n set,\n isPending: pendingThreadIds.size > 0,\n pendingThreadIds,\n isAvailable: unavailableBackend !== backendUrl,\n };\n}\n"],"names":["useState","useRef","useCallback","useEffect","useMutation","withCredentialRenewal","write"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"use-thread-field-override.cjs","sources":["../../src/threads/use-thread-field-override.ts"],"sourcesContent":["/**\n * The optimistic per-thread field write behind the pin (`useThreadFavorite`)\n * and the rename (`useThreadRename`): one TanStack mutation over a REST\n * route with an override map layered over the list rows.\n *\n * Why overrides rather than a cache patch alone: a row's field is folded from\n * two sources — the fetched page and the pushed conversation index — and a\n * push that predates the write would clobber a patched page. The override\n * sits over both until the sources report the same value, then drops away so\n * they own the field again (a later write from another client is never\n * masked). A failure restores the previous value; a 404 / 405 marks the\n * write unavailable — the backend predates the route — so the UI withdraws\n * the control instead of failing on every use.\n *\n * Same-thread writes are serialized: while one is in flight, a further write\n * for that thread flips the row at once but only records the desired value,\n * and at most one follow-up write is sent — with that value — once the\n * in-flight one has answered. Two independent writes for one thread never\n * race, so the server cannot end on an earlier request's value.\n *\n * Everything the hook holds is scoped to `(backendUrl, principalId)`: a\n * credential swap under the same list reads an empty override map, and a\n * write that was in flight for the previous identity is ignored when it\n * answers, so a same-id row under the new identity never inherits the old\n * one's value.\n */\nimport { useMutation } from '@tanstack/react-query';\nimport { useCallback, useEffect, useRef, useState } from 'react';\nimport { type CredentialResolver, withCredentialRenewal } from '../runtime/credential-renewal';\nimport type { RestConversationAuth } from './use-rest-conversation-history';\n\nexport interface ThreadFieldTarget<T> {\n threadId: string;\n value: T;\n}\n\n/** The one field every row must carry: its identity. */\nexport interface ThreadFieldRow {\n threadId: string;\n}\n\nexport interface UseThreadFieldOverrideOptions<T, R extends ThreadFieldRow> {\n /** Names the field: part of the mutation key and of the one-per-backend warning. */\n field: string;\n backendUrl: string;\n /** Non-secret identity in the mutation key (as the read-state mutation keys). */\n principalId: string;\n /** Resolved per request; called with `{ force: true }` when the host refuses the token. */\n getAuth: CredentialResolver<RestConversationAuth>;\n /**\n * The rows as the list sources currently report them, BEFORE overrides. An\n * override is dropped once its row reports the same value.\n */\n rows: readonly R[];\n /** The field as a source row reports it; `undefined` when the row does not carry it. */\n readRow: (row: R) => T | undefined;\n /** The write; resolves to the server's truth after it. */\n write: (auth: RestConversationAuth, target: ThreadFieldTarget<T>) => Promise<ThreadFieldTarget<T>>;\n /** True for the rejection that means the backend has no such route (404 / 405). */\n isUnavailableError: (error: unknown) => boolean;\n /** Logged once per backend when the route is found missing. */\n unavailableWarning: string;\n /** Write the server's answer into the list caches (`patchConversation`). */\n onServerTruth?: (truth: ThreadFieldTarget<T>) => void;\n /** Value equality (default `===`). */\n equals?: (a: T, b: T) => boolean;\n}\n\nexport interface ThreadFieldOverride<T> {\n /** Optimistic, then server-confirmed, values layered over the list sources, keyed by thread id. */\n overrides: Readonly<Record<string, T>>;\n /**\n * Write the field. Flips the row at once; while that thread's write is in\n * flight the call only records the desired value (see module doc).\n */\n set: (target: ThreadFieldTarget<T>) => void;\n /** True while any write is in flight. */\n isPending: boolean;\n /** The threads whose write is in flight — a control disables itself for these. */\n pendingThreadIds: ReadonlySet<string>;\n /**\n * `false` once the backend answered 404 / 405: the route is not deployed\n * there, and the UI withdraws the control.\n */\n isAvailable: boolean;\n}\n\n/** The hook's state, tagged with the identity it belongs to. */\ninterface ScopedFieldState<T> {\n scope: string;\n overrides: Record<string, T>;\n pending: ReadonlySet<string>;\n}\n\ninterface FieldWrite<T> extends ThreadFieldTarget<T> {\n /** The override before this chain of writes began; `undefined` restores the source value. */\n previous: T | undefined;\n /** The identity the write was issued for; an answer for another one is ignored. */\n scope: string;\n /** This thread's write generation; an answer for an older one is ignored. */\n seq: number;\n}\n\nconst EMPTY_PENDING: ReadonlySet<string> = new Set();\n\nfunction fieldScope(backendUrl: string, principalId: string): string {\n return `${backendUrl}::${principalId}`;\n}\n\nfunction withPending(pending: ReadonlySet<string>, threadId: string, isPending: boolean): ReadonlySet<string> {\n if (pending.has(threadId) === isPending) return pending;\n const next = new Set(pending);\n if (isPending) next.add(threadId);\n else next.delete(threadId);\n return next;\n}\n\nconst strictEquals = <T,>(a: T, b: T): boolean => a === b;\n\n/** `(field, backend)` pairs already warned about, so an older agora logs one line per page load, not one per use. */\nconst warnedUnavailableBackends = new Set<string>();\n\n/** Test seam: forget which backends were warned about. */\nexport function resetThreadFieldUnavailableWarnings(): void {\n warnedUnavailableBackends.clear();\n}\n\nexport function useThreadFieldOverride<T, R extends ThreadFieldRow>({\n field,\n backendUrl,\n principalId,\n getAuth,\n rows,\n readRow,\n write,\n isUnavailableError,\n unavailableWarning,\n onServerTruth,\n equals = strictEquals,\n}: UseThreadFieldOverrideOptions<T, R>): ThreadFieldOverride<T> {\n const scope = fieldScope(backendUrl, principalId);\n const [state, setState] = useState<ScopedFieldState<T>>(() => ({\n scope,\n overrides: {},\n pending: EMPTY_PENDING,\n }));\n // An identity swap discards everything held for the previous identity —\n // overrides AND pending rows — rather than merely hiding it: a round trip\n // back to that identity must not revive a row pinned for a write whose\n // answer has since been dropped (it would stay disabled for good). Setting\n // state during render is React's derived-state reset; the render re-runs\n // with the empty state before anything is committed.\n if (state.scope !== scope) {\n setState({ scope, overrides: {}, pending: EMPTY_PENDING });\n }\n const emptyOverridesRef = useRef<Readonly<Record<string, T>>>(Object.freeze({}) as Record<string, T>);\n const overrides = state.scope === scope ? state.overrides : emptyOverridesRef.current;\n const pendingThreadIds = state.scope === scope ? state.pending : EMPTY_PENDING;\n // The backend the route was found missing on. The route is a property of\n // the backend, not of who is asking, so this is keyed by backend alone; a\n // different backend is presumed to have it until it says otherwise.\n const [unavailableBackend, setUnavailableBackend] = useState<string | null>(null);\n\n const scopeRef = useRef(scope);\n scopeRef.current = scope;\n const overridesRef = useRef(overrides);\n overridesRef.current = overrides;\n // The per-render option closures ride refs so a consumer's fresh functions\n // never re-key the mutation or the caught-up effect.\n const readRowRef = useRef(readRow);\n readRowRef.current = readRow;\n const writeRef = useRef(write);\n writeRef.current = write;\n const isUnavailableErrorRef = useRef(isUnavailableError);\n isUnavailableErrorRef.current = isUnavailableError;\n const unavailableWarningRef = useRef(unavailableWarning);\n unavailableWarningRef.current = unavailableWarning;\n const onServerTruthRef = useRef(onServerTruth);\n onServerTruthRef.current = onServerTruth;\n const equalsRef = useRef(equals);\n equalsRef.current = equals;\n // Per-thread write bookkeeping for the CURRENT identity: the generation of\n // the write in flight, and the value a further write asked for meanwhile.\n const inFlightRef = useRef<Map<string, number>>(new Map());\n const queuedRef = useRef<Map<string, T>>(new Map());\n const seqRef = useRef(0);\n const bookkeepingScopeRef = useRef(scope);\n if (bookkeepingScopeRef.current !== scope) {\n // The previous identity's writes are abandoned with its state: their\n // answers are dropped by the scope guard below, and nothing queued\n // behind them is sent.\n bookkeepingScopeRef.current = scope;\n inFlightRef.current = new Map();\n queuedRef.current = new Map();\n }\n\n const update = useCallback(\n (forScope: string, patch: (current: ScopedFieldState<T>) => ScopedFieldState<T>) => {\n setState((current) => {\n const base: ScopedFieldState<T> =\n current.scope === forScope\n ? current\n : { scope: forScope, overrides: {}, pending: EMPTY_PENDING };\n const next = patch(base);\n return next === base && current.scope === forScope ? current : next;\n });\n },\n [],\n );\n\n useEffect(() => {\n const caughtUp = Object.keys(overrides).filter((threadId) => {\n // A row with a write in flight keeps its override whatever the sources\n // say: the first write of a chain patches the page with a value the\n // user has since moved away from, and the row must not flash it.\n if (pendingThreadIds.has(threadId)) return false;\n const row = rows.find((candidate) => candidate.threadId === threadId);\n if (row === undefined) return false;\n const reported = readRowRef.current(row);\n const override = overrides[threadId];\n return reported !== undefined && override !== undefined && equalsRef.current(reported, override);\n });\n if (caughtUp.length === 0) return;\n update(scope, (current) => {\n const next = { ...current.overrides };\n for (const threadId of caughtUp) delete next[threadId];\n return { ...current, overrides: next };\n });\n }, [overrides, pendingThreadIds, rows, scope, update]);\n\n const mutation = useMutation({\n mutationKey: ['conversation-history', field, backendUrl, principalId],\n mutationFn: async ({ threadId, value }: FieldWrite<T>) =>\n withCredentialRenewal(getAuth, (auth) => writeRef.current(auth, { threadId, value })),\n onError: (error, write) => {\n if (isUnavailableErrorRef.current(error)) {\n setUnavailableBackend(backendUrl);\n const warnKey = `${field}::${backendUrl}`;\n if (!warnedUnavailableBackends.has(warnKey)) {\n warnedUnavailableBackends.add(warnKey);\n console.warn(unavailableWarningRef.current);\n }\n }\n if (!isCurrentWrite(write)) return;\n inFlightRef.current.delete(write.threadId);\n // Whatever was asked for meanwhile is dropped with the failure: the row\n // goes back to what it showed before the chain began.\n queuedRef.current.delete(write.threadId);\n update(write.scope, (current) => {\n const overridesNext = { ...current.overrides };\n if (write.previous === undefined) delete overridesNext[write.threadId];\n else overridesNext[write.threadId] = write.previous;\n return {\n ...current,\n overrides: overridesNext,\n pending: withPending(current.pending, write.threadId, false),\n };\n });\n },\n onSuccess: (truth, write) => {\n if (!isCurrentWrite(write)) return;\n inFlightRef.current.delete(write.threadId);\n const queued = queuedRef.current.get(write.threadId);\n const hadQueued = queuedRef.current.has(write.threadId);\n queuedRef.current.delete(write.threadId);\n onServerTruthRef.current?.(truth);\n if (hadQueued && queued !== undefined && !equalsRef.current(queued, truth.value)) {\n // The row already shows the value asked for meanwhile; the server\n // does not have it yet, so send it now — one write, the latest value.\n startWrite(write.scope, {\n threadId: write.threadId,\n value: queued,\n previous: truth.value,\n });\n return;\n }\n update(write.scope, (current) => ({\n ...current,\n overrides: { ...current.overrides, [truth.threadId]: truth.value },\n pending: withPending(current.pending, truth.threadId, false),\n }));\n },\n });\n const mutate = mutation.mutate;\n\n /** True when the answer belongs to the current identity and to this thread's latest write. */\n function isCurrentWrite(write: FieldWrite<T>): boolean {\n return (\n scopeRef.current === write.scope && inFlightRef.current.get(write.threadId) === write.seq\n );\n }\n\n function startWrite(forScope: string, write: Omit<FieldWrite<T>, 'scope' | 'seq'>): void {\n const seq = ++seqRef.current;\n inFlightRef.current.set(write.threadId, seq);\n update(forScope, (current) => ({\n ...current,\n pending: withPending(current.pending, write.threadId, true),\n }));\n mutate({ ...write, scope: forScope, seq });\n }\n\n const startWriteRef = useRef(startWrite);\n startWriteRef.current = startWrite;\n\n const set = useCallback(\n ({ threadId, value }: ThreadFieldTarget<T>) => {\n const forScope = scopeRef.current;\n const previous = overridesRef.current[threadId];\n // The row flips at once whether the write goes out now or after the\n // one in flight.\n update(forScope, (current) => ({\n ...current,\n overrides: { ...current.overrides, [threadId]: value },\n }));\n if (inFlightRef.current.has(threadId)) {\n queuedRef.current.set(threadId, value);\n return;\n }\n startWriteRef.current(forScope, { threadId, value, previous });\n },\n [update],\n );\n\n return {\n overrides,\n set,\n isPending: pendingThreadIds.size > 0,\n pendingThreadIds,\n isAvailable: unavailableBackend !== backendUrl,\n };\n}\n"],"names":["useState","useRef","useCallback","useEffect","useMutation","withCredentialRenewal","write"],"mappings":";;;;;AAuGA,MAAM,oCAAyC,IAAA;AAE/C,SAAS,WAAW,YAAoB,aAA6B;AACnE,SAAO,GAAG,UAAU,KAAK,WAAW;AACtC;AAEA,SAAS,YAAY,SAA8B,UAAkB,WAAyC;AAC5G,MAAI,QAAQ,IAAI,QAAQ,MAAM,UAAW,QAAO;AAChD,QAAM,OAAO,IAAI,IAAI,OAAO;AAC5B,MAAI,UAAW,MAAK,IAAI,QAAQ;AAAA,MAC3B,MAAK,OAAO,QAAQ;AACzB,SAAO;AACT;AAEA,MAAM,eAAe,CAAK,GAAM,MAAkB,MAAM;AAGxD,MAAM,gDAAgC,IAAA;AAO/B,SAAS,uBAAoD;AAAA,EAClE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAS;AACX,GAAgE;AAC9D,QAAM,QAAQ,WAAW,YAAY,WAAW;AAChD,QAAM,CAAC,OAAO,QAAQ,IAAIA,WAAAA,SAA8B,OAAO;AAAA,IAC7D;AAAA,IACA,WAAW,CAAA;AAAA,IACX,SAAS;AAAA,EAAA,EACT;AAOF,MAAI,MAAM,UAAU,OAAO;AACzB,aAAS,EAAE,OAAO,WAAW,CAAA,GAAI,SAAS,eAAe;AAAA,EAC3D;AACA,QAAM,oBAAoBC,WAAAA,OAAoC,OAAO,OAAO,CAAA,CAAE,CAAsB;AACpG,QAAM,YAAY,MAAM,UAAU,QAAQ,MAAM,YAAY,kBAAkB;AAC9E,QAAM,mBAAmB,MAAM,UAAU,QAAQ,MAAM,UAAU;AAIjE,QAAM,CAAC,oBAAoB,qBAAqB,IAAID,WAAAA,SAAwB,IAAI;AAEhF,QAAM,WAAWC,WAAAA,OAAO,KAAK;AAC7B,WAAS,UAAU;AACnB,QAAM,eAAeA,WAAAA,OAAO,SAAS;AACrC,eAAa,UAAU;AAGvB,QAAM,aAAaA,WAAAA,OAAO,OAAO;AACjC,aAAW,UAAU;AACrB,QAAM,WAAWA,WAAAA,OAAO,KAAK;AAC7B,WAAS,UAAU;AACnB,QAAM,wBAAwBA,WAAAA,OAAO,kBAAkB;AACvD,wBAAsB,UAAU;AAChC,QAAM,wBAAwBA,WAAAA,OAAO,kBAAkB;AACvD,wBAAsB,UAAU;AAChC,QAAM,mBAAmBA,WAAAA,OAAO,aAAa;AAC7C,mBAAiB,UAAU;AAC3B,QAAM,YAAYA,WAAAA,OAAO,MAAM;AAC/B,YAAU,UAAU;AAGpB,QAAM,cAAcA,WAAAA,OAA4B,oBAAI,KAAK;AACzD,QAAM,YAAYA,WAAAA,OAAuB,oBAAI,KAAK;AAClD,QAAM,SAASA,WAAAA,OAAO,CAAC;AACvB,QAAM,sBAAsBA,WAAAA,OAAO,KAAK;AACxC,MAAI,oBAAoB,YAAY,OAAO;AAIzC,wBAAoB,UAAU;AAC9B,gBAAY,8BAAc,IAAA;AAC1B,cAAU,8BAAc,IAAA;AAAA,EAC1B;AAEA,QAAM,SAASC,WAAAA;AAAAA,IACb,CAAC,UAAkB,UAAiE;AAClF,eAAS,CAAC,YAAY;AACpB,cAAM,OACJ,QAAQ,UAAU,WACd,UACA,EAAE,OAAO,UAAU,WAAW,IAAI,SAAS,cAAA;AACjD,cAAM,OAAO,MAAM,IAAI;AACvB,eAAO,SAAS,QAAQ,QAAQ,UAAU,WAAW,UAAU;AAAA,MACjE,CAAC;AAAA,IACH;AAAA,IACA,CAAA;AAAA,EAAC;AAGHC,aAAAA,UAAU,MAAM;AACd,UAAM,WAAW,OAAO,KAAK,SAAS,EAAE,OAAO,CAAC,aAAa;AAI3D,UAAI,iBAAiB,IAAI,QAAQ,EAAG,QAAO;AAC3C,YAAM,MAAM,KAAK,KAAK,CAAC,cAAc,UAAU,aAAa,QAAQ;AACpE,UAAI,QAAQ,OAAW,QAAO;AAC9B,YAAM,WAAW,WAAW,QAAQ,GAAG;AACvC,YAAM,WAAW,UAAU,QAAQ;AACnC,aAAO,aAAa,UAAa,aAAa,UAAa,UAAU,QAAQ,UAAU,QAAQ;AAAA,IACjG,CAAC;AACD,QAAI,SAAS,WAAW,EAAG;AAC3B,WAAO,OAAO,CAAC,YAAY;AACzB,YAAM,OAAO,EAAE,GAAG,QAAQ,UAAA;AAC1B,iBAAW,YAAY,SAAU,QAAO,KAAK,QAAQ;AACrD,aAAO,EAAE,GAAG,SAAS,WAAW,KAAA;AAAA,IAClC,CAAC;AAAA,EACH,GAAG,CAAC,WAAW,kBAAkB,MAAM,OAAO,MAAM,CAAC;AAErD,QAAM,WAAWC,WAAAA,YAAY;AAAA,IAC3B,aAAa,CAAC,wBAAwB,OAAO,YAAY,WAAW;AAAA,IACpE,YAAY,OAAO,EAAE,UAAU,MAAA,MAC7BC,kBAAAA,sBAAsB,SAAS,CAAC,SAAS,SAAS,QAAQ,MAAM,EAAE,UAAU,MAAA,CAAO,CAAC;AAAA,IACtF,SAAS,CAAC,OAAOC,WAAU;AACzB,UAAI,sBAAsB,QAAQ,KAAK,GAAG;AACxC,8BAAsB,UAAU;AAChC,cAAM,UAAU,GAAG,KAAK,KAAK,UAAU;AACvC,YAAI,CAAC,0BAA0B,IAAI,OAAO,GAAG;AAC3C,oCAA0B,IAAI,OAAO;AACrC,kBAAQ,KAAK,sBAAsB,OAAO;AAAA,QAC5C;AAAA,MACF;AACA,UAAI,CAAC,eAAeA,MAAK,EAAG;AAC5B,kBAAY,QAAQ,OAAOA,OAAM,QAAQ;AAGzC,gBAAU,QAAQ,OAAOA,OAAM,QAAQ;AACvC,aAAOA,OAAM,OAAO,CAAC,YAAY;AAC/B,cAAM,gBAAgB,EAAE,GAAG,QAAQ,UAAA;AACnC,YAAIA,OAAM,aAAa,OAAW,QAAO,cAAcA,OAAM,QAAQ;AAAA,YAChE,eAAcA,OAAM,QAAQ,IAAIA,OAAM;AAC3C,eAAO;AAAA,UACL,GAAG;AAAA,UACH,WAAW;AAAA,UACX,SAAS,YAAY,QAAQ,SAASA,OAAM,UAAU,KAAK;AAAA,QAAA;AAAA,MAE/D,CAAC;AAAA,IACH;AAAA,IACA,WAAW,CAAC,OAAOA,WAAU;;AAC3B,UAAI,CAAC,eAAeA,MAAK,EAAG;AAC5B,kBAAY,QAAQ,OAAOA,OAAM,QAAQ;AACzC,YAAM,SAAS,UAAU,QAAQ,IAAIA,OAAM,QAAQ;AACnD,YAAM,YAAY,UAAU,QAAQ,IAAIA,OAAM,QAAQ;AACtD,gBAAU,QAAQ,OAAOA,OAAM,QAAQ;AACvC,6BAAiB,YAAjB,0CAA2B;AAC3B,UAAI,aAAa,WAAW,UAAa,CAAC,UAAU,QAAQ,QAAQ,MAAM,KAAK,GAAG;AAGhF,mBAAWA,OAAM,OAAO;AAAA,UACtB,UAAUA,OAAM;AAAA,UAChB,OAAO;AAAA,UACP,UAAU,MAAM;AAAA,QAAA,CACjB;AACD;AAAA,MACF;AACA,aAAOA,OAAM,OAAO,CAAC,aAAa;AAAA,QAChC,GAAG;AAAA,QACH,WAAW,EAAE,GAAG,QAAQ,WAAW,CAAC,MAAM,QAAQ,GAAG,MAAM,MAAA;AAAA,QAC3D,SAAS,YAAY,QAAQ,SAAS,MAAM,UAAU,KAAK;AAAA,MAAA,EAC3D;AAAA,IACJ;AAAA,EAAA,CACD;AACD,QAAM,SAAS,SAAS;AAGxB,WAAS,eAAeA,QAA+B;AACrD,WACE,SAAS,YAAYA,OAAM,SAAS,YAAY,QAAQ,IAAIA,OAAM,QAAQ,MAAMA,OAAM;AAAA,EAE1F;AAEA,WAAS,WAAW,UAAkBA,QAAmD;AACvF,UAAM,MAAM,EAAE,OAAO;AACrB,gBAAY,QAAQ,IAAIA,OAAM,UAAU,GAAG;AAC3C,WAAO,UAAU,CAAC,aAAa;AAAA,MAC7B,GAAG;AAAA,MACH,SAAS,YAAY,QAAQ,SAASA,OAAM,UAAU,IAAI;AAAA,IAAA,EAC1D;AACF,WAAO,EAAE,GAAGA,QAAO,OAAO,UAAU,KAAK;AAAA,EAC3C;AAEA,QAAM,gBAAgBL,WAAAA,OAAO,UAAU;AACvC,gBAAc,UAAU;AAExB,QAAM,MAAMC,WAAAA;AAAAA,IACV,CAAC,EAAE,UAAU,YAAkC;AAC7C,YAAM,WAAW,SAAS;AAC1B,YAAM,WAAW,aAAa,QAAQ,QAAQ;AAG9C,aAAO,UAAU,CAAC,aAAa;AAAA,QAC7B,GAAG;AAAA,QACH,WAAW,EAAE,GAAG,QAAQ,WAAW,CAAC,QAAQ,GAAG,MAAA;AAAA,MAAM,EACrD;AACF,UAAI,YAAY,QAAQ,IAAI,QAAQ,GAAG;AACrC,kBAAU,QAAQ,IAAI,UAAU,KAAK;AACrC;AAAA,MACF;AACA,oBAAc,QAAQ,UAAU,EAAE,UAAU,OAAO,UAAU;AAAA,IAC/D;AAAA,IACA,CAAC,MAAM;AAAA,EAAA;AAGT,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,WAAW,iBAAiB,OAAO;AAAA,IACnC;AAAA,IACA,aAAa,uBAAuB;AAAA,EAAA;AAExC;;"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
const
|
|
3
|
+
const require$$0 = require("react");
|
|
4
4
|
const api = require("./api.cjs");
|
|
5
5
|
const useThreadFieldOverride = require("./use-thread-field-override.cjs");
|
|
6
6
|
const READ_STATE_UNAVAILABLE_WARNING = "[AthenaSDK] This backend has no POST /api/conversations/threads/read-state route; sessions cannot be marked read from here.";
|
|
@@ -29,10 +29,10 @@ function useThreadReadState({
|
|
|
29
29
|
onServerTruth: onServerTruth ? ({ threadId, value }) => onServerTruth({ threadId, isUnread: value }) : void 0
|
|
30
30
|
});
|
|
31
31
|
const set = field.set;
|
|
32
|
-
const rowsRef =
|
|
32
|
+
const rowsRef = require$$0.useRef(rows);
|
|
33
33
|
rowsRef.current = rows;
|
|
34
|
-
const [coveredUpdatedAt, setCoveredUpdatedAt] =
|
|
35
|
-
const setReadState =
|
|
34
|
+
const [coveredUpdatedAt, setCoveredUpdatedAt] = require$$0.useState({});
|
|
35
|
+
const setReadState = require$$0.useCallback(
|
|
36
36
|
({ threadId, isUnread, updatedAt }) => {
|
|
37
37
|
var _a;
|
|
38
38
|
const covered = updatedAt ?? ((_a = rowsRef.current.find((row) => row.threadId === threadId)) == null ? void 0 : _a.updatedAt);
|