@athenaintel/react 0.28.1 → 0.30.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 +418 -10
- package/dist/agent-runtime/src/asset-attachment.cjs.map +1 -0
- package/dist/agent-runtime/src/asset-attachment.js.map +1 -0
- package/dist/agent-runtime/src/auth-denial.cjs.map +1 -0
- package/dist/agent-runtime/src/auth-denial.js.map +1 -0
- package/dist/agent-runtime/src/client-tool-bridge.cjs.map +1 -0
- package/dist/agent-runtime/src/client-tool-bridge.js.map +1 -0
- package/dist/agent-runtime/src/client-tools.cjs.map +1 -0
- package/dist/agent-runtime/src/client-tools.js.map +1 -0
- package/dist/agent-runtime/src/composer-markdown.cjs +124 -0
- package/dist/agent-runtime/src/composer-markdown.cjs.map +1 -0
- package/dist/agent-runtime/src/composer-markdown.js +124 -0
- package/dist/agent-runtime/src/composer-markdown.js.map +1 -0
- package/dist/agent-runtime/src/conversation-index.cjs.map +1 -0
- package/dist/agent-runtime/src/conversation-index.js.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/conversation-list.cjs +36 -0
- package/dist/agent-runtime/src/conversation-list.cjs.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/conversation-list.js +36 -0
- package/dist/agent-runtime/src/conversation-list.js.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/deep-agent-transport-recipe.cjs +5 -3
- package/dist/agent-runtime/src/deep-agent-transport-recipe.cjs.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/deep-agent-transport-recipe.js +6 -4
- package/dist/agent-runtime/src/deep-agent-transport-recipe.js.map +1 -0
- package/dist/agent-runtime/src/edit-command.cjs.map +1 -0
- package/dist/agent-runtime/src/edit-command.js.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/errors.cjs +23 -0
- package/dist/agent-runtime/src/errors.cjs.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/errors.js +23 -0
- package/dist/agent-runtime/src/errors.js.map +1 -0
- package/dist/agent-runtime/src/execute-output.cjs +41 -0
- package/dist/agent-runtime/src/execute-output.cjs.map +1 -0
- package/dist/agent-runtime/src/execute-output.js +41 -0
- package/dist/agent-runtime/src/execute-output.js.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/generated/runconfig-contract.cjs +10 -2
- package/dist/agent-runtime/src/generated/runconfig-contract.cjs.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/generated/runconfig-contract.js +10 -2
- package/dist/agent-runtime/src/generated/runconfig-contract.js.map +1 -0
- package/dist/agent-runtime/src/github-wake-event.cjs.map +1 -0
- package/dist/agent-runtime/src/github-wake-event.js.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/interrupts.cjs +24 -1
- package/dist/agent-runtime/src/interrupts.cjs.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/interrupts.js +24 -1
- package/dist/agent-runtime/src/interrupts.js.map +1 -0
- package/dist/agent-runtime/src/message-author.cjs.map +1 -0
- package/dist/agent-runtime/src/message-author.js.map +1 -0
- package/dist/agent-runtime/src/message-window.cjs.map +1 -0
- package/dist/agent-runtime/src/message-window.js.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/messages.cjs +8 -4
- package/dist/agent-runtime/src/messages.cjs.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/messages.js +6 -2
- package/dist/agent-runtime/src/messages.js.map +1 -0
- package/dist/agent-runtime/src/model-context.cjs.map +1 -0
- package/dist/agent-runtime/src/model-context.js.map +1 -0
- package/dist/agent-runtime/src/optimistic-content.cjs.map +1 -0
- package/dist/agent-runtime/src/optimistic-content.js.map +1 -0
- package/dist/agent-runtime/src/protocol.cjs.map +1 -0
- package/dist/agent-runtime/src/protocol.js.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/queue.cjs +23 -2
- package/dist/agent-runtime/src/queue.cjs.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/queue.js +23 -2
- package/dist/agent-runtime/src/queue.js.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/quota-safe-local-storage-session.cjs +23 -13
- package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/quota-safe-local-storage-session.js +24 -14
- package/dist/agent-runtime/src/quota-safe-local-storage-session.js.map +1 -0
- package/dist/agent-runtime/src/runtime-messages.cjs.map +1 -0
- package/dist/agent-runtime/src/runtime-messages.js.map +1 -0
- package/dist/agent-runtime/src/screen-point.cjs.map +1 -0
- package/dist/agent-runtime/src/screen-point.js.map +1 -0
- package/dist/agent-runtime/src/send-recovery.cjs.map +1 -0
- package/dist/agent-runtime/src/send-recovery.js.map +1 -0
- package/dist/agent-runtime/src/statewire-attach-observer.cjs.map +1 -0
- package/dist/agent-runtime/src/statewire-attach-observer.js.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/statewire-state.cjs +8 -0
- package/dist/agent-runtime/src/statewire-state.cjs.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/statewire-state.js +8 -0
- package/dist/agent-runtime/src/statewire-state.js.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/statewire-suspended.cjs +4 -0
- package/dist/agent-runtime/src/statewire-suspended.cjs.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/statewire-suspended.js +4 -0
- package/dist/agent-runtime/src/statewire-suspended.js.map +1 -0
- package/dist/agent-runtime/src/statewire-transport.cjs +43 -0
- package/dist/agent-runtime/src/statewire-transport.cjs.map +1 -0
- package/dist/agent-runtime/src/statewire-transport.js +43 -0
- package/dist/agent-runtime/src/statewire-transport.js.map +1 -0
- package/dist/agent-runtime/src/streaming-markdown.cjs.map +1 -0
- package/dist/agent-runtime/src/streaming-markdown.js.map +1 -0
- package/dist/agent-runtime/src/subscription-wake-event.cjs +252 -0
- package/dist/agent-runtime/src/subscription-wake-event.cjs.map +1 -0
- package/dist/agent-runtime/src/subscription-wake-event.js +252 -0
- package/dist/agent-runtime/src/subscription-wake-event.js.map +1 -0
- package/dist/agent-runtime/src/thread-extras.cjs.map +1 -0
- package/dist/agent-runtime/src/thread-extras.js.map +1 -0
- package/dist/agent-runtime/src/thread-snapshot-cache.cjs.map +1 -0
- package/dist/agent-runtime/src/thread-snapshot-cache.js.map +1 -0
- package/dist/agent-runtime/src/thread-status.cjs.map +1 -0
- package/dist/agent-runtime/src/thread-status.js.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/tool-metadata.cjs +279 -3
- package/dist/agent-runtime/src/tool-metadata.cjs.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/tool-metadata.js +279 -3
- package/dist/agent-runtime/src/tool-metadata.js.map +1 -0
- package/dist/agent-runtime/src/tool-names.cjs +5 -0
- package/dist/agent-runtime/src/tool-names.cjs.map +1 -0
- package/dist/agent-runtime/src/tool-names.js +5 -0
- package/dist/agent-runtime/src/tool-names.js.map +1 -0
- package/dist/agent-runtime/src/tool-outputs.cjs.map +1 -0
- package/dist/agent-runtime/src/tool-outputs.js.map +1 -0
- package/dist/agent-runtime/src/tool-result.cjs.map +1 -0
- package/dist/agent-runtime/src/tool-result.js.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/use-conversation-list.cjs +33 -22
- package/dist/agent-runtime/src/use-conversation-list.cjs.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/use-conversation-list.js +34 -23
- package/dist/agent-runtime/src/use-conversation-list.js.map +1 -0
- package/dist/agent-runtime/src/use-deep-agent-config.cjs.map +1 -0
- package/dist/agent-runtime/src/use-deep-agent-config.js.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/use-deep-agent-edit-submit.cjs +2 -0
- package/dist/agent-runtime/src/use-deep-agent-edit-submit.cjs.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/use-deep-agent-edit-submit.js +2 -0
- package/dist/agent-runtime/src/use-deep-agent-edit-submit.js.map +1 -0
- package/dist/agent-runtime/src/use-deep-agent-runtime.cjs.map +1 -0
- package/dist/agent-runtime/src/use-deep-agent-runtime.js.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/use-deep-agent-thread.cjs +1 -0
- package/dist/agent-runtime/src/use-deep-agent-thread.cjs.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/use-deep-agent-thread.js +2 -1
- package/dist/agent-runtime/src/use-deep-agent-thread.js.map +1 -0
- package/dist/agent-runtime/src/use-deep-agent-window-sync.cjs.map +1 -0
- package/dist/agent-runtime/src/use-deep-agent-window-sync.js.map +1 -0
- package/dist/agent-runtime/src/use-historical-edit-attachments.cjs +52 -0
- package/dist/agent-runtime/src/use-historical-edit-attachments.cjs.map +1 -0
- package/dist/agent-runtime/src/use-historical-edit-attachments.js +52 -0
- package/dist/agent-runtime/src/use-historical-edit-attachments.js.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/voice-presentation.cjs +14 -0
- package/dist/agent-runtime/src/voice-presentation.cjs.map +1 -0
- package/dist/{packages/agent-runtime → agent-runtime}/src/voice-presentation.js +14 -0
- package/dist/agent-runtime/src/voice-presentation.js.map +1 -0
- package/dist/agent-runtime/src/voice-turn-grouping.cjs.map +1 -0
- package/dist/agent-runtime/src/voice-turn-grouping.js.map +1 -0
- package/dist/assets/AthenaAssetEmbed.cjs +8 -2
- package/dist/assets/AthenaAssetEmbed.cjs.map +1 -1
- package/dist/assets/AthenaAssetEmbed.d.ts +8 -0
- package/dist/assets/AthenaAssetEmbed.js +8 -2
- package/dist/assets/AthenaAssetEmbed.js.map +1 -1
- package/dist/assets/AthenaLayout.cjs +97 -31
- package/dist/assets/AthenaLayout.cjs.map +1 -1
- package/dist/assets/AthenaLayout.d.ts +13 -0
- package/dist/assets/AthenaLayout.js +98 -32
- package/dist/assets/AthenaLayout.js.map +1 -1
- package/dist/assets/asset-embed-messages.cjs.map +1 -1
- package/dist/assets/asset-embed-messages.d.ts +6 -0
- package/dist/assets/asset-embed-messages.js.map +1 -1
- package/dist/assets/asset-panel-store.cjs +68 -32
- package/dist/assets/asset-panel-store.cjs.map +1 -1
- package/dist/assets/asset-panel-store.d.ts +47 -1
- package/dist/assets/asset-panel-store.js +68 -32
- package/dist/assets/asset-panel-store.js.map +1 -1
- package/dist/assets/use-asset-embed.cjs +29 -8
- package/dist/assets/use-asset-embed.cjs.map +1 -1
- package/dist/assets/use-asset-embed.d.ts +7 -0
- package/dist/assets/use-asset-embed.js +29 -8
- package/dist/assets/use-asset-embed.js.map +1 -1
- package/dist/catalog/chat-pickers.cjs +152 -0
- package/dist/catalog/chat-pickers.cjs.map +1 -0
- package/dist/catalog/chat-pickers.d.ts +22 -0
- package/dist/catalog/chat-pickers.js +152 -0
- package/dist/catalog/chat-pickers.js.map +1 -0
- package/dist/catalog/runtime-catalog.cjs +181 -0
- package/dist/catalog/runtime-catalog.cjs.map +1 -0
- package/dist/catalog/runtime-catalog.d.ts +100 -0
- package/dist/catalog/runtime-catalog.js +181 -0
- package/dist/catalog/runtime-catalog.js.map +1 -0
- package/dist/chat/AthenaChat.cjs +86 -46
- package/dist/chat/AthenaChat.cjs.map +1 -1
- package/dist/chat/AthenaChat.d.ts +21 -4
- package/dist/chat/AthenaChat.js +88 -48
- package/dist/chat/AthenaChat.js.map +1 -1
- package/dist/chat/StatewireApprovalCard.cjs +38 -37
- package/dist/chat/StatewireApprovalCard.cjs.map +1 -1
- package/dist/chat/StatewireApprovalCard.d.ts +2 -0
- package/dist/chat/StatewireApprovalCard.js +39 -38
- package/dist/chat/StatewireApprovalCard.js.map +1 -1
- package/dist/chat/StatewireClientToolBridge.cjs +2 -2
- package/dist/chat/StatewireClientToolBridge.js +2 -2
- package/dist/chat/StatewireQueuedMessages.cjs +15 -12
- package/dist/chat/StatewireQueuedMessages.cjs.map +1 -1
- package/dist/chat/StatewireQueuedMessages.d.ts +22 -2
- package/dist/chat/StatewireQueuedMessages.js +15 -12
- package/dist/chat/StatewireQueuedMessages.js.map +1 -1
- package/dist/chat/StatewireRunRefusalNotice.cjs +48 -0
- package/dist/chat/StatewireRunRefusalNotice.cjs.map +1 -0
- package/dist/chat/StatewireRunRefusalNotice.d.ts +25 -0
- package/dist/chat/StatewireRunRefusalNotice.js +48 -0
- package/dist/chat/StatewireRunRefusalNotice.js.map +1 -0
- package/dist/chat/WaitingOnYouBanner.cjs +2 -2
- package/dist/chat/WaitingOnYouBanner.js +2 -2
- package/dist/chat/athena-citation-links.cjs +19 -15
- package/dist/chat/athena-citation-links.cjs.map +1 -1
- package/dist/chat/athena-citation-links.js +19 -15
- package/dist/chat/athena-citation-links.js.map +1 -1
- package/dist/chat/run-activity.cjs +9 -1
- package/dist/chat/run-activity.cjs.map +1 -1
- package/dist/chat/run-activity.d.ts +6 -0
- package/dist/chat/run-activity.js +10 -2
- package/dist/chat/run-activity.js.map +1 -1
- package/dist/chat/statewire-banners.cjs +30 -1
- package/dist/chat/statewire-banners.cjs.map +1 -1
- package/dist/chat/statewire-banners.d.ts +20 -1
- package/dist/chat/statewire-banners.js +32 -3
- package/dist/chat/statewire-banners.js.map +1 -1
- package/dist/chat/statewire-client-tools.cjs +1 -1
- package/dist/chat/statewire-client-tools.js +1 -1
- package/dist/chat/super-grouping/CollapsibleGroup.cjs +1 -1
- package/dist/chat/super-grouping/CollapsibleGroup.cjs.map +1 -1
- package/dist/chat/super-grouping/CollapsibleGroup.js +1 -1
- package/dist/chat/super-grouping/CollapsibleGroup.js.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingCard.cjs +7 -5
- package/dist/chat/super-grouping/SuperGroupingCard.cjs.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingCard.d.ts +8 -2
- package/dist/chat/super-grouping/SuperGroupingCard.js +7 -5
- package/dist/chat/super-grouping/SuperGroupingCard.js.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingTranscript.cjs +350 -0
- package/dist/chat/super-grouping/SuperGroupingTranscript.cjs.map +1 -0
- package/dist/chat/super-grouping/SuperGroupingTranscript.d.ts +31 -0
- package/dist/chat/super-grouping/SuperGroupingTranscript.js +350 -0
- package/dist/chat/super-grouping/SuperGroupingTranscript.js.map +1 -0
- package/dist/chat/super-grouping/ToolTimeline.cjs +13 -2
- package/dist/chat/super-grouping/ToolTimeline.cjs.map +1 -1
- package/dist/chat/super-grouping/ToolTimeline.d.ts +10 -3
- package/dist/chat/super-grouping/ToolTimeline.js +13 -2
- package/dist/chat/super-grouping/ToolTimeline.js.map +1 -1
- package/dist/chat/super-grouping/activity-timeline.cjs +51 -26
- package/dist/chat/super-grouping/activity-timeline.cjs.map +1 -1
- package/dist/chat/super-grouping/activity-timeline.d.ts +40 -8
- package/dist/chat/super-grouping/activity-timeline.js +52 -27
- package/dist/chat/super-grouping/activity-timeline.js.map +1 -1
- package/dist/chat/super-grouping/index.cjs +12 -0
- package/dist/chat/super-grouping/index.cjs.map +1 -1
- package/dist/chat/super-grouping/index.d.ts +7 -2
- package/dist/chat/super-grouping/index.js +14 -2
- package/dist/chat/super-grouping/index.js.map +1 -1
- package/dist/chat/super-grouping/timeline-step.cjs +14 -5
- package/dist/chat/super-grouping/timeline-step.cjs.map +1 -1
- package/dist/chat/super-grouping/timeline-step.d.ts +10 -1
- package/dist/chat/super-grouping/timeline-step.js +15 -6
- package/dist/chat/super-grouping/timeline-step.js.map +1 -1
- package/dist/chat/super-grouping/turn-segments.cjs +82 -0
- package/dist/chat/super-grouping/turn-segments.cjs.map +1 -0
- package/dist/chat/super-grouping/turn-segments.d.ts +69 -0
- package/dist/chat/super-grouping/turn-segments.js +82 -0
- package/dist/chat/super-grouping/turn-segments.js.map +1 -0
- package/dist/chat/super-grouping/turn-timing.cjs +110 -0
- package/dist/chat/super-grouping/turn-timing.cjs.map +1 -0
- package/dist/chat/super-grouping/turn-timing.d.ts +52 -0
- package/dist/chat/super-grouping/turn-timing.js +110 -0
- package/dist/chat/super-grouping/turn-timing.js.map +1 -0
- package/dist/chat/tiptap-text.cjs +1 -1
- package/dist/chat/tiptap-text.js +1 -1
- package/dist/chat/use-athena-run-live.cjs +1 -1
- package/dist/chat/use-athena-run-live.js +1 -1
- package/dist/chat/use-statewire-approval-request.cjs +73 -4
- package/dist/chat/use-statewire-approval-request.cjs.map +1 -1
- package/dist/chat/use-statewire-approval-request.js +74 -5
- package/dist/chat/use-statewire-approval-request.js.map +1 -1
- package/dist/chat-ui/composer/composer-message.cjs +284 -0
- package/dist/chat-ui/composer/composer-message.cjs.map +1 -0
- package/dist/chat-ui/composer/composer-message.d.ts +152 -0
- package/dist/chat-ui/composer/composer-message.js +284 -0
- package/dist/chat-ui/composer/composer-message.js.map +1 -0
- package/dist/chat-ui/composer/tiptap-composer.cjs +57 -11
- package/dist/chat-ui/composer/tiptap-composer.cjs.map +1 -1
- package/dist/chat-ui/composer/tiptap-composer.d.ts +34 -6
- package/dist/chat-ui/composer/tiptap-composer.js +57 -11
- package/dist/chat-ui/composer/tiptap-composer.js.map +1 -1
- package/dist/chat-ui/index.cjs +4 -1
- package/dist/chat-ui/index.cjs.map +1 -1
- package/dist/chat-ui/index.d.ts +3 -2
- package/dist/chat-ui/index.js +5 -2
- package/dist/chat-ui/index.js.map +1 -1
- package/dist/chat-ui/mentions/mention-chip.cjs +3 -2
- package/dist/chat-ui/mentions/mention-chip.cjs.map +1 -1
- package/dist/chat-ui/mentions/mention-chip.js +4 -3
- package/dist/chat-ui/mentions/mention-chip.js.map +1 -1
- package/dist/chat-ui/mentions/mention-extension.cjs +8 -2
- package/dist/chat-ui/mentions/mention-extension.cjs.map +1 -1
- package/dist/chat-ui/mentions/mention-extension.js +8 -2
- package/dist/chat-ui/mentions/mention-extension.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-popup.cjs +3 -1
- package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-popup.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-popup.js +3 -1
- package/dist/chat-ui/mentions/suggestions/components/mention-suggestion-popup.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs +65 -19
- package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/sources/index.d.ts +15 -0
- package/dist/chat-ui/mentions/suggestions/data/sources/index.js +67 -21
- package/dist/chat-ui/mentions/suggestions/data/sources/index.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.cjs +4 -2
- 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 +2 -1
- package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.js +5 -3
- package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.js.map +1 -1
- package/dist/chat-ui/messages/message-components.cjs +30 -10
- package/dist/chat-ui/messages/message-components.cjs.map +1 -1
- package/dist/chat-ui/messages/message-components.d.ts +21 -1
- package/dist/chat-ui/messages/message-components.js +30 -10
- package/dist/chat-ui/messages/message-components.js.map +1 -1
- package/dist/chat-ui/messages/runtime-message.cjs +1 -1
- package/dist/chat-ui/messages/runtime-message.js +1 -1
- package/dist/chat-ui/messages/statewire-continue-run.cjs +5 -5
- package/dist/chat-ui/messages/statewire-continue-run.js +5 -5
- package/dist/chat-ui/messages/user-edit-composer.cjs +1 -1
- package/dist/chat-ui/messages/user-edit-composer.js +1 -1
- package/dist/chat-ui/messages/wake-marker.cjs +39 -4
- package/dist/chat-ui/messages/wake-marker.cjs.map +1 -1
- package/dist/chat-ui/messages/wake-marker.d.ts +16 -5
- package/dist/chat-ui/messages/wake-marker.js +40 -5
- package/dist/chat-ui/messages/wake-marker.js.map +1 -1
- package/dist/chat-ui/rich-text/chat-message-body.cjs +12 -8
- package/dist/chat-ui/rich-text/chat-message-body.cjs.map +1 -1
- package/dist/chat-ui/rich-text/chat-message-body.d.ts +6 -1
- package/dist/chat-ui/rich-text/chat-message-body.js +13 -9
- package/dist/chat-ui/rich-text/chat-message-body.js.map +1 -1
- package/dist/chat-ui/rich-text/chat-text-schema.cjs +64 -6
- package/dist/chat-ui/rich-text/chat-text-schema.cjs.map +1 -1
- package/dist/chat-ui/rich-text/chat-text-schema.d.ts +5 -0
- package/dist/chat-ui/rich-text/chat-text-schema.js +66 -8
- package/dist/chat-ui/rich-text/chat-text-schema.js.map +1 -1
- package/dist/chat-ui/statewire.cjs +1 -1
- package/dist/chat-ui/statewire.d.ts +1 -1
- package/dist/chat-ui/statewire.js +1 -1
- package/dist/chat-ui/thread/statewire-history-edge.cjs +2 -2
- package/dist/chat-ui/thread/statewire-history-edge.js +2 -2
- package/dist/collab/client.cjs +218 -13
- package/dist/collab/client.cjs.map +1 -1
- package/dist/collab/client.d.ts +105 -2
- package/dist/collab/client.js +221 -17
- package/dist/collab/client.js.map +1 -1
- package/dist/collab/index.cjs +2 -0
- package/dist/collab/index.cjs.map +1 -1
- package/dist/collab/index.d.ts +1 -1
- package/dist/collab/index.js +3 -1
- package/dist/composer/AttachmentContext.cjs +38 -12
- package/dist/composer/AttachmentContext.cjs.map +1 -1
- package/dist/composer/AttachmentContext.d.ts +22 -1
- package/dist/composer/AttachmentContext.js +40 -14
- package/dist/composer/AttachmentContext.js.map +1 -1
- package/dist/composer/QuoteContext.cjs +80 -28
- package/dist/composer/QuoteContext.cjs.map +1 -1
- package/dist/composer/QuoteContext.d.ts +35 -6
- package/dist/composer/QuoteContext.js +82 -30
- package/dist/composer/QuoteContext.js.map +1 -1
- package/dist/composer/build-composed-message.cjs +27 -0
- package/dist/composer/build-composed-message.cjs.map +1 -1
- package/dist/composer/build-composed-message.d.ts +21 -0
- package/dist/composer/build-composed-message.js +28 -1
- package/dist/composer/build-composed-message.js.map +1 -1
- package/dist/composer/composer-handoff.cjs +13 -1
- package/dist/composer/composer-handoff.cjs.map +1 -1
- package/dist/composer/composer-handoff.d.ts +12 -0
- package/dist/composer/composer-handoff.js +15 -3
- package/dist/composer/composer-handoff.js.map +1 -1
- package/dist/composer/index.d.ts +6 -3
- package/dist/composer/useReadComposerDraft.cjs +16 -0
- package/dist/composer/useReadComposerDraft.cjs.map +1 -0
- package/dist/composer/useReadComposerDraft.d.ts +6 -0
- package/dist/composer/useReadComposerDraft.js +16 -0
- package/dist/composer/useReadComposerDraft.js.map +1 -0
- package/dist/diagnostics/errors.cjs +6 -0
- package/dist/diagnostics/errors.cjs.map +1 -1
- package/dist/diagnostics/errors.d.ts +6 -0
- package/dist/diagnostics/errors.js +6 -0
- package/dist/diagnostics/errors.js.map +1 -1
- package/dist/index.cjs +159 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +53 -12
- package/dist/index.js +166 -14
- package/dist/index.js.map +1 -1
- package/dist/lib/owner-document.cjs +32 -0
- package/dist/lib/owner-document.cjs.map +1 -0
- package/dist/lib/owner-document.d.ts +17 -0
- package/dist/lib/owner-document.js +32 -0
- package/dist/lib/owner-document.js.map +1 -0
- package/dist/lib/portal-surface.cjs +55 -0
- package/dist/lib/portal-surface.cjs.map +1 -0
- package/dist/lib/portal-surface.d.ts +37 -0
- package/dist/lib/portal-surface.js +55 -0
- package/dist/lib/portal-surface.js.map +1 -0
- package/dist/lib/use-athena-rest-query.cjs +34 -0
- package/dist/lib/use-athena-rest-query.cjs.map +1 -0
- package/dist/lib/use-athena-rest-query.d.ts +31 -0
- package/dist/lib/use-athena-rest-query.js +34 -0
- package/dist/lib/use-athena-rest-query.js.map +1 -0
- package/dist/provider/AthenaProvider.cjs +36 -6
- package/dist/provider/AthenaProvider.cjs.map +1 -1
- package/dist/provider/AthenaProvider.d.ts +20 -1
- package/dist/provider/AthenaProvider.js +38 -8
- package/dist/provider/AthenaProvider.js.map +1 -1
- package/dist/provider/citation-links.d.ts +10 -2
- package/dist/{packages/react → react}/package.json.cjs +1 -1
- package/dist/{packages/react → react}/package.json.js +1 -1
- package/dist/runtime/statewire-lifecycle.cjs +15 -3
- package/dist/runtime/statewire-lifecycle.cjs.map +1 -1
- package/dist/runtime/statewire-lifecycle.d.ts +6 -0
- package/dist/runtime/statewire-lifecycle.js +15 -3
- package/dist/runtime/statewire-lifecycle.js.map +1 -1
- package/dist/runtime/useAthenaStatewireRuntime.cjs +11 -7
- package/dist/runtime/useAthenaStatewireRuntime.cjs.map +1 -1
- package/dist/runtime/useAthenaStatewireRuntime.js +11 -7
- package/dist/runtime/useAthenaStatewireRuntime.js.map +1 -1
- package/dist/search/useAthenaRepoSearch.cjs +5 -13
- package/dist/search/useAthenaRepoSearch.cjs.map +1 -1
- package/dist/search/useAthenaRepoSearch.d.ts +3 -3
- package/dist/search/useAthenaRepoSearch.js +6 -14
- package/dist/search/useAthenaRepoSearch.js.map +1 -1
- package/dist/sheet-range/a1.cjs +162 -0
- package/dist/sheet-range/a1.cjs.map +1 -0
- package/dist/sheet-range/a1.d.ts +91 -0
- package/dist/sheet-range/a1.js +162 -0
- package/dist/sheet-range/a1.js.map +1 -0
- package/dist/sheet-range/index.cjs +22 -0
- package/dist/sheet-range/index.cjs.map +1 -0
- package/dist/sheet-range/index.d.ts +12 -0
- package/dist/sheet-range/index.js +22 -0
- package/dist/sheet-range/index.js.map +1 -0
- package/dist/sheet-range/range-preview-table.cjs +75 -0
- package/dist/sheet-range/range-preview-table.cjs.map +1 -0
- package/dist/sheet-range/range-preview-table.d.ts +20 -0
- package/dist/sheet-range/range-preview-table.js +75 -0
- package/dist/sheet-range/range-preview-table.js.map +1 -0
- package/dist/sheet-range/range-preview.cjs +116 -0
- package/dist/sheet-range/range-preview.cjs.map +1 -0
- package/dist/sheet-range/range-preview.d.ts +67 -0
- package/dist/sheet-range/range-preview.js +116 -0
- package/dist/sheet-range/range-preview.js.map +1 -0
- package/dist/styles.css +1 -1
- package/dist/threads/Inbox.cjs +289 -0
- package/dist/threads/Inbox.cjs.map +1 -0
- package/dist/threads/Inbox.d.ts +46 -0
- package/dist/threads/Inbox.js +289 -0
- package/dist/threads/Inbox.js.map +1 -0
- package/dist/threads/SessionList.cjs +51 -126
- package/dist/threads/SessionList.cjs.map +1 -1
- package/dist/threads/SessionList.d.ts +26 -1
- package/dist/threads/SessionList.js +45 -120
- package/dist/threads/SessionList.js.map +1 -1
- package/dist/threads/SessionsPage.cjs +753 -0
- package/dist/threads/SessionsPage.cjs.map +1 -0
- package/dist/threads/SessionsPage.d.ts +35 -0
- package/dist/threads/SessionsPage.js +753 -0
- package/dist/threads/SessionsPage.js.map +1 -0
- package/dist/threads/api.cjs +21 -1
- package/dist/threads/api.cjs.map +1 -1
- package/dist/threads/api.d.ts +59 -0
- package/dist/threads/api.js +21 -1
- package/dist/threads/api.js.map +1 -1
- package/dist/threads/conversation-list-fetcher.cjs +9 -2
- package/dist/threads/conversation-list-fetcher.cjs.map +1 -1
- package/dist/threads/conversation-list-fetcher.d.ts +14 -1
- package/dist/threads/conversation-list-fetcher.js +9 -2
- package/dist/threads/conversation-list-fetcher.js.map +1 -1
- package/dist/threads/index.d.ts +2 -1
- package/dist/threads/pull-request-display.cjs +25 -0
- package/dist/threads/pull-request-display.cjs.map +1 -0
- package/dist/threads/pull-request-display.d.ts +15 -0
- package/dist/threads/pull-request-display.js +25 -0
- package/dist/threads/pull-request-display.js.map +1 -0
- package/dist/threads/session-list-model.cjs +16 -2
- package/dist/threads/session-list-model.cjs.map +1 -1
- package/dist/threads/session-list-model.d.ts +10 -0
- package/dist/threads/session-list-model.js +16 -2
- package/dist/threads/session-list-model.js.map +1 -1
- package/dist/threads/session-row-parts.cjs +152 -0
- package/dist/threads/session-row-parts.cjs.map +1 -0
- package/dist/threads/session-row-parts.d.ts +50 -0
- package/dist/threads/session-row-parts.js +152 -0
- package/dist/threads/session-row-parts.js.map +1 -0
- package/dist/threads/sessions-page-model.cjs +305 -0
- package/dist/threads/sessions-page-model.cjs.map +1 -0
- package/dist/threads/sessions-page-model.d.ts +86 -0
- package/dist/threads/sessions-page-model.js +305 -0
- package/dist/threads/sessions-page-model.js.map +1 -0
- package/dist/threads/sessions-page-storage.cjs +93 -0
- package/dist/threads/sessions-page-storage.cjs.map +1 -0
- package/dist/threads/sessions-page-storage.d.ts +23 -0
- package/dist/threads/sessions-page-storage.js +93 -0
- package/dist/threads/sessions-page-storage.js.map +1 -0
- package/dist/threads/sessions-query.cjs +235 -0
- package/dist/threads/sessions-query.cjs.map +1 -0
- package/dist/threads/sessions-query.d.ts +119 -0
- package/dist/threads/sessions-query.js +235 -0
- package/dist/threads/sessions-query.js.map +1 -0
- package/dist/threads/statewire-thread-list.cjs +133 -40
- package/dist/threads/statewire-thread-list.cjs.map +1 -1
- package/dist/threads/statewire-thread-list.d.ts +83 -2
- package/dist/threads/statewire-thread-list.js +134 -41
- package/dist/threads/statewire-thread-list.js.map +1 -1
- package/dist/threads/use-athena-sessions.cjs +198 -0
- package/dist/threads/use-athena-sessions.cjs.map +1 -0
- package/dist/threads/use-athena-sessions.d.ts +81 -0
- package/dist/threads/use-athena-sessions.js +198 -0
- package/dist/threads/use-athena-sessions.js.map +1 -0
- package/dist/threads/use-rest-conversation-history.cjs +1 -1
- package/dist/threads/use-rest-conversation-history.js +1 -1
- package/dist/threads/use-statewire-conversation-history.cjs +1 -1
- package/dist/threads/use-statewire-conversation-history.d.ts +3 -0
- package/dist/threads/use-statewire-conversation-history.js +1 -1
- package/dist/threads/use-thread-read-state.cjs +73 -0
- package/dist/threads/use-thread-read-state.cjs.map +1 -0
- package/dist/threads/use-thread-read-state.d.ts +51 -0
- package/dist/threads/use-thread-read-state.js +73 -0
- package/dist/threads/use-thread-read-state.js.map +1 -0
- package/dist/tiptap-markdown-table/src/markdown-table-serializer.cjs.map +1 -0
- package/dist/tiptap-markdown-table/src/markdown-table-serializer.js.map +1 -0
- package/dist/tools/auto-open-tools.cjs +2 -0
- package/dist/tools/auto-open-tools.cjs.map +1 -1
- package/dist/tools/auto-open-tools.js +2 -0
- package/dist/tools/auto-open-tools.js.map +1 -1
- package/dist/tools/file-tool-uis.cjs +18 -43
- package/dist/tools/file-tool-uis.cjs.map +1 -1
- package/dist/tools/file-tool-uis.d.ts +1 -2
- package/dist/tools/file-tool-uis.js +18 -42
- package/dist/tools/file-tool-uis.js.map +1 -1
- package/dist/tools/index.cjs +6 -2
- package/dist/tools/index.cjs.map +1 -1
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.js +6 -2
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/misc-tool-uis.cjs +2 -2
- package/dist/tools/misc-tool-uis.js +2 -2
- package/dist/tools/primitives.cjs +1 -1
- package/dist/tools/primitives.js +1 -1
- package/dist/tools/read-asset-tool-ui.cjs +21 -70
- package/dist/tools/read-asset-tool-ui.cjs.map +1 -1
- package/dist/tools/read-asset-tool-ui.js +21 -70
- package/dist/tools/read-asset-tool-ui.js.map +1 -1
- package/dist/tools/step-text.cjs +21 -0
- package/dist/tools/step-text.cjs.map +1 -0
- package/dist/tools/step-text.d.ts +10 -0
- package/dist/tools/step-text.js +21 -0
- package/dist/tools/step-text.js.map +1 -0
- package/dist/tools/tool-fallback.cjs +24 -5
- package/dist/tools/tool-fallback.cjs.map +1 -1
- package/dist/tools/tool-fallback.d.ts +3 -1
- package/dist/tools/tool-fallback.js +24 -5
- package/dist/tools/tool-fallback.js.map +1 -1
- package/dist/tools/tool-summary.cjs +661 -0
- package/dist/tools/tool-summary.cjs.map +1 -0
- package/dist/tools/tool-summary.d.ts +99 -0
- package/dist/tools/tool-summary.js +661 -0
- package/dist/tools/tool-summary.js.map +1 -0
- package/dist/tools/tool-uis.cjs +37 -95
- package/dist/tools/tool-uis.cjs.map +1 -1
- package/dist/tools/tool-uis.js +37 -95
- package/dist/tools/tool-uis.js.map +1 -1
- package/dist/tools/voice-update-tool-ui.cjs +1 -1
- package/dist/tools/voice-update-tool-ui.js +1 -1
- package/dist/tools/write-todos-tool-ui.cjs +3 -2
- package/dist/tools/write-todos-tool-ui.cjs.map +1 -1
- package/dist/tools/write-todos-tool-ui.d.ts +5 -0
- package/dist/tools/write-todos-tool-ui.js +5 -4
- package/dist/tools/write-todos-tool-ui.js.map +1 -1
- package/dist/ui/popover.cjs +6 -6
- package/dist/ui/popover.cjs.map +1 -1
- package/dist/ui/popover.js +6 -6
- package/dist/ui/popover.js.map +1 -1
- package/dist/ui/tooltip.cjs +16 -2
- package/dist/ui/tooltip.cjs.map +1 -1
- package/dist/ui/tooltip.d.ts +1 -1
- package/dist/ui/tooltip.js +16 -2
- package/dist/ui/tooltip.js.map +1 -1
- package/dist/version.cjs +1 -1
- package/dist/version.js +1 -1
- package/dist/voice/use-athena-voice-session.cjs.map +1 -1
- package/dist/voice/use-athena-voice-session.d.ts +3 -3
- package/dist/voice/use-athena-voice-session.js.map +1 -1
- package/dist/workbench/SessionWorkbench.cjs +378 -0
- package/dist/workbench/SessionWorkbench.cjs.map +1 -0
- package/dist/workbench/SessionWorkbench.d.ts +30 -0
- package/dist/workbench/SessionWorkbench.js +378 -0
- package/dist/workbench/SessionWorkbench.js.map +1 -0
- package/dist/workbench/session-workbench-context.cjs +26 -0
- package/dist/workbench/session-workbench-context.cjs.map +1 -0
- package/dist/workbench/session-workbench-context.d.ts +55 -0
- package/dist/workbench/session-workbench-context.js +26 -0
- package/dist/workbench/session-workbench-context.js.map +1 -0
- package/dist/workbench/session-workbench-model.cjs +288 -0
- package/dist/workbench/session-workbench-model.cjs.map +1 -0
- package/dist/workbench/session-workbench-model.d.ts +168 -0
- package/dist/workbench/session-workbench-model.js +288 -0
- package/dist/workbench/session-workbench-model.js.map +1 -0
- package/dist/workbench/session-workbench-panes.cjs +580 -0
- package/dist/workbench/session-workbench-panes.cjs.map +1 -0
- package/dist/workbench/session-workbench-panes.d.ts +16 -0
- package/dist/workbench/session-workbench-panes.js +580 -0
- package/dist/workbench/session-workbench-panes.js.map +1 -0
- package/dist/workbench/session-workspace-api.cjs +157 -0
- package/dist/workbench/session-workspace-api.cjs.map +1 -0
- package/dist/workbench/session-workspace-api.d.ts +70 -0
- package/dist/workbench/session-workspace-api.js +157 -0
- package/dist/workbench/session-workspace-api.js.map +1 -0
- package/dist/workbench/use-session-workspace.cjs +100 -0
- package/dist/workbench/use-session-workspace.cjs.map +1 -0
- package/dist/workbench/use-session-workspace.d.ts +45 -0
- package/dist/workbench/use-session-workspace.js +100 -0
- package/dist/workbench/use-session-workspace.js.map +1 -0
- package/dist/workbench/workbench-layout-context.cjs +10 -0
- package/dist/workbench/workbench-layout-context.cjs.map +1 -0
- package/dist/workbench/workbench-layout-context.d.ts +17 -0
- package/dist/workbench/workbench-layout-context.js +10 -0
- package/dist/workbench/workbench-layout-context.js.map +1 -0
- package/package.json +20 -9
- package/dist/node_modules/@assistant-ui/react-langchain/dist/converter.cjs +0 -77
- package/dist/node_modules/@assistant-ui/react-langchain/dist/converter.cjs.map +0 -1
- package/dist/node_modules/@assistant-ui/react-langchain/dist/converter.js +0 -77
- package/dist/node_modules/@assistant-ui/react-langchain/dist/converter.js.map +0 -1
- package/dist/node_modules/@assistant-ui/react-langgraph/dist/convertLangChainMessages.cjs +0 -181
- package/dist/node_modules/@assistant-ui/react-langgraph/dist/convertLangChainMessages.cjs.map +0 -1
- package/dist/node_modules/@assistant-ui/react-langgraph/dist/convertLangChainMessages.js +0 -181
- package/dist/node_modules/@assistant-ui/react-langgraph/dist/convertLangChainMessages.js.map +0 -1
- package/dist/packages/agent-runtime/src/asset-attachment.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/asset-attachment.js.map +0 -1
- package/dist/packages/agent-runtime/src/auth-denial.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/auth-denial.js.map +0 -1
- package/dist/packages/agent-runtime/src/client-tool-bridge.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/client-tool-bridge.js.map +0 -1
- package/dist/packages/agent-runtime/src/client-tools.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/client-tools.js.map +0 -1
- package/dist/packages/agent-runtime/src/conversation-index.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/conversation-index.js.map +0 -1
- package/dist/packages/agent-runtime/src/conversation-list.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/conversation-list.js.map +0 -1
- package/dist/packages/agent-runtime/src/deep-agent-transport-recipe.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/deep-agent-transport-recipe.js.map +0 -1
- package/dist/packages/agent-runtime/src/edit-command.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/edit-command.js.map +0 -1
- package/dist/packages/agent-runtime/src/errors.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/errors.js.map +0 -1
- package/dist/packages/agent-runtime/src/generated/runconfig-contract.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/generated/runconfig-contract.js.map +0 -1
- package/dist/packages/agent-runtime/src/github-wake-event.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/github-wake-event.js.map +0 -1
- package/dist/packages/agent-runtime/src/interrupts.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/interrupts.js.map +0 -1
- package/dist/packages/agent-runtime/src/message-author.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/message-author.js.map +0 -1
- package/dist/packages/agent-runtime/src/message-window.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/message-window.js.map +0 -1
- package/dist/packages/agent-runtime/src/messages.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/messages.js.map +0 -1
- package/dist/packages/agent-runtime/src/model-context.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/model-context.js.map +0 -1
- package/dist/packages/agent-runtime/src/optimistic-content.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/optimistic-content.js.map +0 -1
- package/dist/packages/agent-runtime/src/protocol.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/protocol.js.map +0 -1
- package/dist/packages/agent-runtime/src/queue.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/queue.js.map +0 -1
- package/dist/packages/agent-runtime/src/quota-safe-local-storage-session.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/quota-safe-local-storage-session.js.map +0 -1
- package/dist/packages/agent-runtime/src/runtime-messages.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/runtime-messages.js.map +0 -1
- package/dist/packages/agent-runtime/src/screen-point.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/screen-point.js.map +0 -1
- package/dist/packages/agent-runtime/src/send-recovery.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/send-recovery.js.map +0 -1
- package/dist/packages/agent-runtime/src/statewire-attach-observer.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/statewire-attach-observer.js.map +0 -1
- package/dist/packages/agent-runtime/src/statewire-state.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/statewire-state.js.map +0 -1
- package/dist/packages/agent-runtime/src/statewire-suspended.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/statewire-suspended.js.map +0 -1
- package/dist/packages/agent-runtime/src/statewire-transport.cjs +0 -11
- package/dist/packages/agent-runtime/src/statewire-transport.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/statewire-transport.js +0 -11
- package/dist/packages/agent-runtime/src/statewire-transport.js.map +0 -1
- package/dist/packages/agent-runtime/src/streaming-markdown.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/streaming-markdown.js.map +0 -1
- package/dist/packages/agent-runtime/src/thread-extras.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/thread-extras.js.map +0 -1
- package/dist/packages/agent-runtime/src/thread-snapshot-cache.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/thread-snapshot-cache.js.map +0 -1
- package/dist/packages/agent-runtime/src/thread-status.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/thread-status.js.map +0 -1
- package/dist/packages/agent-runtime/src/tool-metadata.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/tool-metadata.js.map +0 -1
- package/dist/packages/agent-runtime/src/tool-outputs.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/tool-outputs.js.map +0 -1
- package/dist/packages/agent-runtime/src/tool-result.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/tool-result.js.map +0 -1
- package/dist/packages/agent-runtime/src/use-conversation-list.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/use-conversation-list.js.map +0 -1
- package/dist/packages/agent-runtime/src/use-deep-agent-config.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/use-deep-agent-config.js.map +0 -1
- package/dist/packages/agent-runtime/src/use-deep-agent-edit-submit.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/use-deep-agent-edit-submit.js.map +0 -1
- package/dist/packages/agent-runtime/src/use-deep-agent-runtime.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/use-deep-agent-runtime.js.map +0 -1
- package/dist/packages/agent-runtime/src/use-deep-agent-thread.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/use-deep-agent-thread.js.map +0 -1
- package/dist/packages/agent-runtime/src/use-deep-agent-window-sync.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/use-deep-agent-window-sync.js.map +0 -1
- package/dist/packages/agent-runtime/src/voice-presentation.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/voice-presentation.js.map +0 -1
- package/dist/packages/agent-runtime/src/voice-turn-grouping.cjs.map +0 -1
- package/dist/packages/agent-runtime/src/voice-turn-grouping.js.map +0 -1
- package/dist/packages/tiptap-markdown-table/src/markdown-table-serializer.cjs.map +0 -1
- package/dist/packages/tiptap-markdown-table/src/markdown-table-serializer.js.map +0 -1
- /package/dist/{packages/agent-runtime → agent-runtime}/src/asset-attachment.cjs +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/asset-attachment.js +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/auth-denial.cjs +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/auth-denial.js +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/client-tool-bridge.cjs +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/client-tool-bridge.js +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/client-tools.cjs +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/client-tools.js +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/conversation-index.cjs +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/conversation-index.js +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/edit-command.cjs +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/edit-command.js +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/github-wake-event.cjs +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/github-wake-event.js +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/message-author.cjs +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/message-author.js +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/message-window.cjs +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/message-window.js +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/model-context.cjs +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/model-context.js +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/optimistic-content.cjs +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/optimistic-content.js +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/protocol.cjs +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/protocol.js +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/runtime-messages.cjs +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/runtime-messages.js +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/screen-point.cjs +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/screen-point.js +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/send-recovery.cjs +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/send-recovery.js +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/statewire-attach-observer.cjs +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/statewire-attach-observer.js +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/streaming-markdown.cjs +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/streaming-markdown.js +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/thread-extras.cjs +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/thread-extras.js +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/thread-snapshot-cache.cjs +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/thread-snapshot-cache.js +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/thread-status.cjs +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/thread-status.js +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/tool-outputs.cjs +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/tool-outputs.js +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/tool-result.cjs +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/tool-result.js +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/use-deep-agent-config.cjs +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/use-deep-agent-config.js +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/use-deep-agent-runtime.cjs +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/use-deep-agent-runtime.js +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/use-deep-agent-window-sync.cjs +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/use-deep-agent-window-sync.js +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/voice-turn-grouping.cjs +0 -0
- /package/dist/{packages/agent-runtime → agent-runtime}/src/voice-turn-grouping.js +0 -0
- /package/dist/{packages/react → react}/package.json.cjs.map +0 -0
- /package/dist/{packages/react → react}/package.json.js.map +0 -0
- /package/dist/{packages/tiptap-markdown-table → tiptap-markdown-table}/src/markdown-table-serializer.cjs +0 -0
- /package/dist/{packages/tiptap-markdown-table → tiptap-markdown-table}/src/markdown-table-serializer.js +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessions-query.js","sources":["../../src/threads/sessions-query.ts"],"sourcesContent":["/**\n * The session-list query behind `SessionsPage` and `Inbox`: what the person\n * asked to see, how it maps onto `POST /api/conversations/threads/list`, and\n * what happens on a server that cannot apply part of it.\n *\n * Every filter is applied by the server as a predicate of its one page\n * statement, so a page is exact and `Load more` continues the filtered set.\n * The server ignores request fields it does not know, so a filter an older\n * agora cannot apply comes back unapplied; the list response names the fields\n * the server applies (`supported_filters`). `planSessionsQuery` splits a query\n * into what to send, what to apply to the loaded rows instead (`degraded`:\n * exact per loaded page, but a page may come back short), and what cannot be\n * applied at all on that server (`unavailable`: the UI disables those\n * controls).\n */\nimport type { ConversationSummary } from '@athenaintel/agent-runtime';\nimport type { ThreadListFilterBody } from './api';\n\nexport type AthenaSessionsSort = 'updated' | 'created';\nexport type AthenaSessionsDirection = 'desc' | 'asc';\n\n/** The collab-channel token for an agent's default channel (sessions with no channel stamp). */\nexport const DEFAULT_COLLAB_CHANNEL = 'default';\n\n/** status_v2 run statuses, in the order a status filter offers them. */\nexport const SESSION_RUN_STATUSES = [\n 'needs_input',\n 'running',\n 'queued',\n 'scheduled',\n 'completed',\n 'failed',\n 'canceled',\n] as const;\nexport type SessionRunStatus = (typeof SESSION_RUN_STATUSES)[number];\n\n/** status_v2 session statuses. */\nexport const SESSION_SESSION_STATUSES = ['active', 'needs_input', 'idle', 'error'] as const;\nexport type SessionSessionStatus = (typeof SESSION_SESSION_STATUSES)[number];\n\n/**\n * What a session list shows. Multi-value fields match any of their values;\n * different fields combine (AND). Unset fields do not filter.\n */\nexport interface AthenaSessionsQuery {\n /** Case-insensitive title search. */\n search?: string;\n /** Collab agents the session started as. */\n collabAgentIds?: readonly string[];\n /** Agent channels (modes); `DEFAULT_COLLAB_CHANNEL` is the agent's default channel. Needs `collabAgentIds`. */\n collabChannelIds?: readonly string[];\n /** Channels the session started from (`web`, `github`, `email`, …). */\n startChannels?: readonly string[];\n /** ISO 8601 bounds; `*After` inclusive, `*Before` exclusive. */\n createdAfter?: string;\n createdBefore?: string;\n updatedAfter?: string;\n updatedBefore?: string;\n /** Only sessions the viewer pinned. */\n favoritesOnly?: boolean;\n /** Only sessions the viewer has not read since they last changed. */\n unreadOnly?: boolean;\n /** status_v2 run statuses (`running` excludes runs silent for 12 hours, as every list does). */\n runStatuses?: readonly SessionRunStatus[];\n /** status_v2 session statuses. */\n sessionStatuses?: readonly SessionSessionStatus[];\n /** `true` only sessions that opened a pull request; `false` only those that opened none. */\n hasPullRequests?: boolean;\n /** `true` only the viewer's own sessions; `false` only sessions shared with them. */\n createdByMe?: boolean;\n /** Leave out sessions dismissed from the inbox. */\n excludeDismissed?: boolean;\n /** Hide sessions started by an automation (a schedule, an email, …). */\n excludeTriggered?: boolean;\n /** Sort key (default `updated`). */\n sort?: AthenaSessionsSort;\n /** Sort direction (default `desc`, newest first). */\n direction?: AthenaSessionsDirection;\n}\n\nexport type AthenaSessionsQueryField = keyof AthenaSessionsQuery;\n\n/** The REST field each query field travels as. */\nconst SERVER_FIELD: Record<AthenaSessionsQueryField, string> = {\n search: 'search',\n collabAgentIds: 'collab_agent_ids',\n collabChannelIds: 'collab_channel_ids',\n startChannels: 'start_channels',\n createdAfter: 'created_after',\n createdBefore: 'created_before',\n updatedAfter: 'updated_after',\n updatedBefore: 'updated_before',\n favoritesOnly: 'favorites_only',\n unreadOnly: 'unread_only',\n runStatuses: 'run_statuses',\n sessionStatuses: 'session_statuses',\n hasPullRequests: 'has_pull_requests',\n createdByMe: 'created_by_me',\n excludeDismissed: 'exclude_dismissed',\n excludeTriggered: 'exclude_triggered',\n sort: 'sort',\n direction: 'direction',\n};\n\n/**\n * The fields every thread-list server has applied, including those that\n * predate `supported_filters` — what a response without the list supports.\n */\nexport const LEGACY_THREAD_LIST_FILTERS: ReadonlySet<string> = new Set([\n 'search',\n 'exclude_triggered',\n 'app_id',\n 'start_channel',\n 'created_after',\n 'include_pull_requests',\n]);\n\n/** The query with unset, empty and default-valued fields dropped and arrays canonicalized. */\nexport function normalizeSessionsQuery(query: AthenaSessionsQuery): AthenaSessionsQuery {\n const out: AthenaSessionsQuery = {};\n const search = query.search?.trim();\n if (search) out.search = search;\n const list = <T extends string>(values: readonly T[] | undefined): T[] | undefined => {\n if (!values || values.length === 0) return undefined;\n return [...new Set(values)].sort();\n };\n const collabAgentIds = list(query.collabAgentIds);\n if (collabAgentIds) out.collabAgentIds = collabAgentIds;\n const collabChannelIds = list(query.collabChannelIds);\n if (collabChannelIds && collabAgentIds) out.collabChannelIds = collabChannelIds;\n const startChannels = list(query.startChannels);\n if (startChannels) out.startChannels = startChannels;\n for (const bound of ['createdAfter', 'createdBefore', 'updatedAfter', 'updatedBefore'] as const) {\n const value = query[bound];\n if (value) out[bound] = value;\n }\n if (query.favoritesOnly) out.favoritesOnly = true;\n if (query.unreadOnly) out.unreadOnly = true;\n const runStatuses = list(query.runStatuses);\n if (runStatuses) out.runStatuses = runStatuses;\n const sessionStatuses = list(query.sessionStatuses);\n if (sessionStatuses) out.sessionStatuses = sessionStatuses;\n if (query.hasPullRequests !== undefined) out.hasPullRequests = query.hasPullRequests;\n if (query.createdByMe !== undefined) out.createdByMe = query.createdByMe;\n if (query.excludeDismissed) out.excludeDismissed = true;\n if (query.excludeTriggered) out.excludeTriggered = true;\n if (query.sort && query.sort !== 'updated') out.sort = query.sort;\n if (query.direction && query.direction !== 'desc') out.direction = query.direction;\n return out;\n}\n\n/** A stable cache identity: semantically equal queries share one key. */\nexport function sessionsQueryKey(query: AthenaSessionsQuery): string {\n const normalized = normalizeSessionsQuery(query) as Record<string, unknown>;\n return JSON.stringify(\n Object.keys(normalized)\n .sort()\n .map((key) => [key, normalized[key]]),\n );\n}\n\n/** The normalized query a `sessionsQueryKey` stands for. */\nexport function sessionsQueryFromKey(key: string): AthenaSessionsQuery {\n const entries: unknown = JSON.parse(key);\n if (!Array.isArray(entries)) return {};\n const query: Record<string, unknown> = {};\n for (const entry of entries) {\n if (Array.isArray(entry) && typeof entry[0] === 'string') query[entry[0]] = entry[1];\n }\n return normalizeSessionsQuery(query as AthenaSessionsQuery);\n}\n\n/** The fields a query sets (after normalization), in a fixed order. */\nexport function activeSessionsQueryFields(query: AthenaSessionsQuery): AthenaSessionsQueryField[] {\n const normalized = normalizeSessionsQuery(query);\n return (Object.keys(SERVER_FIELD) as AthenaSessionsQueryField[]).filter(\n (field) => normalized[field] !== undefined,\n );\n}\n\n/**\n * Every query field a backend can apply nowhere — what a filter UI disables\n * whatever is selected. `supportedFilters` as for `planSessionsQuery`.\n */\nexport function unavailableSessionsQueryFields(options: {\n supportedFilters: ReadonlySet<string> | null;\n includePullRequests: boolean;\n}): AthenaSessionsQueryField[] {\n const supported = options.supportedFilters ?? LEGACY_THREAD_LIST_FILTERS;\n const testable = {\n includePullRequests: options.includePullRequests,\n rowsCarryCreatedByMe: options.supportedFilters !== null,\n };\n return (Object.keys(SERVER_FIELD) as AthenaSessionsQueryField[]).filter(\n (field) =>\n field !== 'sort' &&\n field !== 'direction' &&\n !supported.has(SERVER_FIELD[field]) &&\n !locallyTestable(field, testable),\n );\n}\n\nexport interface SessionsQueryPlan {\n /** Sent to the server (`search` / `exclude_triggered` and `ThreadListFilterBody`). */\n body: ThreadListFilterBody;\n /** Applied to the loaded rows because the server cannot: exact per page, pages may be short. */\n degraded: AthenaSessionsQueryField[];\n /** Cannot be applied on this server at all (the rows carry nothing to test). */\n unavailable: AthenaSessionsQueryField[];\n /** The part of the query the loaded rows are checked against (`matchesSessionsQuery`). */\n local: AthenaSessionsQuery;\n}\n\n/**\n * Which fields a row can be tested on locally, given what this list fetches:\n * pull-request state only rides rows when the list asked for it, and\n * `createdByMe` only on servers new enough to send it.\n */\nfunction locallyTestable(\n field: AthenaSessionsQueryField,\n options: { includePullRequests: boolean; rowsCarryCreatedByMe: boolean },\n): boolean {\n switch (field) {\n case 'excludeDismissed':\n return false;\n case 'hasPullRequests':\n return options.includePullRequests;\n case 'createdByMe':\n return options.rowsCarryCreatedByMe;\n default:\n return true;\n }\n}\n\n/**\n * Split a query for one server. `supportedFilters` is the server's\n * `supported_filters` (`null` for a server that predates it: only\n * `LEGACY_THREAD_LIST_FILTERS` apply there).\n */\nexport function planSessionsQuery(\n query: AthenaSessionsQuery,\n options: { supportedFilters: ReadonlySet<string> | null; includePullRequests: boolean },\n): SessionsQueryPlan {\n const normalized = normalizeSessionsQuery(query);\n const supported = options.supportedFilters ?? LEGACY_THREAD_LIST_FILTERS;\n // A server that echoes `supported_filters` also sends `created_by_me` on rows.\n const rowsCarryCreatedByMe = options.supportedFilters !== null;\n const body: SessionsQueryPlan['body'] = {};\n const degraded: AthenaSessionsQueryField[] = [];\n const unavailable: AthenaSessionsQueryField[] = [];\n const local: AthenaSessionsQuery = {};\n const assignLocal = <K extends AthenaSessionsQueryField>(field: K) => {\n local[field] = normalized[field];\n };\n for (const field of activeSessionsQueryFields(normalized)) {\n const serverField = SERVER_FIELD[field];\n if (supported.has(serverField)) {\n Object.assign(body, { [serverField]: normalized[field] });\n // Server-applied fields are still checked on the loaded rows, so a row\n // a live push changed (read, unpinned, finished) leaves a view it no\n // longer matches; the server already guaranteed the fetched page. The\n // title search is not: the server matches the stored title, while a\n // row shows a display title that may come from its last message.\n if (\n field !== 'search' &&\n locallyTestable(field, {\n includePullRequests: options.includePullRequests,\n rowsCarryCreatedByMe,\n })\n ) {\n assignLocal(field);\n }\n continue;\n }\n if (field === 'sort' || field === 'direction') {\n // Sorting the loaded rows is always possible; it is degraded only in\n // that older pages arrived in the server's default order.\n degraded.push(field);\n assignLocal(field);\n continue;\n }\n if (\n locallyTestable(field, {\n includePullRequests: options.includePullRequests,\n rowsCarryCreatedByMe,\n })\n ) {\n degraded.push(field);\n assignLocal(field);\n } else {\n unavailable.push(field);\n }\n }\n // Sort/direction also order the loaded rows when the server applied them,\n // so a live update keeps its place.\n if (normalized.sort) local.sort = normalized.sort;\n if (normalized.direction) local.direction = normalized.direction;\n return { body, degraded, unavailable, local };\n}\n\nfunction timestamp(value: string | null | undefined): number | null {\n if (!value) return null;\n const parsed = Date.parse(value);\n return Number.isFinite(parsed) ? parsed : null;\n}\n\nfunction withinBounds(\n value: string | null | undefined,\n after: string | undefined,\n before: string | undefined,\n): boolean {\n if (after === undefined && before === undefined) return true;\n const at = timestamp(value);\n if (at === null) return false;\n const afterMs = timestamp(after);\n const beforeMs = timestamp(before);\n if (afterMs !== null && at < afterMs) return false;\n if (beforeMs !== null && at >= beforeMs) return false;\n return true;\n}\n\n/** The fields of a row `matchesSessionsQuery` reads. */\nexport type SessionsQueryRow = Pick<\n ConversationSummary,\n | 'title'\n | 'updatedAt'\n | 'createdAt'\n | 'sourceChannel'\n | 'triggerType'\n | 'isUnread'\n | 'isFavorited'\n | 'runStatus'\n | 'sessionStatus'\n | 'collabAgentId'\n | 'collabChannelId'\n | 'pullRequests'\n | 'createdByMe'\n>;\n\n/**\n * Whether a loaded row matches the locally applicable part of a query\n * (`SessionsQueryPlan.local`). Fields the row does not carry pass, so a\n * missing value never hides a row the server returned.\n */\nexport function matchesSessionsQuery(row: SessionsQueryRow, query: AthenaSessionsQuery): boolean {\n if (query.search && !(row.title ?? '').toLowerCase().includes(query.search.toLowerCase())) {\n return false;\n }\n if (query.collabAgentIds && !query.collabAgentIds.includes(row.collabAgentId ?? '')) return false;\n if (query.collabChannelIds) {\n const channel = row.collabChannelId || DEFAULT_COLLAB_CHANNEL;\n if (!query.collabChannelIds.includes(channel)) return false;\n }\n if (query.startChannels && !query.startChannels.includes(row.sourceChannel ?? '')) return false;\n if (!withinBounds(row.createdAt, query.createdAfter, query.createdBefore)) return false;\n if (!withinBounds(row.updatedAt, query.updatedAfter, query.updatedBefore)) return false;\n if (query.favoritesOnly && row.isFavorited !== true) return false;\n if (query.unreadOnly && !row.isUnread) return false;\n if (query.runStatuses && !(query.runStatuses as readonly string[]).includes(row.runStatus ?? '')) {\n return false;\n }\n if (\n query.sessionStatuses &&\n !(query.sessionStatuses as readonly string[]).includes(row.sessionStatus ?? '')\n ) {\n return false;\n }\n if (query.hasPullRequests !== undefined && row.pullRequests !== undefined && row.pullRequests !== null) {\n if (query.hasPullRequests !== row.pullRequests.length > 0) return false;\n }\n if (query.createdByMe !== undefined && row.createdByMe !== undefined) {\n if (query.createdByMe !== row.createdByMe) return false;\n }\n if (query.excludeTriggered) {\n const trigger = row.triggerType?.trim().toLowerCase() ?? '';\n if (trigger && trigger !== 'manual') return false;\n }\n return true;\n}\n\n/** Rows in the query's order (stable; unparseable times last). */\nexport function sortSessions<T extends Pick<ConversationSummary, 'updatedAt' | 'createdAt'>>(\n rows: readonly T[],\n query: Pick<AthenaSessionsQuery, 'sort' | 'direction'>,\n): T[] {\n const key = query.sort === 'created' ? 'createdAt' : 'updatedAt';\n const sign = query.direction === 'asc' ? 1 : -1;\n return rows\n .map((row, index) => ({ row, index, at: timestamp(row[key]) }))\n .sort((a, b) => {\n if (a.at === null || b.at === null) {\n if (a.at === b.at) return a.index - b.index;\n return a.at === null ? 1 : -1;\n }\n return (a.at - b.at) * sign || a.index - b.index;\n })\n .map(({ row }) => row);\n}\n\n/** The server fields a response says it applies, or `null` when it predates the list. */\nexport function supportedFiltersFromResponse(\n supported: readonly string[] | undefined,\n): ReadonlySet<string> | null {\n return Array.isArray(supported) ? new Set(supported) : null;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -17,10 +17,11 @@ const authRefusalRestart = require("../runtime/auth-refusal-restart.cjs");
|
|
|
17
17
|
const credentialRenewal = require("../runtime/credential-renewal.cjs");
|
|
18
18
|
const useThreadArchive = require("./use-thread-archive.cjs");
|
|
19
19
|
const useThreadFavorite = require("./use-thread-favorite.cjs");
|
|
20
|
+
const useThreadReadState = require("./use-thread-read-state.cjs");
|
|
20
21
|
const useThreadRename = require("./use-thread-rename.cjs");
|
|
21
|
-
const conversationList = require("../
|
|
22
|
-
const useConversationList = require("../
|
|
23
|
-
const conversationIndex = require("../
|
|
22
|
+
const conversationList = require("../agent-runtime/src/conversation-list.cjs");
|
|
23
|
+
const useConversationList = require("../agent-runtime/src/use-conversation-list.cjs");
|
|
24
|
+
const conversationIndex = require("../agent-runtime/src/conversation-index.cjs");
|
|
24
25
|
const AthenaStatewireThreadListContext = react.createContext(null);
|
|
25
26
|
function useAthenaStatewireThreadList() {
|
|
26
27
|
return react.useContext(AthenaStatewireThreadListContext);
|
|
@@ -29,6 +30,16 @@ function useRefreshThreadList() {
|
|
|
29
30
|
var _a;
|
|
30
31
|
return ((_a = useAthenaStatewireThreadList()) == null ? void 0 : _a.refresh) ?? null;
|
|
31
32
|
}
|
|
33
|
+
function indexedThreadsToRefreshFor({
|
|
34
|
+
entries,
|
|
35
|
+
listedThreadIds,
|
|
36
|
+
refreshedThreadIds,
|
|
37
|
+
appId,
|
|
38
|
+
additionalAppIds
|
|
39
|
+
}) {
|
|
40
|
+
const shownAppIds = appId || additionalAppIds.length > 0 ? /* @__PURE__ */ new Set([...appId ? [appId] : [], ...additionalAppIds]) : null;
|
|
41
|
+
return entries.filter((entry) => !shownAppIds || shownAppIds.has(entry.app_id ?? "")).map((entry) => entry.thread_id).filter((threadId) => !listedThreadIds.has(threadId) && !refreshedThreadIds.has(threadId));
|
|
42
|
+
}
|
|
32
43
|
function threadSummaryFromConversation(conversation) {
|
|
33
44
|
return {
|
|
34
45
|
id: conversation.threadId,
|
|
@@ -45,9 +56,23 @@ function threadSummaryFromConversation(conversation) {
|
|
|
45
56
|
triggerType: conversation.triggerType,
|
|
46
57
|
pullRequests: conversation.pullRequests ?? null,
|
|
47
58
|
lastWake: conversation.lastWake ?? null,
|
|
48
|
-
updatedAt: conversation.updatedAt
|
|
59
|
+
updatedAt: conversation.updatedAt,
|
|
60
|
+
createdAt: conversation.createdAt,
|
|
61
|
+
preview: conversation.preview,
|
|
62
|
+
collabAgentId: conversation.collabAgentId ?? null,
|
|
63
|
+
collabChannelId: conversation.collabChannelId ?? null,
|
|
64
|
+
createdByMe: conversation.createdByMe ?? null
|
|
49
65
|
};
|
|
50
66
|
}
|
|
67
|
+
function foldConversationIndex(conversations, indexByThread) {
|
|
68
|
+
return conversations.map((conversation) => {
|
|
69
|
+
const entry = indexByThread.get(conversation.threadId);
|
|
70
|
+
if (!entry) return conversation;
|
|
71
|
+
const merged = conversationList.summaryFromConversationIndexEntry(entry, conversation);
|
|
72
|
+
return title.normalizeThreadTitle(merged.title) === void 0 ? { ...merged, title: conversation.title } : merged;
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
const AthenaSessionsLiveContext = react.createContext(null);
|
|
51
76
|
const THREAD_LIST_PAGE_SIZE = 50;
|
|
52
77
|
function StatewireThreadListState({
|
|
53
78
|
backendUrl,
|
|
@@ -56,6 +81,7 @@ function StatewireThreadListState({
|
|
|
56
81
|
token,
|
|
57
82
|
getToken,
|
|
58
83
|
appId,
|
|
84
|
+
additionalListAppIds,
|
|
59
85
|
initialThreadId,
|
|
60
86
|
includePullRequests,
|
|
61
87
|
snapshotCache,
|
|
@@ -90,20 +116,25 @@ function StatewireThreadListState({
|
|
|
90
116
|
[backendUrl, includePullRequests, getAuth]
|
|
91
117
|
);
|
|
92
118
|
const trimmedSearch = search.trim();
|
|
119
|
+
const additionalListAppIdsKey = JSON.stringify(additionalListAppIds ?? []);
|
|
120
|
+
const listedAppIds = react.useMemo(
|
|
121
|
+
() => JSON.parse(additionalListAppIdsKey),
|
|
122
|
+
[additionalListAppIdsKey]
|
|
123
|
+
);
|
|
93
124
|
const filter = react.useMemo(
|
|
94
125
|
() => ({
|
|
95
126
|
...appId ? { appId } : {},
|
|
127
|
+
...listedAppIds.length > 0 ? { appIds: listedAppIds } : {},
|
|
96
128
|
...trimmedSearch ? { search: trimmedSearch } : {}
|
|
97
129
|
}),
|
|
98
|
-
[appId, trimmedSearch]
|
|
130
|
+
[appId, listedAppIds, trimmedSearch]
|
|
99
131
|
);
|
|
132
|
+
const listScopeKey = `${backendUrl}::${principal}::${hasAuth ? "auth" : "anon"}::${includePullRequests ? "prs" : "no-prs"}`;
|
|
100
133
|
const list = useConversationList.useConversationList({
|
|
101
134
|
fetchPage,
|
|
102
135
|
filter,
|
|
103
136
|
pageSize: THREAD_LIST_PAGE_SIZE,
|
|
104
|
-
|
|
105
|
-
// the cache identity.
|
|
106
|
-
scopeKey: `${backendUrl}::${principal}::${hasAuth ? "auth" : "anon"}::${includePullRequests ? "prs" : "no-prs"}`,
|
|
137
|
+
scopeKey: listScopeKey,
|
|
107
138
|
enabled: hasAuth
|
|
108
139
|
});
|
|
109
140
|
const indexHeaders = react.useCallback(
|
|
@@ -150,21 +181,23 @@ function StatewireThreadListState({
|
|
|
150
181
|
return entries;
|
|
151
182
|
}, [index.entries]);
|
|
152
183
|
const mergedConversations = react.useMemo(
|
|
153
|
-
() => list.conversations
|
|
154
|
-
const entry = indexByThread.get(conversation.threadId);
|
|
155
|
-
if (!entry) return conversation;
|
|
156
|
-
const merged = conversationList.summaryFromConversationIndexEntry(entry, conversation);
|
|
157
|
-
return title.normalizeThreadTitle(merged.title) === void 0 ? { ...merged, title: conversation.title } : merged;
|
|
158
|
-
}),
|
|
184
|
+
() => foldConversationIndex(list.conversations, indexByThread),
|
|
159
185
|
[list.conversations, indexByThread]
|
|
160
186
|
);
|
|
161
|
-
const
|
|
187
|
+
const queryClient = reactQuery.useQueryClient();
|
|
188
|
+
const patchEveryList = react.useCallback(
|
|
189
|
+
(threadId, patch) => conversationList.patchConversationListCaches(queryClient, {
|
|
190
|
+
match: (item) => item.threadId === threadId,
|
|
191
|
+
patch
|
|
192
|
+
}),
|
|
193
|
+
[queryClient]
|
|
194
|
+
);
|
|
162
195
|
const favorite = useThreadFavorite.useThreadFavorite({
|
|
163
196
|
backendUrl,
|
|
164
197
|
principalId: principal,
|
|
165
198
|
getAuth,
|
|
166
199
|
rows: mergedConversations,
|
|
167
|
-
onServerTruth: ({ threadId, isFavorited }) =>
|
|
200
|
+
onServerTruth: ({ threadId, isFavorited }) => patchEveryList(threadId, { isFavorited })
|
|
168
201
|
});
|
|
169
202
|
const favoriteOverrides = favorite.overrides;
|
|
170
203
|
const rename = useThreadRename.useThreadRename({
|
|
@@ -172,16 +205,24 @@ function StatewireThreadListState({
|
|
|
172
205
|
principalId: principal,
|
|
173
206
|
getAuth,
|
|
174
207
|
rows: mergedConversations,
|
|
175
|
-
onServerTruth: ({ threadId, title: title2 }) =>
|
|
208
|
+
onServerTruth: ({ threadId, title: title2 }) => patchEveryList(threadId, { title: title2 })
|
|
176
209
|
});
|
|
177
210
|
const titleOverrides = rename.overrides;
|
|
178
|
-
const
|
|
211
|
+
const readState = useThreadReadState.useThreadReadState({
|
|
212
|
+
backendUrl,
|
|
213
|
+
principalId: principal,
|
|
214
|
+
getAuth,
|
|
215
|
+
rows: mergedConversations,
|
|
216
|
+
onServerTruth: ({ threadId, isUnread }) => patchEveryList(threadId, { isUnread })
|
|
217
|
+
});
|
|
218
|
+
const readOverrides = readState.overrides;
|
|
219
|
+
const readCoveredUpdatedAt = readState.coveredUpdatedAt;
|
|
179
220
|
const archive = useThreadArchive.useThreadArchive({
|
|
180
221
|
backendUrl,
|
|
181
222
|
principalId: principal,
|
|
182
223
|
getAuth,
|
|
183
224
|
onArchived: (threadId) => {
|
|
184
|
-
|
|
225
|
+
conversationList.removeConversationFromListCaches(queryClient, { threadId });
|
|
185
226
|
setActive(
|
|
186
227
|
(current) => current.id === threadId ? { id: mintThreadId.mintThreadId(), isNew: true } : current
|
|
187
228
|
);
|
|
@@ -196,12 +237,17 @@ function StatewireThreadListState({
|
|
|
196
237
|
);
|
|
197
238
|
if (forgotten.length > 0) archiveRelease(forgotten);
|
|
198
239
|
}, [hiddenThreadIds, mergedConversations, indexByThread, archiveRelease]);
|
|
240
|
+
const applyOverrides = react.useCallback(
|
|
241
|
+
(rows) => useThreadReadState.withReadStateOverrides(
|
|
242
|
+
useThreadRename.withTitleOverrides(useThreadFavorite.withFavoriteOverrides(rows, favoriteOverrides), titleOverrides),
|
|
243
|
+
readOverrides,
|
|
244
|
+
readCoveredUpdatedAt
|
|
245
|
+
).filter((conversation) => !hiddenThreadIds.has(conversation.threadId)),
|
|
246
|
+
[favoriteOverrides, titleOverrides, readOverrides, readCoveredUpdatedAt, hiddenThreadIds]
|
|
247
|
+
);
|
|
199
248
|
const data = react.useMemo(
|
|
200
|
-
() =>
|
|
201
|
-
|
|
202
|
-
titleOverrides
|
|
203
|
-
).filter((conversation) => !hiddenThreadIds.has(conversation.threadId)).map(threadSummaryFromConversation),
|
|
204
|
-
[mergedConversations, favoriteOverrides, titleOverrides, hiddenThreadIds]
|
|
249
|
+
() => applyOverrides(mergedConversations).map(threadSummaryFromConversation),
|
|
250
|
+
[applyOverrides, mergedConversations]
|
|
205
251
|
);
|
|
206
252
|
const isLoading = list.isLoading;
|
|
207
253
|
const lastActiveConversationRef = react.useRef(null);
|
|
@@ -217,12 +263,18 @@ function StatewireThreadListState({
|
|
|
217
263
|
if (activeConversation !== null) lastActiveConversationRef.current = activeConversation;
|
|
218
264
|
const activeThread = react.useMemo(
|
|
219
265
|
() => activeConversation ? threadSummaryFromConversation(
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
266
|
+
useThreadReadState.withReadStateOverrides(
|
|
267
|
+
[
|
|
268
|
+
useThreadRename.withTitleOverride(
|
|
269
|
+
useThreadFavorite.withFavoriteOverride(activeConversation, favoriteOverrides),
|
|
270
|
+
titleOverrides
|
|
271
|
+
)
|
|
272
|
+
],
|
|
273
|
+
readOverrides,
|
|
274
|
+
readCoveredUpdatedAt
|
|
275
|
+
)[0] ?? activeConversation
|
|
224
276
|
) : null,
|
|
225
|
-
[activeConversation, favoriteOverrides, titleOverrides]
|
|
277
|
+
[activeConversation, favoriteOverrides, titleOverrides, readOverrides, readCoveredUpdatedAt]
|
|
226
278
|
);
|
|
227
279
|
const listRefresh = list.refresh;
|
|
228
280
|
const refresh = react.useCallback(() => {
|
|
@@ -235,16 +287,16 @@ function StatewireThreadListState({
|
|
|
235
287
|
const refreshedForRef = react.useRef(/* @__PURE__ */ new Set());
|
|
236
288
|
react.useEffect(() => {
|
|
237
289
|
if (index.entries === null) return;
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
if (
|
|
247
|
-
}, [index.entries, list.conversations, appId, listRefresh]);
|
|
290
|
+
const unlisted = indexedThreadsToRefreshFor({
|
|
291
|
+
entries: index.entries,
|
|
292
|
+
listedThreadIds: new Set(list.conversations.map((conversation) => conversation.threadId)),
|
|
293
|
+
refreshedThreadIds: refreshedForRef.current,
|
|
294
|
+
appId,
|
|
295
|
+
additionalAppIds: listedAppIds
|
|
296
|
+
});
|
|
297
|
+
for (const threadId of unlisted) refreshedForRef.current.add(threadId);
|
|
298
|
+
if (unlisted.length > 0) void listRefresh();
|
|
299
|
+
}, [index.entries, list.conversations, appId, listedAppIds, listRefresh]);
|
|
248
300
|
const selectThread = react.useCallback((threadId) => {
|
|
249
301
|
if (!threadId) return;
|
|
250
302
|
setActive(
|
|
@@ -314,6 +366,8 @@ function StatewireThreadListState({
|
|
|
314
366
|
archivePendingThreadIds: archive.pendingThreadIds,
|
|
315
367
|
archivePending: archive.isPending,
|
|
316
368
|
archiveAvailable: archive.isAvailable,
|
|
369
|
+
setReadState: readState.setReadState,
|
|
370
|
+
readStatePendingThreadIds: readState.pendingThreadIds,
|
|
317
371
|
titleSource
|
|
318
372
|
}),
|
|
319
373
|
[
|
|
@@ -343,10 +397,44 @@ function StatewireThreadListState({
|
|
|
343
397
|
archive.pendingThreadIds,
|
|
344
398
|
archive.isPending,
|
|
345
399
|
archive.isAvailable,
|
|
400
|
+
readState.setReadState,
|
|
401
|
+
readState.pendingThreadIds,
|
|
346
402
|
titleSource
|
|
347
403
|
]
|
|
348
404
|
);
|
|
349
|
-
|
|
405
|
+
const live = react.useMemo(
|
|
406
|
+
() => ({
|
|
407
|
+
backendUrl,
|
|
408
|
+
getAuth,
|
|
409
|
+
principal,
|
|
410
|
+
hasAuth,
|
|
411
|
+
includePullRequests,
|
|
412
|
+
scopeKey: listScopeKey,
|
|
413
|
+
credentialGeneration,
|
|
414
|
+
baseFilter: {
|
|
415
|
+
...appId ? { appId } : {},
|
|
416
|
+
...listedAppIds.length > 0 ? { appIds: listedAppIds } : {}
|
|
417
|
+
},
|
|
418
|
+
indexByThread,
|
|
419
|
+
indexEntries: index.entries,
|
|
420
|
+
applyOverrides
|
|
421
|
+
}),
|
|
422
|
+
[
|
|
423
|
+
backendUrl,
|
|
424
|
+
getAuth,
|
|
425
|
+
principal,
|
|
426
|
+
hasAuth,
|
|
427
|
+
includePullRequests,
|
|
428
|
+
listScopeKey,
|
|
429
|
+
credentialGeneration,
|
|
430
|
+
appId,
|
|
431
|
+
listedAppIds,
|
|
432
|
+
indexByThread,
|
|
433
|
+
index.entries,
|
|
434
|
+
applyOverrides
|
|
435
|
+
]
|
|
436
|
+
);
|
|
437
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AthenaStatewireThreadListContext.Provider, { value, children: /* @__PURE__ */ jsxRuntime.jsx(AthenaSessionsLiveContext.Provider, { value: live, children }) });
|
|
350
438
|
}
|
|
351
439
|
function AthenaStatewireThreadListProvider({
|
|
352
440
|
backendUrl,
|
|
@@ -355,6 +443,7 @@ function AthenaStatewireThreadListProvider({
|
|
|
355
443
|
token,
|
|
356
444
|
getToken,
|
|
357
445
|
appId,
|
|
446
|
+
additionalListAppIds,
|
|
358
447
|
initialThreadId,
|
|
359
448
|
includePullRequests = true,
|
|
360
449
|
snapshotCache,
|
|
@@ -370,6 +459,7 @@ function AthenaStatewireThreadListProvider({
|
|
|
370
459
|
token,
|
|
371
460
|
getToken,
|
|
372
461
|
appId,
|
|
462
|
+
additionalListAppIds,
|
|
373
463
|
initialThreadId,
|
|
374
464
|
includePullRequests,
|
|
375
465
|
snapshotCache,
|
|
@@ -422,10 +512,13 @@ function StatewireThreadTitlePoller() {
|
|
|
422
512
|
}, [activeThreadId, hasMessages, hasTitle, titleSource]);
|
|
423
513
|
return null;
|
|
424
514
|
}
|
|
515
|
+
exports.AthenaSessionsLiveContext = AthenaSessionsLiveContext;
|
|
425
516
|
exports.AthenaStatewireThreadListContext = AthenaStatewireThreadListContext;
|
|
426
517
|
exports.AthenaStatewireThreadListProvider = AthenaStatewireThreadListProvider;
|
|
427
518
|
exports.StatewireThreadTitlePoller = StatewireThreadTitlePoller;
|
|
428
519
|
exports.TITLE_POLL_DELAY_MS = TITLE_POLL_DELAY_MS;
|
|
520
|
+
exports.foldConversationIndex = foldConversationIndex;
|
|
521
|
+
exports.indexedThreadsToRefreshFor = indexedThreadsToRefreshFor;
|
|
429
522
|
exports.threadSummaryFromConversation = threadSummaryFromConversation;
|
|
430
523
|
exports.useAthenaStatewireThreadList = useAthenaStatewireThreadList;
|
|
431
524
|
exports.useRefreshThreadList = useRefreshThreadList;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"statewire-thread-list.cjs","sources":["../../src/threads/statewire-thread-list.tsx"],"sourcesContent":["import {\n type ConversationAttention,\n type ConversationAttentionSource,\n type ConversationIndexEntry,\n type ConversationListFilter,\n type ConversationPullRequest,\n type ConversationSummary,\n type ConversationWake,\n conversationIndexUrlFromStatewireUrl,\n type DeepAgentHeadersResolver,\n type DeepAgentThreadSnapshotCache,\n deriveConversationAttention,\n summaryFromConversationIndexEntry,\n useConversationIndex,\n useConversationList,\n} from '@athenaintel/agent-runtime';\nimport { QueryClient, QueryClientProvider, useQuery } from '@tanstack/react-query';\nimport { useAuiState } from '@assistant-ui/react';\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\nimport { AthenaAuthContext } from '../auth/AthenaAuthContext';\nimport {\n type AthenaStatewireTokenGetter,\n resolveStatewireAuthHeaders,\n resolveStatewireAuthToken,\n} from '../runtime/statewire-auth-headers';\nimport { fetchAccountIdentity, getThreadState } from './api';\nimport { createRestConversationListFetcher } from './conversation-list-fetcher';\nimport { credentialShape, sameCredentialShape } from './credential-shape';\nimport { mintThreadId } from './mint-thread-id';\nimport { useAthenaStatewireThreadId } from './thread-id-context';\nimport { createThreadPrefetcher } from './thread-prefetcher';\nimport { isSerializedContentPartsTitle, normalizeThreadTitle } from './title';\nimport { useRestartAfterAuthRefusal } from '../runtime/auth-refusal-restart';\nimport { withCredentialRenewal } from '../runtime/credential-renewal';\nimport { useThreadArchive } from './use-thread-archive';\nimport {\n type ThreadFavoriteTarget,\n useThreadFavorite,\n withFavoriteOverride,\n withFavoriteOverrides,\n} from './use-thread-favorite';\nimport {\n type ThreadRenameTarget,\n useThreadRename,\n withTitleOverride,\n withTitleOverrides,\n} from './use-thread-rename';\n\n/**\n * One row of the thread list — the fields a Devin-style session list renders\n * (`SessionList`), all read from the shared conversation-list contract. The\n * attention fields are `null` on a server that does not derive them; the\n * pull-request state is `null` until the list has fetched it (or when the\n * provider opted out of it).\n */\nexport interface AthenaStatewireThreadSummary {\n id: string;\n title: string | null;\n /**\n * What the session asks of the viewer: the server-derived state when\n * reported, else the client fallback from the status planes\n * (`deriveConversationAttention`).\n */\n attention: ConversationAttention | null;\n /** One line (≤ 80 chars) of what the viewer should do next, when the server derives one. */\n nextAction: string | null;\n attentionSource: ConversationAttentionSource | null;\n /**\n * Whether the viewer pinned the session. Toggled through\n * `AthenaStatewireThreadListState.setFavorited`; a toggle in flight is\n * reflected here at once and held until the list sources report it.\n */\n isFavorited: boolean;\n isUnread: boolean;\n /** Canonical status_v2 planes, or `null` on an older server. */\n sessionStatus: string | null;\n runStatus: string | null;\n /** Channel the session was started from (e.g. `web`, `github`, `api`). */\n startChannel: string | null;\n /** Client app that created the session (SESSION_APP_ID_GUIDE). */\n appId: string | null;\n /** Trigger marker (`manual` remains user-initiated; other values are automated). */\n triggerType: string | null;\n /** Pull requests the session opened with their live GitHub state. */\n pullRequests: ConversationPullRequest[] | null;\n /** The last wake of a resting session. */\n lastWake: ConversationWake | null;\n /** ISO 8601 timestamp of the last update (the list's sort key). */\n updatedAt: string;\n}\n\n/**\n * Thread-list state. The list is the persisted Agora session list; the ACTIVE\n * thread is a plain id the statewire runtime attaches to — switching threads\n * remounts the statewire session against the new `…/v2/threads/{id}` URL\n * (the same model the mobile app uses).\n */\nexport interface AthenaStatewireThreadListState {\n /** The rows the current `search` lists, newest first. */\n threads: AthenaStatewireThreadSummary[];\n isLoading: boolean;\n /** True while the live first page (or a history page) is being fetched. */\n isFetching: boolean;\n /**\n * True once the live first page has answered at least once for the current\n * search and identity. Until then an empty `threads` means \"not known\n * yet\" (no credential resolved, first page in flight), not \"no sessions\":\n * `SessionList` shows skeleton rows, never the empty state.\n */\n hasResolvedFirstPage: boolean;\n activeThreadId: string;\n /**\n * The active thread's row, independent of what `threads` currently lists:\n * a search that hides the row, or a page that has not fetched it, must not\n * make the active chat's attention disappear. Resolved from the listed row,\n * else the pushed index entry folded over the last row seen, else that\n * last row; `null` for a never-started chat the backend does not know yet.\n */\n activeThread: AthenaStatewireThreadSummary | null;\n /** True while the active thread is a locally-minted chat with no server history. */\n isNewChat: boolean;\n selectThread: (threadId: string) => void;\n /**\n * Warm the provider's snapshot cache with a thread's REST state ahead of a\n * `selectThread`, so the switch paints the transcript on its first frame\n * instead of the loading scrim while the statewire attach lands.\n * `SessionList` calls it after a 120 ms hover dwell and on row focus.\n * Fetches once per thread per identity, deduplicates requests in flight,\n * runs at most two at a time and ignores failures; a no-op for the active\n * thread, a thread the cache already holds, or a provider without a cache.\n */\n prefetchThread: (threadId: string) => void;\n newThread: () => void;\n refresh: () => void;\n /**\n * Server-side title search (`search` on the REST thread list). An empty\n * string lists everything; the search covers the viewer's whole authorized\n * history, not just the live page.\n */\n search: string;\n setSearch: (search: string) => void;\n /** Whether another page of older sessions can be fetched. */\n hasNextPage: boolean;\n isFetchingNextPage: boolean;\n /** Fetch the next page of older sessions (frozen history pages, never replayed). */\n fetchNextPage: () => void;\n /**\n * Pin or unpin a session (`POST /api/conversations/threads/favorite`). The\n * row flips at once and moves between the `Pinned` and `Recent` groups; the\n * server's answer is written back, and a failure restores the previous\n * state. Writes for one thread are serialized: a toggle while that\n * thread's write is in flight records the value and sends at most one\n * follow-up write once the first has answered.\n */\n setFavorited: (target: ThreadFavoriteTarget) => void;\n /** True while any pin toggle is in flight. */\n favoritePending: boolean;\n /** The sessions whose pin toggle is in flight; `SessionList` disables their pin control. */\n favoritePendingThreadIds: ReadonlySet<string>;\n /**\n * Whether the backend offers the favorite route. `false` once it answered\n * 404 / 405 (an agora that predates the route): `SessionList` then shows\n * the read-only pin and no toggle, and `setFavorited` keeps failing.\n */\n favoriteToggleAvailable: boolean;\n /**\n * Rename a session for every viewer (`POST /api/conversations/threads/rename`).\n * The row shows the new title at once; the server's stored title is\n * written back, and a failure restores the previous one. Same-thread\n * writes are serialized like the pin's.\n */\n renameThread: (target: ThreadRenameTarget) => void;\n /** The sessions whose rename is in flight; `SessionList` keeps their editor closed. */\n renamePendingThreadIds: ReadonlySet<string>;\n /**\n * Whether the backend offers the rename route. `false` once it answered\n * 404 / 405 (an agora that predates the route): `SessionList` then offers\n * no Rename action, and `renameThread` keeps failing.\n */\n renameAvailable: boolean;\n /**\n * Archive a session (`POST /api/conversations/threads/archive`). The row\n * leaves the list at once and stays hidden until both list sources stop\n * reporting it; a failure brings it back. Archiving the active session\n * moves the chat to a new one once the server has confirmed.\n */\n archiveThread: (threadId: string) => void;\n /** The sessions whose archive is in flight. */\n archivePendingThreadIds: ReadonlySet<string>;\n /** True while any archive is in flight. */\n archivePending: boolean;\n /**\n * Whether the backend offers the archive route. `false` once it answered\n * 404 / 405: `SessionList` then offers no Archive action.\n */\n archiveAvailable: boolean;\n /**\n * Where titles come from. `'index'` once the signed-in user's live\n * conversation index has replicated — titles and newly created threads then\n * arrive as pushed updates; `'poll'` while it has not (no signed-in\n * principal, e.g. API-key mode, or before its snapshot), when a\n * freshly-started thread's title is picked up by the bounded REST poll.\n */\n titleSource: 'index' | 'poll';\n}\n\nexport const AthenaStatewireThreadListContext =\n createContext<AthenaStatewireThreadListState | null>(null);\n\n/** Read the statewire thread-list state, or null outside that mode. */\nexport function useAthenaStatewireThreadList(): AthenaStatewireThreadListState | null {\n return useContext(AthenaStatewireThreadListContext);\n}\n\n/** Trigger a re-fetch of the thread list. `null` outside `enableThreadList` mode. */\nexport function useRefreshThreadList(): (() => void) | null {\n return useAthenaStatewireThreadList()?.refresh ?? null;\n}\n\n/**\n * Project one contract row onto the thread-list row. Exported for hosts (and\n * tests) that build rows from a `ConversationSummary` of their own.\n */\nexport function threadSummaryFromConversation(\n conversation: ConversationSummary,\n): AthenaStatewireThreadSummary {\n return {\n id: conversation.threadId,\n title: normalizeThreadTitle(conversation.title) ?? null,\n attention: deriveConversationAttention(conversation),\n nextAction: conversation.nextAction ?? null,\n attentionSource: conversation.attentionSource ?? null,\n isFavorited: conversation.isFavorited ?? false,\n isUnread: conversation.isUnread,\n sessionStatus: conversation.sessionStatus,\n runStatus: conversation.runStatus,\n startChannel: conversation.sourceChannel,\n appId: conversation.appId,\n triggerType: conversation.triggerType,\n pullRequests: conversation.pullRequests ?? null,\n lastWake: conversation.lastWake ?? null,\n updatedAt: conversation.updatedAt,\n };\n}\n\n/**\n * The statewire thread list reads one live page through the shared\n * conversation-list contract; the REST default page size predates the shared\n * pager and is preserved here.\n */\nconst THREAD_LIST_PAGE_SIZE = 50;\n\nfunction StatewireThreadListState({\n backendUrl,\n syncUrl,\n apiKey,\n token,\n getToken,\n appId,\n initialThreadId,\n includePullRequests,\n snapshotCache,\n children,\n}: {\n backendUrl: string;\n syncUrl?: string;\n apiKey?: string;\n token?: string | null;\n getToken?: AthenaStatewireTokenGetter;\n appId?: string;\n initialThreadId?: string;\n includePullRequests: boolean;\n snapshotCache?: DeepAgentThreadSnapshotCache;\n children: ReactNode;\n}) {\n const [active, setActive] = useState<{ id: string; isNew: boolean }>(() =>\n initialThreadId\n ? { id: initialThreadId, isNew: false }\n : { id: mintThreadId(), isNew: true },\n );\n const [search, setSearch] = useState('');\n\n const tokenRef = useRef(token);\n tokenRef.current = token;\n const apiKeyRef = useRef(apiKey);\n apiKeyRef.current = apiKey;\n const getTokenRef = useRef(getToken);\n getTokenRef.current = getToken;\n\n // The cache must be keyed by WHO is asking. Keying on `backendUrl`/`appId`\n // alone let a token swap to a different user read the previous user's thread\n // titles out of the cache. The principal is a non-secret user id, so no\n // credential enters the key (or React Query's devtools). The shared pager\n // never serves placeholder rows across keys, so another principal's list is\n // never shown while the new one loads.\n const authContext = useContext(AthenaAuthContext);\n const principal = authContext?.user?.userId ?? '';\n // A live token getter is a credential too: a `getToken`-only host\n // authenticates its chat, so its list must not stay empty.\n const hasAuth = !!(apiKey || token || getToken);\n\n // Resolved per request with the attach's token semantics (getter first,\n // host-held token as the fallback) so a rotated token is never stale;\n // `force` renews a token the host just refused (`withCredentialRenewal`).\n const getAuth = useCallback(\n async (options?: { force?: boolean }) => ({\n apiKey: apiKeyRef.current,\n token: await resolveStatewireAuthToken(\n { apiKey: apiKeyRef.current, token: tokenRef.current, getToken: getTokenRef.current },\n { staleAuth: options?.force ?? false },\n ),\n }),\n [],\n );\n const fetchPage = useMemo(\n () => createRestConversationListFetcher({ backendUrl, includePullRequests, getAuth }),\n [backendUrl, includePullRequests, getAuth],\n );\n const trimmedSearch = search.trim();\n const filter = useMemo<ConversationListFilter>(\n () => ({\n ...(appId ? { appId } : {}),\n ...(trimmedSearch ? { search: trimmedSearch } : {}),\n }),\n [appId, trimmedSearch],\n );\n const list = useConversationList({\n fetchPage,\n filter,\n pageSize: THREAD_LIST_PAGE_SIZE,\n // Pull-request opt-in changes what a cached row holds, so it is part of\n // the cache identity.\n scopeKey: `${backendUrl}::${principal}::${hasAuth ? 'auth' : 'anon'}::${\n includePullRequests ? 'prs' : 'no-prs'\n }`,\n enabled: hasAuth,\n });\n\n // Live rows ride the signed-in user's conversation index — the same push\n // channel the conversation-history panel renders from: the host replicates\n // title, lifecycle, attention and creation changes as ops, so a\n // freshly-started thread's server-generated title (or a session flipping to\n // \"needs you\") lands without polling. The index is one instance per\n // `(workspace, user)` in agora's ids, so the pair is resolved from the\n // backend once a principal is known and the index only attaches once both\n // halves are; API-key-only hosts keep the bounded REST poll\n // (`titleSource: 'poll'`).\n const indexHeaders = useCallback<DeepAgentHeadersResolver>(\n (ctx) =>\n resolveStatewireAuthHeaders(\n { apiKey: apiKeyRef.current, token: tokenRef.current, getToken: getTokenRef.current },\n ctx,\n ),\n [],\n );\n // The workspace half is the CREDENTIAL's: a scoped credential (sandbox,\n // preview, Office session) pins its own workspace, so swapping one for\n // another under the same principal must re-resolve the pair. The query is\n // therefore keyed by a credential generation — a counter that advances\n // whenever the host's credentials change — so no secret enters the key.\n const credentialsRef = useRef(credentialShape({ apiKey, token, getToken }));\n const credentialGenerationRef = useRef(0);\n const currentCredentials = credentialShape({ apiKey, token, getToken });\n if (!sameCredentialShape(credentialsRef.current, currentCredentials)) {\n credentialsRef.current = currentCredentials;\n credentialGenerationRef.current += 1;\n }\n const credentialGeneration = credentialGenerationRef.current;\n const identityEnabled = syncUrl !== undefined && principal.length > 0 && hasAuth;\n const identity = useQuery({\n // Keyed by the non-secret principal and credential generation, never the\n // credential itself.\n queryKey: ['athena-sdk', 'account-identity', backendUrl, principal, credentialGeneration],\n queryFn: ({ signal }) =>\n withCredentialRenewal(getAuth, (auth) => fetchAccountIdentity(backendUrl, auth, { signal })),\n enabled: identityEnabled,\n staleTime: Number.POSITIVE_INFINITY,\n });\n const indexWorkspaceId = identity.data?.workspaceId ?? '';\n const indexUserId = identity.data?.userId ?? '';\n const indexEnabled = identityEnabled && indexWorkspaceId.length > 0 && indexUserId.length > 0;\n const index = useConversationIndex({\n baseUrl: syncUrl === undefined ? '' : conversationIndexUrlFromStatewireUrl(syncUrl),\n workspaceId: indexWorkspaceId || 'pending-workspace',\n userId: indexUserId || 'pending-user',\n headers: indexHeaders,\n enabled: indexEnabled,\n });\n // The index parks after repeated credential refusals; re-arm it as soon as\n // a new token exists so live rows resume without a reload.\n useRestartAfterAuthRefusal({\n connection: index.connection,\n reconnect: index.connection.reconnect,\n });\n const indexByThread = useMemo(() => {\n const entries = new Map<string, ConversationIndexEntry>();\n for (const entry of index.entries ?? []) entries.set(entry.thread_id, entry);\n return entries;\n }, [index.entries]);\n\n // Each fetched row folds its pushed index entry through the shared\n // `summaryFromConversationIndexEntry`, so titles, lifecycle and attention\n // update live while the fields the index never carries (pull requests,\n // the last wake) keep their fetched values. A pushed title that normalizes\n // to nothing falls back to the fetched one.\n const mergedConversations = useMemo(\n () =>\n list.conversations.map((conversation) => {\n const entry = indexByThread.get(conversation.threadId);\n if (!entry) return conversation;\n const merged = summaryFromConversationIndexEntry(entry, conversation);\n return normalizeThreadTitle(merged.title) === undefined\n ? { ...merged, title: conversation.title }\n : merged;\n }),\n [list.conversations, indexByThread],\n );\n // A pin toggle sits over the fold: the row flips at once, and a pushed\n // index entry that predates the write cannot clobber it. The override drops\n // once both sources report the toggled value.\n const listPatchConversation = list.patchConversation;\n const favorite = useThreadFavorite({\n backendUrl,\n principalId: principal,\n getAuth,\n rows: mergedConversations,\n onServerTruth: ({ threadId, isFavorited }) =>\n listPatchConversation(threadId, { isFavorited }),\n });\n const favoriteOverrides = favorite.overrides;\n // A rename sits over the fold the same way: the row shows the new title\n // at once, and a pushed index entry that predates the write cannot restore\n // the old one. The override drops once both sources report the new title.\n const rename = useThreadRename({\n backendUrl,\n principalId: principal,\n getAuth,\n rows: mergedConversations,\n onServerTruth: ({ threadId, title }) => listPatchConversation(threadId, { title }),\n });\n const titleOverrides = rename.overrides;\n\n // An archive hides the row at once and keeps it hidden until neither list\n // source reports it any more — the cached page is patched on the server's\n // answer, but the pushed index may still carry the row until the publish\n // that follows the commit lands. A failure drops the id and the row comes\n // back from the still-cached page: no refetch needed. Scoping, the\n // one-write-per-thread guard and the route-missing fallback live in the hook.\n const listRemoveConversation = list.removeConversation;\n const archive = useThreadArchive({\n backendUrl,\n principalId: principal,\n getAuth,\n onArchived: (threadId) => {\n listRemoveConversation(threadId);\n // The archived session cannot stay the active chat: the server no\n // longer lists it, so the chat moves to a fresh one.\n setActive((current) =>\n current.id === threadId ? { id: mintThreadId(), isNew: true } : current,\n );\n },\n });\n const hiddenThreadIds = archive.hiddenThreadIds;\n const archiveRelease = archive.release;\n // A hidden row is released once both sources have forgotten it, so a\n // session archived elsewhere and then restored is never masked here.\n useEffect(() => {\n if (hiddenThreadIds.size === 0) return;\n const forgotten = [...hiddenThreadIds].filter(\n (threadId) =>\n !mergedConversations.some((conversation) => conversation.threadId === threadId) &&\n !indexByThread.has(threadId),\n );\n if (forgotten.length > 0) archiveRelease(forgotten);\n }, [hiddenThreadIds, mergedConversations, indexByThread, archiveRelease]);\n\n const data = useMemo(\n () =>\n withTitleOverrides(\n withFavoriteOverrides(mergedConversations, favoriteOverrides),\n titleOverrides,\n )\n .filter((conversation) => !hiddenThreadIds.has(conversation.threadId))\n .map(threadSummaryFromConversation),\n [mergedConversations, favoriteOverrides, titleOverrides, hiddenThreadIds],\n );\n const isLoading = list.isLoading;\n\n // The active thread's row must survive a search that filters it out of\n // the page (the banner above the chat reads it): the listed row when there\n // is one, else the pushed index entry folded over the last row seen for\n // this thread (so pull requests survive the fold), else that last row.\n const lastActiveConversationRef = useRef<ConversationSummary | null>(null);\n const activeConversation = useMemo<ConversationSummary | null>(() => {\n const listed = mergedConversations.find((conversation) => conversation.threadId === active.id);\n if (listed) return listed;\n const remembered =\n lastActiveConversationRef.current?.threadId === active.id\n ? lastActiveConversationRef.current\n : undefined;\n const entry = indexByThread.get(active.id);\n if (entry) return summaryFromConversationIndexEntry(entry, remembered);\n return remembered ?? null;\n }, [mergedConversations, indexByThread, active.id]);\n if (activeConversation !== null) lastActiveConversationRef.current = activeConversation;\n const activeThread = useMemo(\n () =>\n activeConversation\n ? threadSummaryFromConversation(\n withTitleOverride(\n withFavoriteOverride(activeConversation, favoriteOverrides),\n titleOverrides,\n ),\n )\n : null,\n [activeConversation, favoriteOverrides, titleOverrides],\n );\n\n const listRefresh = list.refresh;\n const refresh = useCallback(() => {\n void listRefresh();\n }, [listRefresh]);\n const listFetchNextPage = list.fetchNextPage;\n const fetchNextPage = useCallback(() => {\n void listFetchNextPage();\n }, [listFetchNextPage]);\n\n // A thread the index knows — created here on first send, or elsewhere —\n // that the REST page does not list yet: refresh once per such id so the row\n // appears without the user pressing refresh. Rows for other app ids belong\n // to other lists and never trigger one.\n const refreshedForRef = useRef<Set<string>>(new Set());\n useEffect(() => {\n if (index.entries === null) return;\n const listed = new Set(list.conversations.map((conversation) => conversation.threadId));\n let pending = false;\n for (const entry of index.entries) {\n if (appId && entry.app_id !== appId) continue;\n if (listed.has(entry.thread_id) || refreshedForRef.current.has(entry.thread_id)) continue;\n refreshedForRef.current.add(entry.thread_id);\n pending = true;\n }\n if (pending) void listRefresh();\n }, [index.entries, list.conversations, appId, listRefresh]);\n\n const selectThread = useCallback((threadId: string) => {\n if (!threadId) return;\n setActive((current) =>\n current.id === threadId ? current : { id: threadId, isNew: false },\n );\n }, []);\n\n // The hover prefetcher is one per (backend, principal, credential\n // generation): a credential swap clears the provider's snapshot cache, so\n // the attempt ledger resets with it and a late answer from the previous\n // identity is never remembered under the new one.\n const prefetchScope = `${backendUrl}::${principal}::${credentialGeneration}`;\n const prefetchScopeRef = useRef(prefetchScope);\n prefetchScopeRef.current = prefetchScope;\n const prefetcher = useMemo(() => {\n if (!snapshotCache) return null;\n const scope = prefetchScope;\n return createThreadPrefetcher({\n cache: snapshotCache,\n fetchState: async (threadId) =>\n withCredentialRenewal(getAuth, (auth) =>\n getThreadState(backendUrl, auth, threadId, { skipCache: false }),\n ),\n isCurrent: () => prefetchScopeRef.current === scope,\n });\n }, [snapshotCache, prefetchScope, backendUrl, getAuth]);\n const activeIdRef = useRef(active.id);\n activeIdRef.current = active.id;\n const prefetchThread = useCallback(\n (threadId: string) => {\n if (!prefetcher || !threadId || threadId === activeIdRef.current) return;\n prefetcher.prefetch(threadId);\n },\n [prefetcher],\n );\n\n const newThread = useCallback(() => {\n setActive({ id: mintThreadId(), isNew: true });\n }, []);\n\n // A minted thread stops being \"new\" once the backend lists it — on the\n // fetched page or in the pushed index (a search may keep it off the page):\n // until then `useAthenaThreadManager` reports a null id, so URL sync cannot\n // name it.\n const isPersisted =\n data.some((thread) => thread.id === active.id) || indexByThread.has(active.id);\n useEffect(() => {\n if (isPersisted) {\n setActive((current) => (current.isNew ? { ...current, isNew: false } : current));\n }\n }, [isPersisted]);\n\n const titleSource: AthenaStatewireThreadListState['titleSource'] =\n index.entries !== null ? 'index' : 'poll';\n\n const value = useMemo<AthenaStatewireThreadListState>(\n () => ({\n threads: data,\n isLoading,\n isFetching: list.isFetching,\n hasResolvedFirstPage: list.hasResolvedFirstPage,\n activeThreadId: active.id,\n activeThread,\n isNewChat: active.isNew,\n selectThread,\n prefetchThread,\n newThread,\n refresh,\n search,\n setSearch,\n hasNextPage: list.hasNextPage,\n isFetchingNextPage: list.isFetchingNextPage,\n fetchNextPage,\n setFavorited: favorite.setFavorited,\n favoritePending: favorite.isPending,\n favoritePendingThreadIds: favorite.pendingThreadIds,\n favoriteToggleAvailable: favorite.isAvailable,\n renameThread: rename.rename,\n renamePendingThreadIds: rename.pendingThreadIds,\n renameAvailable: rename.isAvailable,\n archiveThread: archive.archive,\n archivePendingThreadIds: archive.pendingThreadIds,\n archivePending: archive.isPending,\n archiveAvailable: archive.isAvailable,\n titleSource,\n }),\n [\n data,\n isLoading,\n list.isFetching,\n list.hasResolvedFirstPage,\n active.id,\n activeThread,\n active.isNew,\n selectThread,\n prefetchThread,\n newThread,\n refresh,\n search,\n list.hasNextPage,\n list.isFetchingNextPage,\n fetchNextPage,\n favorite.setFavorited,\n favorite.isPending,\n favorite.pendingThreadIds,\n favorite.isAvailable,\n rename.rename,\n rename.pendingThreadIds,\n rename.isAvailable,\n archive.archive,\n archive.pendingThreadIds,\n archive.isPending,\n archive.isAvailable,\n titleSource,\n ],\n );\n\n return (\n <AthenaStatewireThreadListContext.Provider value={value}>\n {children}\n </AthenaStatewireThreadListContext.Provider>\n );\n}\n\n/**\n * Provides the statewire thread-list state, with an SDK-scoped QueryClient so\n * consumers do not need their own QueryClientProvider. `syncUrl` (the\n * `…/v2/threads` mount) locates the conversation index beside it; without it\n * titles fall back to the REST poll. `includePullRequests` (default `true`)\n * asks the list for live pull-request state so `SessionList` can render its\n * chips; a host that never shows them turns it off to spare the server the\n * lookup. `snapshotCache` is the provider's thread snapshot cache — the one\n * the runtime seeds a switched-to thread from — which `prefetchThread` warms;\n * without it prefetching is a no-op.\n */\nexport function AthenaStatewireThreadListProvider({\n backendUrl,\n syncUrl,\n apiKey,\n token,\n getToken,\n appId,\n initialThreadId,\n includePullRequests = true,\n snapshotCache,\n children,\n}: {\n backendUrl: string;\n syncUrl?: string;\n apiKey?: string;\n token?: string | null;\n getToken?: AthenaStatewireTokenGetter;\n appId?: string;\n initialThreadId?: string;\n includePullRequests?: boolean;\n snapshotCache?: DeepAgentThreadSnapshotCache;\n children: ReactNode;\n}) {\n const [queryClient] = useState(() => new QueryClient());\n return (\n <QueryClientProvider client={queryClient}>\n <StatewireThreadListState\n backendUrl={backendUrl}\n syncUrl={syncUrl}\n apiKey={apiKey}\n token={token}\n getToken={getToken}\n appId={appId}\n initialThreadId={initialThreadId}\n includePullRequests={includePullRequests}\n snapshotCache={snapshotCache}\n >\n {children}\n </StatewireThreadListState>\n </QueryClientProvider>\n );\n}\n\n/** How long after a thread's first message the title poll starts (exported for tests). */\nexport const TITLE_POLL_DELAY_MS = 5000;\nconst TITLE_POLL_INTERVAL_MS = 2000;\nconst TITLE_POLL_MAX_DURATION_MS = 60_000;\n\n/**\n * Fallback for hosts without a live conversation index (`titleSource: 'poll'`,\n * i.e. no signed-in principal): refreshes the thread list until a\n * freshly-started thread's server-generated title appears. Idle while the\n * index carries titles. Mount inside the statewire runtime scope (needs aui\n * state).\n *\n * The thread is read from the statewire scope, not the list: the scope\n * publishes the id together with the client it belongs to, so the messages\n * observed here are always the named thread's (the list's selection moves\n * one commit ahead of the client during a switch).\n */\nexport function StatewireThreadTitlePoller(): null {\n const list = useAthenaStatewireThreadList();\n const activeThreadId = useAthenaStatewireThreadId();\n const hasMessages = useAuiState((s) => (s.optional.thread?.messages.length ?? 0) > 0);\n\n const titleSource = list?.titleSource ?? 'poll';\n const entry = list?.threads.find((thread) => thread.id === activeThreadId);\n const title = entry?.title?.trim() ?? '';\n const hasTitle = title.length > 0 && !isSerializedContentPartsTitle(title);\n\n // The poller stays mounted across thread switches, so the visit is tracked\n // by hand: one poll per visit — no restart when the visited thread's\n // messages or title flip underneath it — and a re-selected thread polls\n // again, as it did when every switch remounted the poller. The record is\n // replaced whenever the attached thread changes, whether or not a poll\n // started for it, so a visit to a thread that needs no poll can never make\n // the next visit to a previous thread look already polled.\n const visitRef = useRef<{ threadId: string; polled: boolean } | null>(null);\n const refreshRef = useRef(list?.refresh);\n refreshRef.current = list?.refresh;\n\n useEffect(() => {\n if (visitRef.current?.threadId !== activeThreadId) {\n visitRef.current = { threadId: activeThreadId, polled: false };\n }\n const visit = visitRef.current;\n if (!hasMessages || hasTitle || titleSource === 'index') return;\n if (visit.polled) return;\n visit.polled = true;\n\n let intervalId: ReturnType<typeof setInterval> | null = null;\n const startId = setTimeout(() => {\n intervalId = setInterval(() => refreshRef.current?.(), TITLE_POLL_INTERVAL_MS);\n }, TITLE_POLL_DELAY_MS);\n const stopId = setTimeout(() => {\n if (intervalId !== null) clearInterval(intervalId);\n }, TITLE_POLL_MAX_DURATION_MS);\n\n return () => {\n clearTimeout(startId);\n clearTimeout(stopId);\n if (intervalId !== null) clearInterval(intervalId);\n };\n }, [activeThreadId, hasMessages, hasTitle, titleSource]);\n\n return null;\n}\n"],"names":["createContext","useContext","normalizeThreadTitle","deriveConversationAttention","useState","mintThreadId","useRef","AthenaAuthContext","useCallback","resolveStatewireAuthToken","useMemo","createRestConversationListFetcher","useConversationList","resolveStatewireAuthHeaders","credentialShape","sameCredentialShape","useQuery","withCredentialRenewal","fetchAccountIdentity","useConversationIndex","conversationIndexUrlFromStatewireUrl","useRestartAfterAuthRefusal","summaryFromConversationIndexEntry","useThreadFavorite","useThreadRename","title","useThreadArchive","useEffect","withTitleOverrides","withFavoriteOverrides","_a","withTitleOverride","withFavoriteOverride","createThreadPrefetcher","getThreadState","jsx","QueryClient","QueryClientProvider","useAthenaStatewireThreadId","useAuiState","isSerializedContentPartsTitle"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"statewire-thread-list.cjs","sources":["../../src/threads/statewire-thread-list.tsx"],"sourcesContent":["import {\n type ConversationAttention,\n type ConversationAttentionSource,\n type ConversationIndexEntry,\n type ConversationListFilter,\n type ConversationPullRequest,\n type ConversationSummary,\n type ConversationWake,\n conversationIndexUrlFromStatewireUrl,\n type DeepAgentHeadersResolver,\n type DeepAgentThreadSnapshotCache,\n deriveConversationAttention,\n patchConversationListCaches,\n removeConversationFromListCaches,\n summaryFromConversationIndexEntry,\n useConversationIndex,\n useConversationList,\n} from '@athenaintel/agent-runtime';\nimport { QueryClient, QueryClientProvider, useQuery, useQueryClient } from '@tanstack/react-query';\nimport { useAuiState } from '@assistant-ui/react';\nimport {\n createContext,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useRef,\n useState,\n type ReactNode,\n} from 'react';\nimport { AthenaAuthContext } from '../auth/AthenaAuthContext';\nimport {\n type AthenaStatewireTokenGetter,\n resolveStatewireAuthHeaders,\n resolveStatewireAuthToken,\n} from '../runtime/statewire-auth-headers';\nimport { fetchAccountIdentity, getThreadState } from './api';\nimport { createRestConversationListFetcher } from './conversation-list-fetcher';\nimport { credentialShape, sameCredentialShape } from './credential-shape';\nimport { mintThreadId } from './mint-thread-id';\nimport { useAthenaStatewireThreadId } from './thread-id-context';\nimport { createThreadPrefetcher } from './thread-prefetcher';\nimport { isSerializedContentPartsTitle, normalizeThreadTitle } from './title';\nimport { useRestartAfterAuthRefusal } from '../runtime/auth-refusal-restart';\nimport { type CredentialResolver, withCredentialRenewal } from '../runtime/credential-renewal';\nimport { useThreadArchive } from './use-thread-archive';\nimport {\n type ThreadFavoriteTarget,\n useThreadFavorite,\n withFavoriteOverride,\n withFavoriteOverrides,\n} from './use-thread-favorite';\nimport {\n type ThreadReadStateTarget,\n useThreadReadState,\n withReadStateOverrides,\n} from './use-thread-read-state';\nimport {\n type ThreadRenameTarget,\n useThreadRename,\n withTitleOverride,\n withTitleOverrides,\n} from './use-thread-rename';\n\n/**\n * One row of the thread list — the fields a Devin-style session list renders\n * (`SessionList`), all read from the shared conversation-list contract. The\n * attention fields are `null` on a server that does not derive them; the\n * pull-request state is `null` until the list has fetched it (or when the\n * provider opted out of it).\n */\nexport interface AthenaStatewireThreadSummary {\n id: string;\n title: string | null;\n /**\n * What the session asks of the viewer: the server-derived state when\n * reported, else the client fallback from the status planes\n * (`deriveConversationAttention`).\n */\n attention: ConversationAttention | null;\n /** One line (≤ 80 chars) of what the viewer should do next, when the server derives one. */\n nextAction: string | null;\n attentionSource: ConversationAttentionSource | null;\n /**\n * Whether the viewer pinned the session. Toggled through\n * `AthenaStatewireThreadListState.setFavorited`; a toggle in flight is\n * reflected here at once and held until the list sources report it.\n */\n isFavorited: boolean;\n isUnread: boolean;\n /** Canonical status_v2 planes, or `null` on an older server. */\n sessionStatus: string | null;\n runStatus: string | null;\n /** Channel the session was started from (e.g. `web`, `github`, `api`). */\n startChannel: string | null;\n /** Client app that created the session (SESSION_APP_ID_GUIDE). */\n appId: string | null;\n /** Trigger marker (`manual` remains user-initiated; other values are automated). */\n triggerType: string | null;\n /** Pull requests the session opened with their live GitHub state. */\n pullRequests: ConversationPullRequest[] | null;\n /** The last wake of a resting session. */\n lastWake: ConversationWake | null;\n /** ISO 8601 timestamp of the last update (the list's sort key). */\n updatedAt: string;\n /** ISO 8601 creation time; `null` when the list did not report it. */\n createdAt?: string | null;\n /** The session's last message, for a preview line (the inbox excerpt). */\n preview?: string | null;\n /** The collab agent the session started as, and its channel (`null`: the default channel). */\n collabAgentId?: string | null;\n collabChannelId?: string | null;\n /** Whether the viewer started the session (`false`: shared with them); `null` when not reported. */\n createdByMe?: boolean | null;\n}\n\n/**\n * Thread-list state. The list is the persisted Agora session list; the ACTIVE\n * thread is a plain id the statewire runtime attaches to — switching threads\n * remounts the statewire session against the new `…/v2/threads/{id}` URL\n * (the same model the mobile app uses).\n */\nexport interface AthenaStatewireThreadListState {\n /** The rows the current `search` lists, newest first. */\n threads: AthenaStatewireThreadSummary[];\n isLoading: boolean;\n /** True while the live first page (or a history page) is being fetched. */\n isFetching: boolean;\n /**\n * True once the live first page has answered at least once for the current\n * search and identity. Until then an empty `threads` means \"not known\n * yet\" (no credential resolved, first page in flight), not \"no sessions\":\n * `SessionList` shows skeleton rows, never the empty state.\n */\n hasResolvedFirstPage: boolean;\n activeThreadId: string;\n /**\n * The active thread's row, independent of what `threads` currently lists:\n * a search that hides the row, or a page that has not fetched it, must not\n * make the active chat's attention disappear. Resolved from the listed row,\n * else the pushed index entry folded over the last row seen, else that\n * last row; `null` for a never-started chat the backend does not know yet.\n */\n activeThread: AthenaStatewireThreadSummary | null;\n /** True while the active thread is a locally-minted chat with no server history. */\n isNewChat: boolean;\n selectThread: (threadId: string) => void;\n /**\n * Warm the provider's snapshot cache with a thread's REST state ahead of a\n * `selectThread`, so the switch paints the transcript on its first frame\n * instead of the loading scrim while the statewire attach lands.\n * `SessionList` calls it after a 120 ms hover dwell and on row focus.\n * Fetches once per thread per identity, deduplicates requests in flight,\n * runs at most two at a time and ignores failures; a no-op for the active\n * thread, a thread the cache already holds, or a provider without a cache.\n */\n prefetchThread: (threadId: string) => void;\n newThread: () => void;\n refresh: () => void;\n /**\n * Server-side title search (`search` on the REST thread list). An empty\n * string lists everything; the search covers the viewer's whole authorized\n * history, not just the live page.\n */\n search: string;\n setSearch: (search: string) => void;\n /** Whether another page of older sessions can be fetched. */\n hasNextPage: boolean;\n isFetchingNextPage: boolean;\n /** Fetch the next page of older sessions (frozen history pages, never replayed). */\n fetchNextPage: () => void;\n /**\n * Pin or unpin a session (`POST /api/conversations/threads/favorite`). The\n * row flips at once and moves between the `Pinned` and `Recent` groups; the\n * server's answer is written back, and a failure restores the previous\n * state. Writes for one thread are serialized: a toggle while that\n * thread's write is in flight records the value and sends at most one\n * follow-up write once the first has answered.\n */\n setFavorited: (target: ThreadFavoriteTarget) => void;\n /** True while any pin toggle is in flight. */\n favoritePending: boolean;\n /** The sessions whose pin toggle is in flight; `SessionList` disables their pin control. */\n favoritePendingThreadIds: ReadonlySet<string>;\n /**\n * Whether the backend offers the favorite route. `false` once it answered\n * 404 / 405 (an agora that predates the route): `SessionList` then shows\n * the read-only pin and no toggle, and `setFavorited` keeps failing.\n */\n favoriteToggleAvailable: boolean;\n /**\n * Rename a session for every viewer (`POST /api/conversations/threads/rename`).\n * The row shows the new title at once; the server's stored title is\n * written back, and a failure restores the previous one. Same-thread\n * writes are serialized like the pin's.\n */\n renameThread: (target: ThreadRenameTarget) => void;\n /** The sessions whose rename is in flight; `SessionList` keeps their editor closed. */\n renamePendingThreadIds: ReadonlySet<string>;\n /**\n * Whether the backend offers the rename route. `false` once it answered\n * 404 / 405 (an agora that predates the route): `SessionList` then offers\n * no Rename action, and `renameThread` keeps failing.\n */\n renameAvailable: boolean;\n /**\n * Archive a session (`POST /api/conversations/threads/archive`). The row\n * leaves the list at once and stays hidden until both list sources stop\n * reporting it; a failure brings it back. Archiving the active session\n * moves the chat to a new one once the server has confirmed.\n */\n archiveThread: (threadId: string) => void;\n /** The sessions whose archive is in flight. */\n archivePendingThreadIds: ReadonlySet<string>;\n /** True while any archive is in flight. */\n archivePending: boolean;\n /**\n * Whether the backend offers the archive route. `false` once it answered\n * 404 / 405: `SessionList` then offers no Archive action.\n */\n archiveAvailable: boolean;\n /**\n * Mark a session read or unread for the viewer\n * (`POST /api/conversations/threads/read-state`). The row flips at once in\n * every list under the provider (`SessionList`, `SessionsPage`, `Inbox`);\n * the server's answer is written back, and a failure restores the previous\n * state. Same-thread writes are serialized like the pin's.\n */\n setReadState: (target: ThreadReadStateTarget) => void;\n /** The sessions whose read-state write is in flight. */\n readStatePendingThreadIds: ReadonlySet<string>;\n /**\n * Where titles come from. `'index'` once the signed-in user's live\n * conversation index has replicated — titles and newly created threads then\n * arrive as pushed updates; `'poll'` while it has not (no signed-in\n * principal, e.g. API-key mode, or before its snapshot), when a\n * freshly-started thread's title is picked up by the bounded REST poll.\n */\n titleSource: 'index' | 'poll';\n}\n\nexport const AthenaStatewireThreadListContext =\n createContext<AthenaStatewireThreadListState | null>(null);\n\n/** Read the statewire thread-list state, or null outside that mode. */\nexport function useAthenaStatewireThreadList(): AthenaStatewireThreadListState | null {\n return useContext(AthenaStatewireThreadListContext);\n}\n\n/** Trigger a re-fetch of the thread list. `null` outside `enableThreadList` mode. */\nexport function useRefreshThreadList(): (() => void) | null {\n return useAthenaStatewireThreadList()?.refresh ?? null;\n}\n\n/**\n * Project one contract row onto the thread-list row. Exported for hosts (and\n * tests) that build rows from a `ConversationSummary` of their own.\n */\n/**\n * The threads the conversation index knows that the fetched list does not show yet, and that have\n * not prompted a refresh before: each warrants one refresh of the list. Only threads of the apps\n * the list shows count (its `appId` and `additionalAppIds`); with neither, every app's do.\n * Exported for tests.\n */\nexport function indexedThreadsToRefreshFor({\n entries,\n listedThreadIds,\n refreshedThreadIds,\n appId,\n additionalAppIds,\n}: {\n entries: ReadonlyArray<{ thread_id: string; app_id: string | null }>;\n listedThreadIds: ReadonlySet<string>;\n refreshedThreadIds: ReadonlySet<string>;\n appId: string | undefined;\n additionalAppIds: readonly string[];\n}): string[] {\n const shownAppIds =\n appId || additionalAppIds.length > 0\n ? new Set([...(appId ? [appId] : []), ...additionalAppIds])\n : null;\n return entries\n .filter((entry) => !shownAppIds || shownAppIds.has(entry.app_id ?? ''))\n .map((entry) => entry.thread_id)\n .filter((threadId) => !listedThreadIds.has(threadId) && !refreshedThreadIds.has(threadId));\n}\n\nexport function threadSummaryFromConversation(\n conversation: ConversationSummary,\n): AthenaStatewireThreadSummary {\n return {\n id: conversation.threadId,\n title: normalizeThreadTitle(conversation.title) ?? null,\n attention: deriveConversationAttention(conversation),\n nextAction: conversation.nextAction ?? null,\n attentionSource: conversation.attentionSource ?? null,\n isFavorited: conversation.isFavorited ?? false,\n isUnread: conversation.isUnread,\n sessionStatus: conversation.sessionStatus,\n runStatus: conversation.runStatus,\n startChannel: conversation.sourceChannel,\n appId: conversation.appId,\n triggerType: conversation.triggerType,\n pullRequests: conversation.pullRequests ?? null,\n lastWake: conversation.lastWake ?? null,\n updatedAt: conversation.updatedAt,\n createdAt: conversation.createdAt,\n preview: conversation.preview,\n collabAgentId: conversation.collabAgentId ?? null,\n collabChannelId: conversation.collabChannelId ?? null,\n createdByMe: conversation.createdByMe ?? null,\n };\n}\n\n/**\n * Fold the pushed conversation index into fetched rows: each row with an\n * index entry takes its pushed fields through the shared\n * `summaryFromConversationIndexEntry` (titles, lifecycle, attention), while\n * what the index never carries (pull requests, the last wake, who started\n * it) keeps the fetched value. A pushed title that normalizes to nothing\n * falls back to the fetched one. Exported for tests.\n */\nexport function foldConversationIndex(\n conversations: readonly ConversationSummary[],\n indexByThread: ReadonlyMap<string, ConversationIndexEntry>,\n): ConversationSummary[] {\n return conversations.map((conversation) => {\n const entry = indexByThread.get(conversation.threadId);\n if (!entry) return conversation;\n const merged = summaryFromConversationIndexEntry(entry, conversation);\n return normalizeThreadTitle(merged.title) === undefined\n ? { ...merged, title: conversation.title }\n : merged;\n });\n}\n\n/**\n * What the thread-list provider shares with the other lists mounted under it\n * (`SessionsPage`, `Inbox`): the credential, the live conversation index and\n * the optimistic overrides (pin, title, read state, archived rows), so every\n * list folds the same pushes and shows the same in-flight writes. Internal —\n * hosts use `useAthenaSessions`.\n */\nexport interface AthenaSessionsLiveState {\n backendUrl: string;\n getAuth: CredentialResolver<{ apiKey?: string; token?: string | null }>;\n principal: string;\n hasAuth: boolean;\n includePullRequests: boolean;\n /** The provider list's cache scope (backend, principal, auth, PR opt-in). */\n scopeKey: string;\n /**\n * Advances whenever the host's credential changes (a swapped API key or\n * token, a scoped credential for another workspace under the same\n * principal), so caches keyed on it are never read with another credential.\n */\n credentialGeneration: number;\n /** The app scope the provider lists (`appId` / `additionalListAppIds`). */\n baseFilter: ConversationListFilter;\n indexByThread: ReadonlyMap<string, ConversationIndexEntry>;\n /** `null` until the index has replicated (or without one). */\n indexEntries: readonly ConversationIndexEntry[] | null;\n /** Layer the in-flight writes over rows and drop archived ones. */\n applyOverrides: (rows: readonly ConversationSummary[]) => ConversationSummary[];\n}\n\nexport const AthenaSessionsLiveContext = createContext<AthenaSessionsLiveState | null>(null);\n\n/**\n * The statewire thread list reads one live page through the shared\n * conversation-list contract; the REST default page size predates the shared\n * pager and is preserved here.\n */\nconst THREAD_LIST_PAGE_SIZE = 50;\n\nfunction StatewireThreadListState({\n backendUrl,\n syncUrl,\n apiKey,\n token,\n getToken,\n appId,\n additionalListAppIds,\n initialThreadId,\n includePullRequests,\n snapshotCache,\n children,\n}: {\n backendUrl: string;\n syncUrl?: string;\n apiKey?: string;\n token?: string | null;\n getToken?: AthenaStatewireTokenGetter;\n appId?: string;\n additionalListAppIds?: readonly string[];\n initialThreadId?: string;\n includePullRequests: boolean;\n snapshotCache?: DeepAgentThreadSnapshotCache;\n children: ReactNode;\n}) {\n const [active, setActive] = useState<{ id: string; isNew: boolean }>(() =>\n initialThreadId\n ? { id: initialThreadId, isNew: false }\n : { id: mintThreadId(), isNew: true },\n );\n const [search, setSearch] = useState('');\n\n const tokenRef = useRef(token);\n tokenRef.current = token;\n const apiKeyRef = useRef(apiKey);\n apiKeyRef.current = apiKey;\n const getTokenRef = useRef(getToken);\n getTokenRef.current = getToken;\n\n // The cache must be keyed by WHO is asking. Keying on `backendUrl`/`appId`\n // alone let a token swap to a different user read the previous user's thread\n // titles out of the cache. The principal is a non-secret user id, so no\n // credential enters the key (or React Query's devtools). The shared pager\n // never serves placeholder rows across keys, so another principal's list is\n // never shown while the new one loads.\n const authContext = useContext(AthenaAuthContext);\n const principal = authContext?.user?.userId ?? '';\n // A live token getter is a credential too: a `getToken`-only host\n // authenticates its chat, so its list must not stay empty.\n const hasAuth = !!(apiKey || token || getToken);\n\n // Resolved per request with the attach's token semantics (getter first,\n // host-held token as the fallback) so a rotated token is never stale;\n // `force` renews a token the host just refused (`withCredentialRenewal`).\n const getAuth = useCallback(\n async (options?: { force?: boolean }) => ({\n apiKey: apiKeyRef.current,\n token: await resolveStatewireAuthToken(\n { apiKey: apiKeyRef.current, token: tokenRef.current, getToken: getTokenRef.current },\n { staleAuth: options?.force ?? false },\n ),\n }),\n [],\n );\n const fetchPage = useMemo(\n () => createRestConversationListFetcher({ backendUrl, includePullRequests, getAuth }),\n [backendUrl, includePullRequests, getAuth],\n );\n const trimmedSearch = search.trim();\n // A stable key, so a host passing a fresh array each render does not refetch; JSON keeps each\n // id exact (no separator an id could contain).\n const additionalListAppIdsKey = JSON.stringify(additionalListAppIds ?? []);\n const listedAppIds = useMemo<readonly string[]>(\n () => JSON.parse(additionalListAppIdsKey) as string[],\n [additionalListAppIdsKey],\n );\n const filter = useMemo<ConversationListFilter>(\n () => ({\n ...(appId ? { appId } : {}),\n ...(listedAppIds.length > 0 ? { appIds: listedAppIds } : {}),\n ...(trimmedSearch ? { search: trimmedSearch } : {}),\n }),\n [appId, listedAppIds, trimmedSearch],\n );\n // Pull-request opt-in changes what a cached row holds, so it is part of\n // the cache identity.\n const listScopeKey = `${backendUrl}::${principal}::${hasAuth ? 'auth' : 'anon'}::${\n includePullRequests ? 'prs' : 'no-prs'\n }`;\n const list = useConversationList({\n fetchPage,\n filter,\n pageSize: THREAD_LIST_PAGE_SIZE,\n scopeKey: listScopeKey,\n enabled: hasAuth,\n });\n\n // Live rows ride the signed-in user's conversation index — the same push\n // channel the conversation-history panel renders from: the host replicates\n // title, lifecycle, attention and creation changes as ops, so a\n // freshly-started thread's server-generated title (or a session flipping to\n // \"needs you\") lands without polling. The index is one instance per\n // `(workspace, user)` in agora's ids, so the pair is resolved from the\n // backend once a principal is known and the index only attaches once both\n // halves are; API-key-only hosts keep the bounded REST poll\n // (`titleSource: 'poll'`).\n const indexHeaders = useCallback<DeepAgentHeadersResolver>(\n (ctx) =>\n resolveStatewireAuthHeaders(\n { apiKey: apiKeyRef.current, token: tokenRef.current, getToken: getTokenRef.current },\n ctx,\n ),\n [],\n );\n // The workspace half is the CREDENTIAL's: a scoped credential (sandbox,\n // preview, Office session) pins its own workspace, so swapping one for\n // another under the same principal must re-resolve the pair. The query is\n // therefore keyed by a credential generation — a counter that advances\n // whenever the host's credentials change — so no secret enters the key.\n const credentialsRef = useRef(credentialShape({ apiKey, token, getToken }));\n const credentialGenerationRef = useRef(0);\n const currentCredentials = credentialShape({ apiKey, token, getToken });\n if (!sameCredentialShape(credentialsRef.current, currentCredentials)) {\n credentialsRef.current = currentCredentials;\n credentialGenerationRef.current += 1;\n }\n const credentialGeneration = credentialGenerationRef.current;\n const identityEnabled = syncUrl !== undefined && principal.length > 0 && hasAuth;\n const identity = useQuery({\n // Keyed by the non-secret principal and credential generation, never the\n // credential itself.\n queryKey: ['athena-sdk', 'account-identity', backendUrl, principal, credentialGeneration],\n queryFn: ({ signal }) =>\n withCredentialRenewal(getAuth, (auth) => fetchAccountIdentity(backendUrl, auth, { signal })),\n enabled: identityEnabled,\n staleTime: Number.POSITIVE_INFINITY,\n });\n const indexWorkspaceId = identity.data?.workspaceId ?? '';\n const indexUserId = identity.data?.userId ?? '';\n const indexEnabled = identityEnabled && indexWorkspaceId.length > 0 && indexUserId.length > 0;\n const index = useConversationIndex({\n baseUrl: syncUrl === undefined ? '' : conversationIndexUrlFromStatewireUrl(syncUrl),\n workspaceId: indexWorkspaceId || 'pending-workspace',\n userId: indexUserId || 'pending-user',\n headers: indexHeaders,\n enabled: indexEnabled,\n });\n // The index parks after repeated credential refusals; re-arm it as soon as\n // a new token exists so live rows resume without a reload.\n useRestartAfterAuthRefusal({\n connection: index.connection,\n reconnect: index.connection.reconnect,\n });\n const indexByThread = useMemo(() => {\n const entries = new Map<string, ConversationIndexEntry>();\n for (const entry of index.entries ?? []) entries.set(entry.thread_id, entry);\n return entries;\n }, [index.entries]);\n\n // Each fetched row folds its pushed index entry through the shared\n // `summaryFromConversationIndexEntry`, so titles, lifecycle and attention\n // update live while the fields the index never carries (pull requests,\n // the last wake) keep their fetched values. A pushed title that normalizes\n // to nothing falls back to the fetched one.\n const mergedConversations = useMemo(\n () => foldConversationIndex(list.conversations, indexByThread),\n [list.conversations, indexByThread],\n );\n // The server's answer to a write is patched into EVERY conversation list\n // cached under this provider (its own page, and any `SessionsPage` /\n // `Inbox` view) — the client is the provider's own, so nothing outside it\n // is touched.\n const queryClient = useQueryClient();\n const patchEveryList = useCallback(\n (threadId: string, patch: Partial<ConversationSummary>) =>\n patchConversationListCaches(queryClient, {\n match: (item) => item.threadId === threadId,\n patch,\n }),\n [queryClient],\n );\n // A pin toggle sits over the fold: the row flips at once, and a pushed\n // index entry that predates the write cannot clobber it. The override drops\n // once both sources report the toggled value.\n const favorite = useThreadFavorite({\n backendUrl,\n principalId: principal,\n getAuth,\n rows: mergedConversations,\n onServerTruth: ({ threadId, isFavorited }) => patchEveryList(threadId, { isFavorited }),\n });\n const favoriteOverrides = favorite.overrides;\n // A rename sits over the fold the same way: the row shows the new title\n // at once, and a pushed index entry that predates the write cannot restore\n // the old one. The override drops once both sources report the new title.\n const rename = useThreadRename({\n backendUrl,\n principalId: principal,\n getAuth,\n rows: mergedConversations,\n onServerTruth: ({ threadId, title }) => patchEveryList(threadId, { title }),\n });\n const titleOverrides = rename.overrides;\n // Read state likewise; the read-state route publishes no index update, so\n // the override is what keeps a stale pushed `is_unread` from flipping the\n // row back until the index's next rebuild agrees.\n const readState = useThreadReadState({\n backendUrl,\n principalId: principal,\n getAuth,\n rows: mergedConversations,\n onServerTruth: ({ threadId, isUnread }) => patchEveryList(threadId, { isUnread }),\n });\n const readOverrides = readState.overrides;\n const readCoveredUpdatedAt = readState.coveredUpdatedAt;\n\n // An archive hides the row at once and keeps it hidden until neither list\n // source reports it any more — the cached page is patched on the server's\n // answer, but the pushed index may still carry the row until the publish\n // that follows the commit lands. A failure drops the id and the row comes\n // back from the still-cached page: no refetch needed. Scoping, the\n // one-write-per-thread guard and the route-missing fallback live in the hook.\n const archive = useThreadArchive({\n backendUrl,\n principalId: principal,\n getAuth,\n onArchived: (threadId) => {\n removeConversationFromListCaches(queryClient, { threadId });\n // The archived session cannot stay the active chat: the server no\n // longer lists it, so the chat moves to a fresh one.\n setActive((current) =>\n current.id === threadId ? { id: mintThreadId(), isNew: true } : current,\n );\n },\n });\n const hiddenThreadIds = archive.hiddenThreadIds;\n const archiveRelease = archive.release;\n // A hidden row is released once both sources have forgotten it, so a\n // session archived elsewhere and then restored is never masked here.\n useEffect(() => {\n if (hiddenThreadIds.size === 0) return;\n const forgotten = [...hiddenThreadIds].filter(\n (threadId) =>\n !mergedConversations.some((conversation) => conversation.threadId === threadId) &&\n !indexByThread.has(threadId),\n );\n if (forgotten.length > 0) archiveRelease(forgotten);\n }, [hiddenThreadIds, mergedConversations, indexByThread, archiveRelease]);\n\n const applyOverrides = useCallback(\n (rows: readonly ConversationSummary[]) =>\n withReadStateOverrides(\n withTitleOverrides(withFavoriteOverrides(rows, favoriteOverrides), titleOverrides),\n readOverrides,\n readCoveredUpdatedAt,\n ).filter((conversation) => !hiddenThreadIds.has(conversation.threadId)),\n [favoriteOverrides, titleOverrides, readOverrides, readCoveredUpdatedAt, hiddenThreadIds],\n );\n const data = useMemo(\n () => applyOverrides(mergedConversations).map(threadSummaryFromConversation),\n [applyOverrides, mergedConversations],\n );\n const isLoading = list.isLoading;\n\n // The active thread's row must survive a search that filters it out of\n // the page (the banner above the chat reads it): the listed row when there\n // is one, else the pushed index entry folded over the last row seen for\n // this thread (so pull requests survive the fold), else that last row.\n const lastActiveConversationRef = useRef<ConversationSummary | null>(null);\n const activeConversation = useMemo<ConversationSummary | null>(() => {\n const listed = mergedConversations.find((conversation) => conversation.threadId === active.id);\n if (listed) return listed;\n const remembered =\n lastActiveConversationRef.current?.threadId === active.id\n ? lastActiveConversationRef.current\n : undefined;\n const entry = indexByThread.get(active.id);\n if (entry) return summaryFromConversationIndexEntry(entry, remembered);\n return remembered ?? null;\n }, [mergedConversations, indexByThread, active.id]);\n if (activeConversation !== null) lastActiveConversationRef.current = activeConversation;\n const activeThread = useMemo(\n () =>\n activeConversation\n ? threadSummaryFromConversation(\n withReadStateOverrides(\n [\n withTitleOverride(\n withFavoriteOverride(activeConversation, favoriteOverrides),\n titleOverrides,\n ),\n ],\n readOverrides,\n readCoveredUpdatedAt,\n )[0] ?? activeConversation,\n )\n : null,\n [activeConversation, favoriteOverrides, titleOverrides, readOverrides, readCoveredUpdatedAt],\n );\n\n const listRefresh = list.refresh;\n const refresh = useCallback(() => {\n void listRefresh();\n }, [listRefresh]);\n const listFetchNextPage = list.fetchNextPage;\n const fetchNextPage = useCallback(() => {\n void listFetchNextPage();\n }, [listFetchNextPage]);\n\n // A thread the index knows — created here on first send, or elsewhere —\n // that the REST page does not list yet: refresh once per such id so the row\n // appears without the user pressing refresh. Rows for apps this list does\n // not show (its `appId` and `additionalListAppIds`) never trigger one.\n const refreshedForRef = useRef<Set<string>>(new Set());\n useEffect(() => {\n if (index.entries === null) return;\n const unlisted = indexedThreadsToRefreshFor({\n entries: index.entries,\n listedThreadIds: new Set(list.conversations.map((conversation) => conversation.threadId)),\n refreshedThreadIds: refreshedForRef.current,\n appId,\n additionalAppIds: listedAppIds,\n });\n for (const threadId of unlisted) refreshedForRef.current.add(threadId);\n if (unlisted.length > 0) void listRefresh();\n }, [index.entries, list.conversations, appId, listedAppIds, listRefresh]);\n\n const selectThread = useCallback((threadId: string) => {\n if (!threadId) return;\n setActive((current) =>\n current.id === threadId ? current : { id: threadId, isNew: false },\n );\n }, []);\n\n // The hover prefetcher is one per (backend, principal, credential\n // generation): a credential swap clears the provider's snapshot cache, so\n // the attempt ledger resets with it and a late answer from the previous\n // identity is never remembered under the new one.\n const prefetchScope = `${backendUrl}::${principal}::${credentialGeneration}`;\n const prefetchScopeRef = useRef(prefetchScope);\n prefetchScopeRef.current = prefetchScope;\n const prefetcher = useMemo(() => {\n if (!snapshotCache) return null;\n const scope = prefetchScope;\n return createThreadPrefetcher({\n cache: snapshotCache,\n fetchState: async (threadId) =>\n withCredentialRenewal(getAuth, (auth) =>\n getThreadState(backendUrl, auth, threadId, { skipCache: false }),\n ),\n isCurrent: () => prefetchScopeRef.current === scope,\n });\n }, [snapshotCache, prefetchScope, backendUrl, getAuth]);\n const activeIdRef = useRef(active.id);\n activeIdRef.current = active.id;\n const prefetchThread = useCallback(\n (threadId: string) => {\n if (!prefetcher || !threadId || threadId === activeIdRef.current) return;\n prefetcher.prefetch(threadId);\n },\n [prefetcher],\n );\n\n const newThread = useCallback(() => {\n setActive({ id: mintThreadId(), isNew: true });\n }, []);\n\n // A minted thread stops being \"new\" once the backend lists it — on the\n // fetched page or in the pushed index (a search may keep it off the page):\n // until then `useAthenaThreadManager` reports a null id, so URL sync cannot\n // name it.\n const isPersisted =\n data.some((thread) => thread.id === active.id) || indexByThread.has(active.id);\n useEffect(() => {\n if (isPersisted) {\n setActive((current) => (current.isNew ? { ...current, isNew: false } : current));\n }\n }, [isPersisted]);\n\n const titleSource: AthenaStatewireThreadListState['titleSource'] =\n index.entries !== null ? 'index' : 'poll';\n\n const value = useMemo<AthenaStatewireThreadListState>(\n () => ({\n threads: data,\n isLoading,\n isFetching: list.isFetching,\n hasResolvedFirstPage: list.hasResolvedFirstPage,\n activeThreadId: active.id,\n activeThread,\n isNewChat: active.isNew,\n selectThread,\n prefetchThread,\n newThread,\n refresh,\n search,\n setSearch,\n hasNextPage: list.hasNextPage,\n isFetchingNextPage: list.isFetchingNextPage,\n fetchNextPage,\n setFavorited: favorite.setFavorited,\n favoritePending: favorite.isPending,\n favoritePendingThreadIds: favorite.pendingThreadIds,\n favoriteToggleAvailable: favorite.isAvailable,\n renameThread: rename.rename,\n renamePendingThreadIds: rename.pendingThreadIds,\n renameAvailable: rename.isAvailable,\n archiveThread: archive.archive,\n archivePendingThreadIds: archive.pendingThreadIds,\n archivePending: archive.isPending,\n archiveAvailable: archive.isAvailable,\n setReadState: readState.setReadState,\n readStatePendingThreadIds: readState.pendingThreadIds,\n titleSource,\n }),\n [\n data,\n isLoading,\n list.isFetching,\n list.hasResolvedFirstPage,\n active.id,\n activeThread,\n active.isNew,\n selectThread,\n prefetchThread,\n newThread,\n refresh,\n search,\n list.hasNextPage,\n list.isFetchingNextPage,\n fetchNextPage,\n favorite.setFavorited,\n favorite.isPending,\n favorite.pendingThreadIds,\n favorite.isAvailable,\n rename.rename,\n rename.pendingThreadIds,\n rename.isAvailable,\n archive.archive,\n archive.pendingThreadIds,\n archive.isPending,\n archive.isAvailable,\n readState.setReadState,\n readState.pendingThreadIds,\n titleSource,\n ],\n );\n\n const live = useMemo<AthenaSessionsLiveState>(\n () => ({\n backendUrl,\n getAuth,\n principal,\n hasAuth,\n includePullRequests,\n scopeKey: listScopeKey,\n credentialGeneration,\n baseFilter: {\n ...(appId ? { appId } : {}),\n ...(listedAppIds.length > 0 ? { appIds: listedAppIds } : {}),\n },\n indexByThread,\n indexEntries: index.entries,\n applyOverrides,\n }),\n [\n backendUrl,\n getAuth,\n principal,\n hasAuth,\n includePullRequests,\n listScopeKey,\n credentialGeneration,\n appId,\n listedAppIds,\n indexByThread,\n index.entries,\n applyOverrides,\n ],\n );\n\n return (\n <AthenaStatewireThreadListContext.Provider value={value}>\n <AthenaSessionsLiveContext.Provider value={live}>{children}</AthenaSessionsLiveContext.Provider>\n </AthenaStatewireThreadListContext.Provider>\n );\n}\n\n/**\n * Provides the statewire thread-list state, with an SDK-scoped QueryClient so\n * consumers do not need their own QueryClientProvider. `syncUrl` (the\n * `…/v2/threads` mount) locates the conversation index beside it; without it\n * titles fall back to the REST poll. `includePullRequests` (default `true`)\n * asks the list for live pull-request state so `SessionList` can render its\n * chips; a host that never shows them turns it off to spare the server the\n * lookup. `snapshotCache` is the provider's thread snapshot cache — the one\n * the runtime seeds a switched-to thread from — which `prefetchThread` warms;\n * without it prefetching is a no-op.\n */\nexport function AthenaStatewireThreadListProvider({\n backendUrl,\n syncUrl,\n apiKey,\n token,\n getToken,\n appId,\n additionalListAppIds,\n initialThreadId,\n includePullRequests = true,\n snapshotCache,\n children,\n}: {\n backendUrl: string;\n syncUrl?: string;\n apiKey?: string;\n token?: string | null;\n getToken?: AthenaStatewireTokenGetter;\n appId?: string;\n /** Other client apps whose sessions the list shows too (a union with `appId`). */\n additionalListAppIds?: readonly string[];\n initialThreadId?: string;\n includePullRequests?: boolean;\n snapshotCache?: DeepAgentThreadSnapshotCache;\n children: ReactNode;\n}) {\n const [queryClient] = useState(() => new QueryClient());\n return (\n <QueryClientProvider client={queryClient}>\n <StatewireThreadListState\n backendUrl={backendUrl}\n syncUrl={syncUrl}\n apiKey={apiKey}\n token={token}\n getToken={getToken}\n appId={appId}\n additionalListAppIds={additionalListAppIds}\n initialThreadId={initialThreadId}\n includePullRequests={includePullRequests}\n snapshotCache={snapshotCache}\n >\n {children}\n </StatewireThreadListState>\n </QueryClientProvider>\n );\n}\n\n/** How long after a thread's first message the title poll starts (exported for tests). */\nexport const TITLE_POLL_DELAY_MS = 5000;\nconst TITLE_POLL_INTERVAL_MS = 2000;\nconst TITLE_POLL_MAX_DURATION_MS = 60_000;\n\n/**\n * Fallback for hosts without a live conversation index (`titleSource: 'poll'`,\n * i.e. no signed-in principal): refreshes the thread list until a\n * freshly-started thread's server-generated title appears. Idle while the\n * index carries titles. Mount inside the statewire runtime scope (needs aui\n * state).\n *\n * The thread is read from the statewire scope, not the list: the scope\n * publishes the id together with the client it belongs to, so the messages\n * observed here are always the named thread's (the list's selection moves\n * one commit ahead of the client during a switch).\n */\nexport function StatewireThreadTitlePoller(): null {\n const list = useAthenaStatewireThreadList();\n const activeThreadId = useAthenaStatewireThreadId();\n const hasMessages = useAuiState((s) => (s.optional.thread?.messages.length ?? 0) > 0);\n\n const titleSource = list?.titleSource ?? 'poll';\n const entry = list?.threads.find((thread) => thread.id === activeThreadId);\n const title = entry?.title?.trim() ?? '';\n const hasTitle = title.length > 0 && !isSerializedContentPartsTitle(title);\n\n // The poller stays mounted across thread switches, so the visit is tracked\n // by hand: one poll per visit — no restart when the visited thread's\n // messages or title flip underneath it — and a re-selected thread polls\n // again, as it did when every switch remounted the poller. The record is\n // replaced whenever the attached thread changes, whether or not a poll\n // started for it, so a visit to a thread that needs no poll can never make\n // the next visit to a previous thread look already polled.\n const visitRef = useRef<{ threadId: string; polled: boolean } | null>(null);\n const refreshRef = useRef(list?.refresh);\n refreshRef.current = list?.refresh;\n\n useEffect(() => {\n if (visitRef.current?.threadId !== activeThreadId) {\n visitRef.current = { threadId: activeThreadId, polled: false };\n }\n const visit = visitRef.current;\n if (!hasMessages || hasTitle || titleSource === 'index') return;\n if (visit.polled) return;\n visit.polled = true;\n\n let intervalId: ReturnType<typeof setInterval> | null = null;\n const startId = setTimeout(() => {\n intervalId = setInterval(() => refreshRef.current?.(), TITLE_POLL_INTERVAL_MS);\n }, TITLE_POLL_DELAY_MS);\n const stopId = setTimeout(() => {\n if (intervalId !== null) clearInterval(intervalId);\n }, TITLE_POLL_MAX_DURATION_MS);\n\n return () => {\n clearTimeout(startId);\n clearTimeout(stopId);\n if (intervalId !== null) clearInterval(intervalId);\n };\n }, [activeThreadId, hasMessages, hasTitle, titleSource]);\n\n return null;\n}\n"],"names":["createContext","useContext","normalizeThreadTitle","deriveConversationAttention","summaryFromConversationIndexEntry","useState","mintThreadId","useRef","AthenaAuthContext","useCallback","resolveStatewireAuthToken","useMemo","createRestConversationListFetcher","useConversationList","resolveStatewireAuthHeaders","credentialShape","sameCredentialShape","useQuery","withCredentialRenewal","fetchAccountIdentity","useConversationIndex","conversationIndexUrlFromStatewireUrl","useRestartAfterAuthRefusal","useQueryClient","patchConversationListCaches","useThreadFavorite","useThreadRename","title","useThreadReadState","useThreadArchive","removeConversationFromListCaches","useEffect","withReadStateOverrides","withTitleOverrides","withFavoriteOverrides","_a","withTitleOverride","withFavoriteOverride","createThreadPrefetcher","getThreadState","jsx","QueryClient","QueryClientProvider","useAthenaStatewireThreadId","useAuiState","isSerializedContentPartsTitle"],"mappings":"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"}
|