@athenaintel/react 0.57.2 → 0.60.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 +795 -12
- package/dist/agent-runtime/src/addressed-agents.cjs +16 -0
- package/dist/agent-runtime/src/addressed-agents.cjs.map +1 -0
- package/dist/agent-runtime/src/addressed-agents.d.ts +30 -0
- package/dist/agent-runtime/src/addressed-agents.js +16 -0
- package/dist/agent-runtime/src/addressed-agents.js.map +1 -0
- package/dist/agent-runtime/src/answer-label.cjs +4 -3
- package/dist/agent-runtime/src/answer-label.cjs.map +1 -1
- package/dist/agent-runtime/src/answer-label.d.ts +13 -6
- package/dist/agent-runtime/src/answer-label.js +4 -3
- package/dist/agent-runtime/src/answer-label.js.map +1 -1
- package/dist/agent-runtime/src/chat-outbox-attachments.cjs.map +1 -1
- package/dist/agent-runtime/src/chat-outbox-attachments.d.ts +1 -1
- package/dist/agent-runtime/src/chat-outbox-attachments.js.map +1 -1
- package/dist/agent-runtime/src/chat-outbox-entry.cjs +101 -0
- package/dist/agent-runtime/src/chat-outbox-entry.cjs.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-entry.d.ts +99 -0
- package/dist/agent-runtime/src/chat-outbox-entry.js +101 -0
- package/dist/agent-runtime/src/chat-outbox-entry.js.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-legacy.cjs +252 -0
- package/dist/agent-runtime/src/chat-outbox-legacy.cjs.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-legacy.d.ts +96 -0
- package/dist/agent-runtime/src/chat-outbox-legacy.js +252 -0
- package/dist/agent-runtime/src/chat-outbox-legacy.js.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-policy.cjs +30 -0
- package/dist/agent-runtime/src/chat-outbox-policy.cjs.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-policy.d.ts +42 -0
- package/dist/agent-runtime/src/chat-outbox-policy.js +30 -0
- package/dist/agent-runtime/src/chat-outbox-policy.js.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-storage.cjs +306 -0
- package/dist/agent-runtime/src/chat-outbox-storage.cjs.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-storage.d.ts +194 -0
- package/dist/agent-runtime/src/chat-outbox-storage.js +306 -0
- package/dist/agent-runtime/src/chat-outbox-storage.js.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-thread.cjs +21 -94
- package/dist/agent-runtime/src/chat-outbox-thread.cjs.map +1 -1
- package/dist/agent-runtime/src/chat-outbox-thread.d.ts +22 -18
- package/dist/agent-runtime/src/chat-outbox-thread.js +21 -94
- package/dist/agent-runtime/src/chat-outbox-thread.js.map +1 -1
- package/dist/agent-runtime/src/chat-outbox.cjs +492 -547
- package/dist/agent-runtime/src/chat-outbox.cjs.map +1 -1
- package/dist/agent-runtime/src/chat-outbox.d.ts +110 -142
- package/dist/agent-runtime/src/chat-outbox.js +492 -547
- package/dist/agent-runtime/src/chat-outbox.js.map +1 -1
- package/dist/agent-runtime/src/composer-markdown.cjs +0 -16
- package/dist/agent-runtime/src/composer-markdown.cjs.map +1 -1
- package/dist/agent-runtime/src/composer-markdown.d.ts +1 -1
- package/dist/agent-runtime/src/composer-markdown.js +1 -17
- package/dist/agent-runtime/src/composer-markdown.js.map +1 -1
- package/dist/agent-runtime/src/deep-agent-transport-recipe.cjs +3 -1
- package/dist/agent-runtime/src/deep-agent-transport-recipe.cjs.map +1 -1
- package/dist/agent-runtime/src/deep-agent-transport-recipe.d.ts +8 -1
- package/dist/agent-runtime/src/deep-agent-transport-recipe.js +3 -1
- package/dist/agent-runtime/src/deep-agent-transport-recipe.js.map +1 -1
- package/dist/agent-runtime/src/dictation-preferences.d.ts +356 -0
- package/dist/agent-runtime/src/dictation-record.d.ts +279 -0
- package/dist/agent-runtime/src/dictation-session.d.ts +106 -7
- package/dist/agent-runtime/src/dictation-snippets.d.ts +9 -0
- package/dist/agent-runtime/src/dictation-transfer.d.ts +142 -0
- package/dist/agent-runtime/src/edit-command.cjs.map +1 -1
- package/dist/agent-runtime/src/edit-command.d.ts +1 -1
- package/dist/agent-runtime/src/edit-command.js.map +1 -1
- package/dist/agent-runtime/src/errors.cjs +1 -0
- package/dist/agent-runtime/src/errors.cjs.map +1 -1
- package/dist/agent-runtime/src/errors.js +1 -0
- package/dist/agent-runtime/src/errors.js.map +1 -1
- package/dist/agent-runtime/src/generated/runconfig-contract.cjs +24 -0
- package/dist/agent-runtime/src/generated/runconfig-contract.cjs.map +1 -1
- package/dist/agent-runtime/src/generated/runconfig-contract.d.ts +3 -3
- package/dist/agent-runtime/src/generated/runconfig-contract.js +24 -0
- package/dist/agent-runtime/src/generated/runconfig-contract.js.map +1 -1
- package/dist/agent-runtime/src/index.d.ts +14 -8
- package/dist/agent-runtime/src/lane-follow.cjs +289 -0
- package/dist/agent-runtime/src/lane-follow.cjs.map +1 -0
- package/dist/agent-runtime/src/lane-follow.js +289 -0
- package/dist/agent-runtime/src/lane-follow.js.map +1 -0
- package/dist/agent-runtime/src/lane-images.cjs +387 -0
- package/dist/agent-runtime/src/lane-images.cjs.map +1 -0
- package/dist/agent-runtime/src/lane-images.js +387 -0
- package/dist/agent-runtime/src/lane-images.js.map +1 -0
- package/dist/agent-runtime/src/message-window.js +1 -1
- package/dist/agent-runtime/src/messages.cjs +19 -1
- package/dist/agent-runtime/src/messages.cjs.map +1 -1
- package/dist/agent-runtime/src/messages.d.ts +8 -0
- package/dist/agent-runtime/src/messages.js +21 -3
- package/dist/agent-runtime/src/messages.js.map +1 -1
- package/dist/agent-runtime/src/named-agents.cjs +301 -0
- package/dist/agent-runtime/src/named-agents.cjs.map +1 -0
- package/dist/agent-runtime/src/named-agents.d.ts +246 -0
- package/dist/agent-runtime/src/named-agents.js +301 -0
- package/dist/agent-runtime/src/named-agents.js.map +1 -0
- package/dist/agent-runtime/src/offline-status.cjs.map +1 -1
- package/dist/agent-runtime/src/offline-status.d.ts +93 -2
- package/dist/agent-runtime/src/offline-status.js.map +1 -1
- package/dist/agent-runtime/src/ptc-subcalls.cjs +41 -0
- package/dist/agent-runtime/src/ptc-subcalls.cjs.map +1 -0
- package/dist/agent-runtime/src/ptc-subcalls.js +41 -0
- package/dist/agent-runtime/src/ptc-subcalls.js.map +1 -0
- package/dist/agent-runtime/src/queue.cjs +2 -2
- package/dist/agent-runtime/src/queue.cjs.map +1 -1
- package/dist/agent-runtime/src/queue.d.ts +20 -25
- package/dist/agent-runtime/src/queue.js +2 -2
- package/dist/agent-runtime/src/queue.js.map +1 -1
- package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs +314 -84
- package/dist/agent-runtime/src/quota-safe-local-storage-session.cjs.map +1 -1
- package/dist/agent-runtime/src/quota-safe-local-storage-session.d.ts +137 -40
- package/dist/agent-runtime/src/quota-safe-local-storage-session.js +318 -88
- package/dist/agent-runtime/src/quota-safe-local-storage-session.js.map +1 -1
- package/dist/agent-runtime/src/run-send.cjs +54 -0
- package/dist/agent-runtime/src/run-send.cjs.map +1 -0
- package/dist/agent-runtime/src/run-send.d.ts +51 -0
- package/dist/agent-runtime/src/run-send.js +54 -0
- package/dist/agent-runtime/src/run-send.js.map +1 -0
- package/dist/agent-runtime/src/running-tool-placeholder.cjs +6 -0
- package/dist/agent-runtime/src/running-tool-placeholder.cjs.map +1 -1
- package/dist/agent-runtime/src/running-tool-placeholder.js +6 -0
- package/dist/agent-runtime/src/running-tool-placeholder.js.map +1 -1
- package/dist/agent-runtime/src/runtime.d.ts +9 -5
- package/dist/agent-runtime/src/sealed-idb.cjs +64 -0
- package/dist/agent-runtime/src/sealed-idb.cjs.map +1 -1
- package/dist/agent-runtime/src/sealed-idb.d.ts +16 -0
- package/dist/agent-runtime/src/sealed-idb.js +64 -0
- package/dist/agent-runtime/src/sealed-idb.js.map +1 -1
- package/dist/agent-runtime/src/send-recovery.cjs +90 -118
- package/dist/agent-runtime/src/send-recovery.cjs.map +1 -1
- package/dist/agent-runtime/src/send-recovery.d.ts +25 -29
- package/dist/agent-runtime/src/send-recovery.js +90 -118
- package/dist/agent-runtime/src/send-recovery.js.map +1 -1
- package/dist/agent-runtime/src/statewire-diagnostics.d.ts +4 -1
- package/dist/agent-runtime/src/statewire-held-sends.cjs +191 -0
- package/dist/agent-runtime/src/statewire-held-sends.cjs.map +1 -0
- package/dist/agent-runtime/src/statewire-held-sends.d.ts +119 -0
- package/dist/agent-runtime/src/statewire-held-sends.js +191 -0
- package/dist/agent-runtime/src/statewire-held-sends.js.map +1 -0
- package/dist/agent-runtime/src/statewire-state.cjs +4 -0
- package/dist/agent-runtime/src/statewire-state.cjs.map +1 -1
- package/dist/agent-runtime/src/statewire-state.js +4 -0
- package/dist/agent-runtime/src/statewire-state.js.map +1 -1
- package/dist/agent-runtime/src/statewire-transport.cjs +8 -2
- package/dist/agent-runtime/src/statewire-transport.cjs.map +1 -1
- package/dist/agent-runtime/src/statewire-transport.d.ts +14 -5
- package/dist/agent-runtime/src/statewire-transport.js +8 -2
- package/dist/agent-runtime/src/statewire-transport.js.map +1 -1
- package/dist/agent-runtime/src/subagent-transcripts.cjs +1 -23
- package/dist/agent-runtime/src/subagent-transcripts.cjs.map +1 -1
- package/dist/agent-runtime/src/subagent-transcripts.js +3 -25
- package/dist/agent-runtime/src/subagent-transcripts.js.map +1 -1
- package/dist/agent-runtime/src/subagents.cjs +22 -29
- package/dist/agent-runtime/src/subagents.cjs.map +1 -1
- package/dist/agent-runtime/src/subagents.js +23 -30
- package/dist/agent-runtime/src/subagents.js.map +1 -1
- package/dist/agent-runtime/src/thread-extras.cjs +27 -19
- package/dist/agent-runtime/src/thread-extras.cjs.map +1 -1
- package/dist/agent-runtime/src/thread-extras.d.ts +19 -6
- package/dist/agent-runtime/src/thread-extras.js +27 -19
- package/dist/agent-runtime/src/thread-extras.js.map +1 -1
- package/dist/agent-runtime/src/thread-handoff-flow-machine.d.ts +8 -8
- package/dist/agent-runtime/src/tool-metadata.cjs +19 -0
- package/dist/agent-runtime/src/tool-metadata.cjs.map +1 -1
- package/dist/agent-runtime/src/tool-metadata.js +19 -0
- package/dist/agent-runtime/src/tool-metadata.js.map +1 -1
- package/dist/agent-runtime/src/tool-names.cjs +21 -0
- package/dist/agent-runtime/src/tool-names.cjs.map +1 -1
- package/dist/agent-runtime/src/tool-names.d.ts +8 -0
- package/dist/agent-runtime/src/tool-names.js +21 -0
- package/dist/agent-runtime/src/tool-names.js.map +1 -1
- package/dist/agent-runtime/src/typed-interrupt-kinds.cjs +247 -0
- package/dist/agent-runtime/src/typed-interrupt-kinds.cjs.map +1 -0
- package/dist/agent-runtime/src/typed-interrupt-kinds.d.ts +173 -0
- package/dist/agent-runtime/src/typed-interrupt-kinds.js +247 -0
- package/dist/agent-runtime/src/typed-interrupt-kinds.js.map +1 -0
- package/dist/agent-runtime/src/typed-interrupts.cjs +48 -0
- package/dist/agent-runtime/src/typed-interrupts.cjs.map +1 -0
- package/dist/agent-runtime/src/typed-interrupts.d.ts +75 -0
- package/dist/agent-runtime/src/typed-interrupts.js +48 -0
- package/dist/agent-runtime/src/typed-interrupts.js.map +1 -0
- package/dist/agent-runtime/src/types.d.ts +1 -1
- package/dist/agent-runtime/src/use-conversation-list.cjs +1 -0
- package/dist/agent-runtime/src/use-conversation-list.cjs.map +1 -1
- package/dist/agent-runtime/src/use-conversation-list.d.ts +7 -0
- package/dist/agent-runtime/src/use-conversation-list.js +1 -0
- package/dist/agent-runtime/src/use-conversation-list.js.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.cjs +46 -29
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.d.ts +14 -22
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.js +46 -29
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.js.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-runtime.cjs +78 -14
- package/dist/agent-runtime/src/use-deep-agent-runtime.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-runtime.d.ts +34 -7
- package/dist/agent-runtime/src/use-deep-agent-runtime.js +79 -15
- package/dist/agent-runtime/src/use-deep-agent-runtime.js.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-thread.cjs +16 -1
- package/dist/agent-runtime/src/use-deep-agent-thread.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-thread.d.ts +7 -2
- package/dist/agent-runtime/src/use-deep-agent-thread.js +16 -1
- package/dist/agent-runtime/src/use-deep-agent-thread.js.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-voice.cjs +30 -4
- package/dist/agent-runtime/src/use-deep-agent-voice.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-voice.d.ts +22 -4
- package/dist/agent-runtime/src/use-deep-agent-voice.js +30 -4
- package/dist/agent-runtime/src/use-deep-agent-voice.js.map +1 -1
- package/dist/agent-runtime/src/withdrawn-turns.d.ts +5 -4
- package/dist/agent-runtime/src/word-device-fit.d.ts +174 -0
- package/dist/agent-runtime/src/work-in.d.ts +127 -0
- package/dist/assets/AthenaAssetEmbed.cjs.map +1 -1
- package/dist/assets/AthenaAssetEmbed.d.ts +6 -1
- package/dist/assets/AthenaAssetEmbed.js.map +1 -1
- package/dist/assets/asset-panel-store.cjs +13 -5
- package/dist/assets/asset-panel-store.cjs.map +1 -1
- package/dist/assets/asset-panel-store.d.ts +33 -2
- package/dist/assets/asset-panel-store.js +13 -5
- package/dist/assets/asset-panel-store.js.map +1 -1
- package/dist/auth/AthenaCredentialSourceContext.cjs +11 -0
- package/dist/auth/AthenaCredentialSourceContext.cjs.map +1 -1
- package/dist/auth/AthenaCredentialSourceContext.d.ts +6 -0
- package/dist/auth/AthenaCredentialSourceContext.js +11 -0
- package/dist/auth/AthenaCredentialSourceContext.js.map +1 -1
- package/dist/auth/account-identity.cjs +13 -2
- package/dist/auth/account-identity.cjs.map +1 -1
- package/dist/auth/account-identity.d.ts +9 -0
- package/dist/auth/account-identity.js +13 -2
- package/dist/auth/account-identity.js.map +1 -1
- package/dist/auth/credential-source.cjs +20 -4
- package/dist/auth/credential-source.cjs.map +1 -1
- package/dist/auth/credential-source.d.ts +9 -0
- package/dist/auth/credential-source.js +20 -4
- package/dist/auth/credential-source.js.map +1 -1
- package/dist/catalog/chat-pickers.cjs +31 -0
- package/dist/catalog/chat-pickers.cjs.map +1 -1
- package/dist/catalog/chat-pickers.d.ts +17 -0
- package/dist/catalog/chat-pickers.js +33 -2
- package/dist/catalog/chat-pickers.js.map +1 -1
- package/dist/catalog/runtime-catalog.cjs +63 -3
- package/dist/catalog/runtime-catalog.cjs.map +1 -1
- package/dist/catalog/runtime-catalog.d.ts +63 -3
- package/dist/catalog/runtime-catalog.js +64 -4
- package/dist/catalog/runtime-catalog.js.map +1 -1
- package/dist/chat/AthenaChat.cjs +301 -98
- package/dist/chat/AthenaChat.cjs.map +1 -1
- package/dist/chat/AthenaChat.d.ts +80 -4
- package/dist/chat/AthenaChat.js +302 -99
- package/dist/chat/AthenaChat.js.map +1 -1
- package/dist/chat/StatewireApprovalCard.cjs +35 -5
- package/dist/chat/StatewireApprovalCard.cjs.map +1 -1
- package/dist/chat/StatewireApprovalCard.d.ts +55 -2
- package/dist/chat/StatewireApprovalCard.js +37 -7
- package/dist/chat/StatewireApprovalCard.js.map +1 -1
- package/dist/chat/StatewireQueuedMessages.cjs +17 -2
- package/dist/chat/StatewireQueuedMessages.cjs.map +1 -1
- package/dist/chat/StatewireQueuedMessages.d.ts +8 -45
- package/dist/chat/StatewireQueuedMessages.js +18 -3
- package/dist/chat/StatewireQueuedMessages.js.map +1 -1
- package/dist/chat/chat-agent-mentions.cjs +70 -0
- package/dist/chat/chat-agent-mentions.cjs.map +1 -0
- package/dist/chat/chat-agent-mentions.d.ts +13 -0
- package/dist/chat/chat-agent-mentions.js +70 -0
- package/dist/chat/chat-agent-mentions.js.map +1 -0
- package/dist/chat/composer-actions.cjs +12 -0
- package/dist/chat/composer-actions.cjs.map +1 -0
- package/dist/chat/composer-actions.d.ts +22 -0
- package/dist/chat/composer-actions.js +12 -0
- package/dist/chat/composer-actions.js.map +1 -0
- package/dist/chat/follow-up-suggestions.cjs +185 -0
- package/dist/chat/follow-up-suggestions.cjs.map +1 -0
- package/dist/chat/follow-up-suggestions.d.ts +64 -0
- package/dist/chat/follow-up-suggestions.js +185 -0
- package/dist/chat/follow-up-suggestions.js.map +1 -0
- package/dist/chat/super-grouping/ToolTimeline.cjs +4 -3
- package/dist/chat/super-grouping/ToolTimeline.cjs.map +1 -1
- package/dist/chat/super-grouping/ToolTimeline.d.ts +7 -3
- package/dist/chat/super-grouping/ToolTimeline.js +4 -3
- package/dist/chat/super-grouping/ToolTimeline.js.map +1 -1
- package/dist/chat/turn-changes.cjs +284 -0
- package/dist/chat/turn-changes.cjs.map +1 -0
- package/dist/chat/turn-changes.d.ts +130 -0
- package/dist/chat/turn-changes.js +284 -0
- package/dist/chat/turn-changes.js.map +1 -0
- package/dist/chat/typed-interrupts/StatewireTypedInterruptCard.cjs +31 -0
- package/dist/chat/typed-interrupts/StatewireTypedInterruptCard.cjs.map +1 -0
- package/dist/chat/typed-interrupts/StatewireTypedInterruptCard.d.ts +31 -0
- package/dist/chat/typed-interrupts/StatewireTypedInterruptCard.js +31 -0
- package/dist/chat/typed-interrupts/StatewireTypedInterruptCard.js.map +1 -0
- package/dist/chat/typed-interrupts/approval-cards.cjs +250 -0
- package/dist/chat/typed-interrupts/approval-cards.cjs.map +1 -0
- package/dist/chat/typed-interrupts/approval-cards.d.ts +22 -0
- package/dist/chat/typed-interrupts/approval-cards.js +250 -0
- package/dist/chat/typed-interrupts/approval-cards.js.map +1 -0
- package/dist/chat/typed-interrupts/form-cards.cjs +289 -0
- package/dist/chat/typed-interrupts/form-cards.cjs.map +1 -0
- package/dist/chat/typed-interrupts/form-cards.d.ts +6 -0
- package/dist/chat/typed-interrupts/form-cards.js +289 -0
- package/dist/chat/typed-interrupts/form-cards.js.map +1 -0
- package/dist/chat/typed-interrupts/interrupt-card-shell.cjs +182 -0
- package/dist/chat/typed-interrupts/interrupt-card-shell.cjs.map +1 -0
- package/dist/chat/typed-interrupts/interrupt-card-shell.d.ts +47 -0
- package/dist/chat/typed-interrupts/interrupt-card-shell.js +182 -0
- package/dist/chat/typed-interrupts/interrupt-card-shell.js.map +1 -0
- package/dist/chat/typed-interrupts/json-schema-form.cjs +388 -0
- package/dist/chat/typed-interrupts/json-schema-form.cjs.map +1 -0
- package/dist/chat/typed-interrupts/json-schema-form.d.ts +33 -0
- package/dist/chat/typed-interrupts/json-schema-form.js +388 -0
- package/dist/chat/typed-interrupts/json-schema-form.js.map +1 -0
- package/dist/chat/typed-interrupts/questionnaire-card.cjs +449 -0
- package/dist/chat/typed-interrupts/questionnaire-card.cjs.map +1 -0
- package/dist/chat/typed-interrupts/questionnaire-card.d.ts +20 -0
- package/dist/chat/typed-interrupts/questionnaire-card.js +449 -0
- package/dist/chat/typed-interrupts/questionnaire-card.js.map +1 -0
- package/dist/chat/typed-interrupts/request-file-card.cjs +159 -0
- package/dist/chat/typed-interrupts/request-file-card.cjs.map +1 -0
- package/dist/chat/typed-interrupts/request-file-card.d.ts +2 -0
- package/dist/chat/typed-interrupts/request-file-card.js +159 -0
- package/dist/chat/typed-interrupts/request-file-card.js.map +1 -0
- package/dist/chat/typed-interrupts/toolkit-selection-card.cjs +189 -0
- package/dist/chat/typed-interrupts/toolkit-selection-card.cjs.map +1 -0
- package/dist/chat/typed-interrupts/toolkit-selection-card.d.ts +23 -0
- package/dist/chat/typed-interrupts/toolkit-selection-card.js +189 -0
- package/dist/chat/typed-interrupts/toolkit-selection-card.js.map +1 -0
- package/dist/chat/typed-interrupts/typed-interrupt-body.cjs +26 -0
- package/dist/chat/typed-interrupts/typed-interrupt-body.cjs.map +1 -0
- package/dist/chat/typed-interrupts/typed-interrupt-body.d.ts +3 -0
- package/dist/chat/typed-interrupts/typed-interrupt-body.js +26 -0
- package/dist/chat/typed-interrupts/typed-interrupt-body.js.map +1 -0
- package/dist/chat/typed-interrupts/typed-interrupt-graphql.cjs +105 -0
- package/dist/chat/typed-interrupts/typed-interrupt-graphql.cjs.map +1 -0
- package/dist/chat/typed-interrupts/typed-interrupt-graphql.d.ts +29 -0
- package/dist/chat/typed-interrupts/typed-interrupt-graphql.js +105 -0
- package/dist/chat/typed-interrupts/typed-interrupt-graphql.js.map +1 -0
- package/dist/chat/typed-interrupts/typed-interrupt-notice.cjs +70 -0
- package/dist/chat/typed-interrupts/typed-interrupt-notice.cjs.map +1 -0
- package/dist/chat/typed-interrupts/typed-interrupt-notice.d.ts +45 -0
- package/dist/chat/typed-interrupts/typed-interrupt-notice.js +70 -0
- package/dist/chat/typed-interrupts/typed-interrupt-notice.js.map +1 -0
- package/dist/chat/typed-interrupts/typed-interrupt-panel.cjs +76 -0
- package/dist/chat/typed-interrupts/typed-interrupt-panel.cjs.map +1 -0
- package/dist/chat/typed-interrupts/typed-interrupt-panel.d.ts +11 -0
- package/dist/chat/typed-interrupts/typed-interrupt-panel.js +76 -0
- package/dist/chat/typed-interrupts/typed-interrupt-panel.js.map +1 -0
- package/dist/chat/typed-interrupts/typed-interrupt-types.d.ts +46 -0
- package/dist/chat/typed-interrupts/use-interrupt-draft.cjs +106 -0
- package/dist/chat/typed-interrupts/use-interrupt-draft.cjs.map +1 -0
- package/dist/chat/typed-interrupts/use-interrupt-draft.d.ts +29 -0
- package/dist/chat/typed-interrupts/use-interrupt-draft.js +106 -0
- package/dist/chat/typed-interrupts/use-interrupt-draft.js.map +1 -0
- package/dist/chat/typed-interrupts/use-statewire-typed-interrupt.cjs +231 -0
- package/dist/chat/typed-interrupts/use-statewire-typed-interrupt.cjs.map +1 -0
- package/dist/chat/typed-interrupts/use-statewire-typed-interrupt.d.ts +66 -0
- package/dist/chat/typed-interrupts/use-statewire-typed-interrupt.js +231 -0
- package/dist/chat/typed-interrupts/use-statewire-typed-interrupt.js.map +1 -0
- package/dist/chat-ui/composer/composer-named-agents.cjs +13 -0
- package/dist/chat-ui/composer/composer-named-agents.cjs.map +1 -0
- package/dist/chat-ui/composer/composer-named-agents.d.ts +20 -0
- package/dist/chat-ui/composer/composer-named-agents.js +13 -0
- package/dist/chat-ui/composer/composer-named-agents.js.map +1 -0
- package/dist/chat-ui/composer/slash-command-menu.cjs +143 -0
- package/dist/chat-ui/composer/slash-command-menu.cjs.map +1 -0
- package/dist/chat-ui/composer/slash-command-menu.d.ts +19 -0
- package/dist/chat-ui/composer/slash-command-menu.js +143 -0
- package/dist/chat-ui/composer/slash-command-menu.js.map +1 -0
- package/dist/chat-ui/composer/slash-commands-extension.cjs +51 -0
- package/dist/chat-ui/composer/slash-commands-extension.cjs.map +1 -0
- package/dist/chat-ui/composer/slash-commands-extension.d.ts +39 -0
- package/dist/chat-ui/composer/slash-commands-extension.js +51 -0
- package/dist/chat-ui/composer/slash-commands-extension.js.map +1 -0
- package/dist/chat-ui/composer/slash-commands.cjs +74 -0
- package/dist/chat-ui/composer/slash-commands.cjs.map +1 -0
- package/dist/chat-ui/composer/slash-commands.d.ts +82 -0
- package/dist/chat-ui/composer/slash-commands.js +74 -0
- package/dist/chat-ui/composer/slash-commands.js.map +1 -0
- package/dist/chat-ui/composer/tiptap-composer.cjs +135 -9
- package/dist/chat-ui/composer/tiptap-composer.cjs.map +1 -1
- package/dist/chat-ui/composer/tiptap-composer.d.ts +61 -2
- package/dist/chat-ui/composer/tiptap-composer.js +135 -9
- package/dist/chat-ui/composer/tiptap-composer.js.map +1 -1
- package/dist/chat-ui/index.cjs +5 -0
- package/dist/chat-ui/index.cjs.map +1 -1
- package/dist/chat-ui/index.d.ts +4 -2
- package/dist/chat-ui/index.js +5 -0
- package/dist/chat-ui/index.js.map +1 -1
- package/dist/chat-ui/mentions/mention-chip.cjs +10 -4
- package/dist/chat-ui/mentions/mention-chip.cjs.map +1 -1
- package/dist/chat-ui/mentions/mention-chip.js +11 -5
- package/dist/chat-ui/mentions/mention-chip.js.map +1 -1
- package/dist/chat-ui/mentions/mention-extension.cjs +8 -1
- package/dist/chat-ui/mentions/mention-extension.cjs.map +1 -1
- package/dist/chat-ui/mentions/mention-extension.js +8 -1
- package/dist/chat-ui/mentions/mention-extension.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/get-scope-name.cjs +1 -0
- package/dist/chat-ui/mentions/suggestions/components/get-scope-name.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/get-scope-name.js +1 -0
- package/dist/chat-ui/mentions/suggestions/components/get-scope-name.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/mention-icon.cjs +20 -2
- package/dist/chat-ui/mentions/suggestions/components/mention-icon.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/mention-icon.d.ts +10 -1
- package/dist/chat-ui/mentions/suggestions/components/mention-icon.js +22 -4
- package/dist/chat-ui/mentions/suggestions/components/mention-icon.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/menu-item.cjs +1 -1
- package/dist/chat-ui/mentions/suggestions/components/menu-item.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/components/menu-item.js +1 -1
- package/dist/chat-ui/mentions/suggestions/components/menu-item.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/api-client.cjs +45 -0
- package/dist/chat-ui/mentions/suggestions/data/api-client.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/api-client.d.ts +48 -0
- package/dist/chat-ui/mentions/suggestions/data/api-client.js +45 -0
- package/dist/chat-ui/mentions/suggestions/data/api-client.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icon-names.generated.cjs +89 -0
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icon-names.generated.cjs.map +1 -0
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icon-names.generated.d.ts +8 -0
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icon-names.generated.js +89 -0
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icon-names.generated.js.map +1 -0
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icons.cjs +140 -116
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icons.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icons.d.ts +46 -12
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icons.js +141 -117
- package/dist/chat-ui/mentions/suggestions/data/sources/asset-type-icons.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs +272 -25
- package/dist/chat-ui/mentions/suggestions/data/sources/index.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/sources/index.d.ts +88 -10
- package/dist/chat-ui/mentions/suggestions/data/sources/index.js +274 -27
- package/dist/chat-ui/mentions/suggestions/data/sources/index.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/types.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/types.d.ts +27 -1
- package/dist/chat-ui/mentions/suggestions/data/types.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.cjs +56 -5
- 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 +26 -6
- package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.js +57 -6
- package/dist/chat-ui/mentions/suggestions/data/use-mention-suggestions.js.map +1 -1
- package/dist/chat-ui/mentions/suggestions/mention-suggestions.extension.cjs +34 -17
- package/dist/chat-ui/mentions/suggestions/mention-suggestions.extension.cjs.map +1 -1
- package/dist/chat-ui/mentions/suggestions/mention-suggestions.extension.d.ts +19 -1
- package/dist/chat-ui/mentions/suggestions/mention-suggestions.extension.js +35 -18
- package/dist/chat-ui/mentions/suggestions/mention-suggestions.extension.js.map +1 -1
- package/dist/chat-ui/mentions/use-asset-icon-app-url.cjs +12 -0
- package/dist/chat-ui/mentions/use-asset-icon-app-url.cjs.map +1 -0
- package/dist/chat-ui/mentions/use-asset-icon-app-url.d.ts +8 -0
- package/dist/chat-ui/mentions/use-asset-icon-app-url.js +12 -0
- package/dist/chat-ui/mentions/use-asset-icon-app-url.js.map +1 -0
- package/dist/chat-ui/statewire.d.ts +1 -1
- package/dist/chat-ui/thread/statewire-history-edge.cjs +15 -0
- package/dist/chat-ui/thread/statewire-history-edge.cjs.map +1 -1
- package/dist/chat-ui/thread/statewire-history-edge.d.ts +4 -1
- package/dist/chat-ui/thread/statewire-history-edge.js +15 -0
- package/dist/chat-ui/thread/statewire-history-edge.js.map +1 -1
- package/dist/collab/client.cjs +41 -6
- package/dist/collab/client.cjs.map +1 -1
- package/dist/collab/client.d.ts +38 -7
- package/dist/collab/client.js +41 -6
- package/dist/collab/client.js.map +1 -1
- package/dist/composer/ComposerAttachedReferences.cjs +119 -0
- package/dist/composer/ComposerAttachedReferences.cjs.map +1 -0
- package/dist/composer/ComposerAttachedReferences.d.ts +26 -0
- package/dist/composer/ComposerAttachedReferences.js +119 -0
- package/dist/composer/ComposerAttachedReferences.js.map +1 -0
- package/dist/composer/ComposerNamedAgents.cjs +63 -0
- package/dist/composer/ComposerNamedAgents.cjs.map +1 -0
- package/dist/composer/ComposerNamedAgents.d.ts +16 -0
- package/dist/composer/ComposerNamedAgents.js +63 -0
- package/dist/composer/ComposerNamedAgents.js.map +1 -0
- package/dist/composer/attached-references.cjs +159 -0
- package/dist/composer/attached-references.cjs.map +1 -0
- package/dist/composer/attached-references.d.ts +86 -0
- package/dist/composer/attached-references.js +159 -0
- package/dist/composer/attached-references.js.map +1 -0
- package/dist/composer/build-composed-message.cjs +14 -7
- package/dist/composer/build-composed-message.cjs.map +1 -1
- package/dist/composer/build-composed-message.d.ts +6 -1
- package/dist/composer/build-composed-message.js +14 -7
- package/dist/composer/build-composed-message.js.map +1 -1
- package/dist/composer/composer-handoff.cjs +6 -2
- package/dist/composer/composer-handoff.cjs.map +1 -1
- package/dist/composer/composer-handoff.d.ts +7 -1
- package/dist/composer/composer-handoff.js +6 -2
- package/dist/composer/composer-handoff.js.map +1 -1
- package/dist/composer/folder-upload.cjs +149 -0
- package/dist/composer/folder-upload.cjs.map +1 -0
- package/dist/composer/folder-upload.d.ts +79 -0
- package/dist/composer/folder-upload.js +149 -0
- package/dist/composer/folder-upload.js.map +1 -0
- package/dist/composer/index.d.ts +1 -1
- package/dist/composer/staged-message-metadata.cjs +12 -0
- package/dist/composer/staged-message-metadata.cjs.map +1 -0
- package/dist/composer/staged-message-metadata.d.ts +15 -0
- package/dist/composer/staged-message-metadata.js +12 -0
- package/dist/composer/staged-message-metadata.js.map +1 -0
- package/dist/composer/useAttachToChat.cjs +35 -0
- package/dist/composer/useAttachToChat.cjs.map +1 -0
- package/dist/composer/useAttachToChat.d.ts +54 -0
- package/dist/composer/useAttachToChat.js +35 -0
- package/dist/composer/useAttachToChat.js.map +1 -0
- package/dist/composer/useAttachedReferencesComposerProps.cjs +19 -0
- package/dist/composer/useAttachedReferencesComposerProps.cjs.map +1 -0
- package/dist/composer/useAttachedReferencesComposerProps.d.ts +12 -0
- package/dist/composer/useAttachedReferencesComposerProps.js +19 -0
- package/dist/composer/useAttachedReferencesComposerProps.js.map +1 -0
- package/dist/composer/useFileUpload.cjs +95 -7
- package/dist/composer/useFileUpload.cjs.map +1 -1
- package/dist/composer/useFileUpload.d.ts +21 -2
- package/dist/composer/useFileUpload.js +95 -7
- package/dist/composer/useFileUpload.js.map +1 -1
- package/dist/data/athena-api-error.cjs +125 -0
- package/dist/data/athena-api-error.cjs.map +1 -0
- package/dist/data/athena-api-error.d.ts +96 -0
- package/dist/data/athena-api-error.js +125 -0
- package/dist/data/athena-api-error.js.map +1 -0
- package/dist/data/athena-data-client.cjs +106 -0
- package/dist/data/athena-data-client.cjs.map +1 -0
- package/dist/data/athena-data-client.d.ts +74 -0
- package/dist/data/athena-data-client.js +106 -0
- package/dist/data/athena-data-client.js.map +1 -0
- package/dist/data/athena-member.cjs +93 -0
- package/dist/data/athena-member.cjs.map +1 -0
- package/dist/data/athena-member.d.ts +125 -0
- package/dist/data/athena-member.js +93 -0
- package/dist/data/athena-member.js.map +1 -0
- package/dist/data/athena-request.cjs +460 -0
- package/dist/data/athena-request.cjs.map +1 -0
- package/dist/data/athena-request.d.ts +120 -0
- package/dist/data/athena-request.js +460 -0
- package/dist/data/athena-request.js.map +1 -0
- package/dist/data/use-athena-fetch.cjs +14 -0
- package/dist/data/use-athena-fetch.cjs.map +1 -0
- package/dist/data/use-athena-fetch.d.ts +19 -0
- package/dist/data/use-athena-fetch.js +14 -0
- package/dist/data/use-athena-fetch.js.map +1 -0
- package/dist/data/use-athena-graphql.cjs +66 -0
- package/dist/data/use-athena-graphql.cjs.map +1 -0
- package/dist/data/use-athena-graphql.d.ts +56 -0
- package/dist/data/use-athena-graphql.js +66 -0
- package/dist/data/use-athena-graphql.js.map +1 -0
- package/dist/data/use-athena-rest.cjs +33 -0
- package/dist/data/use-athena-rest.cjs.map +1 -0
- package/dist/data/use-athena-rest.d.ts +21 -0
- package/dist/data/use-athena-rest.js +33 -0
- package/dist/data/use-athena-rest.js.map +1 -0
- package/dist/data/use-semantic-query.cjs +44 -0
- package/dist/data/use-semantic-query.cjs.map +1 -0
- package/dist/data/use-semantic-query.d.ts +92 -0
- package/dist/data/use-semantic-query.js +44 -0
- package/dist/data/use-semantic-query.js.map +1 -0
- package/dist/diagnostics/athena-diagnostics.cjs.map +1 -1
- package/dist/diagnostics/athena-diagnostics.d.ts +5 -1
- package/dist/diagnostics/athena-diagnostics.js.map +1 -1
- package/dist/diagnostics/errors.cjs +7 -0
- package/dist/diagnostics/errors.cjs.map +1 -1
- package/dist/diagnostics/errors.d.ts +7 -0
- package/dist/diagnostics/errors.js +7 -0
- package/dist/diagnostics/errors.js.map +1 -1
- package/dist/index.cjs +155 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +72 -13
- package/dist/index.js +148 -4
- package/dist/index.js.map +1 -1
- package/dist/keryx-http/src/initial-sync.cjs +64 -16
- package/dist/keryx-http/src/initial-sync.cjs.map +1 -1
- package/dist/keryx-http/src/initial-sync.d.ts +31 -1
- package/dist/keryx-http/src/initial-sync.js +64 -16
- package/dist/keryx-http/src/initial-sync.js.map +1 -1
- package/dist/keryx-http/src/own-awareness.cjs +20 -0
- package/dist/keryx-http/src/own-awareness.cjs.map +1 -0
- package/dist/keryx-http/src/own-awareness.d.ts +50 -0
- package/dist/keryx-http/src/own-awareness.js +20 -0
- package/dist/keryx-http/src/own-awareness.js.map +1 -0
- package/dist/keryx-http/src/update-attributions.cjs +26 -1
- package/dist/keryx-http/src/update-attributions.cjs.map +1 -1
- package/dist/keryx-http/src/update-attributions.d.ts +10 -1
- package/dist/keryx-http/src/update-attributions.js +26 -1
- package/dist/keryx-http/src/update-attributions.js.map +1 -1
- package/dist/offline/chat-outbox.cjs +262 -26
- package/dist/offline/chat-outbox.cjs.map +1 -1
- package/dist/offline/chat-outbox.d.ts +90 -12
- package/dist/offline/chat-outbox.js +263 -27
- package/dist/offline/chat-outbox.js.map +1 -1
- package/dist/provider/AthenaProvider.cjs +60 -22
- package/dist/provider/AthenaProvider.cjs.map +1 -1
- package/dist/provider/AthenaProvider.d.ts +24 -8
- package/dist/provider/AthenaProvider.js +61 -23
- package/dist/provider/AthenaProvider.js.map +1 -1
- package/dist/react/package.json.cjs +1 -1
- package/dist/react/package.json.js +1 -1
- package/dist/references/src/anchors/parse.cjs +11 -1
- package/dist/references/src/anchors/parse.cjs.map +1 -1
- package/dist/references/src/anchors/parse.js +11 -1
- package/dist/references/src/anchors/parse.js.map +1 -1
- package/dist/references/src/anchors/schemas.d.ts +1 -0
- package/dist/references/src/anchors/serialize.cjs +1 -0
- package/dist/references/src/anchors/serialize.cjs.map +1 -1
- package/dist/references/src/anchors/serialize.js +1 -0
- package/dist/references/src/anchors/serialize.js.map +1 -1
- package/dist/references/src/anchors/types.cjs +5 -0
- package/dist/references/src/anchors/types.cjs.map +1 -1
- package/dist/references/src/anchors/types.d.ts +9 -0
- package/dist/references/src/anchors/types.js +5 -0
- package/dist/references/src/anchors/types.js.map +1 -1
- package/dist/references/src/attachable.cjs +149 -0
- package/dist/references/src/attachable.cjs.map +1 -0
- package/dist/references/src/attachable.d.ts +87 -0
- package/dist/references/src/attachable.js +149 -0
- package/dist/references/src/attachable.js.map +1 -0
- package/dist/references/src/schemas.d.ts +2 -0
- package/dist/runtime/StatewirePlanModeLaneSync.cjs +93 -0
- package/dist/runtime/StatewirePlanModeLaneSync.cjs.map +1 -0
- package/dist/runtime/StatewirePlanModeLaneSync.d.ts +34 -0
- package/dist/runtime/StatewirePlanModeLaneSync.js +93 -0
- package/dist/runtime/StatewirePlanModeLaneSync.js.map +1 -0
- package/dist/runtime/StatewireThreadConfigLaneSync.cjs +2 -0
- package/dist/runtime/StatewireThreadConfigLaneSync.cjs.map +1 -1
- package/dist/runtime/StatewireThreadConfigLaneSync.d.ts +4 -0
- package/dist/runtime/StatewireThreadConfigLaneSync.js +2 -0
- package/dist/runtime/StatewireThreadConfigLaneSync.js.map +1 -1
- package/dist/runtime/statewire-plan-mode.cjs +71 -0
- package/dist/runtime/statewire-plan-mode.cjs.map +1 -0
- package/dist/runtime/statewire-plan-mode.d.ts +88 -0
- package/dist/runtime/statewire-plan-mode.js +71 -0
- package/dist/runtime/statewire-plan-mode.js.map +1 -0
- package/dist/runtime/statewire-run-config.cjs +3 -1
- package/dist/runtime/statewire-run-config.cjs.map +1 -1
- package/dist/runtime/statewire-run-config.d.ts +7 -0
- package/dist/runtime/statewire-run-config.js +3 -1
- package/dist/runtime/statewire-run-config.js.map +1 -1
- package/dist/runtime/statewire-session-key.cjs +11 -5
- package/dist/runtime/statewire-session-key.cjs.map +1 -1
- package/dist/runtime/statewire-session-key.d.ts +22 -10
- package/dist/runtime/statewire-session-key.js +11 -5
- package/dist/runtime/statewire-session-key.js.map +1 -1
- package/dist/runtime/useAthenaStatewireRuntime.cjs +64 -9
- package/dist/runtime/useAthenaStatewireRuntime.cjs.map +1 -1
- package/dist/runtime/useAthenaStatewireRuntime.d.ts +26 -10
- package/dist/runtime/useAthenaStatewireRuntime.js +66 -11
- package/dist/runtime/useAthenaStatewireRuntime.js.map +1 -1
- package/dist/search/useAthenaAssets.cjs +394 -0
- package/dist/search/useAthenaAssets.cjs.map +1 -0
- package/dist/search/useAthenaAssets.d.ts +186 -0
- package/dist/search/useAthenaAssets.js +394 -0
- package/dist/search/useAthenaAssets.js.map +1 -0
- package/dist/sheet-range/index.cjs +4 -0
- package/dist/sheet-range/index.cjs.map +1 -1
- package/dist/sheet-range/index.d.ts +4 -2
- package/dist/sheet-range/index.js +4 -0
- package/dist/sheet-range/index.js.map +1 -1
- package/dist/sheet-range/query-range.cjs +102 -0
- package/dist/sheet-range/query-range.cjs.map +1 -0
- package/dist/sheet-range/query-range.d.ts +46 -0
- package/dist/sheet-range/query-range.js +102 -0
- package/dist/sheet-range/query-range.js.map +1 -0
- package/dist/styles.css +1 -1
- package/dist/subagents/index.cjs +49 -0
- package/dist/subagents/index.cjs.map +1 -0
- package/dist/subagents/index.d.ts +16 -0
- package/dist/subagents/index.js +49 -0
- package/dist/subagents/index.js.map +1 -0
- package/dist/subagents/lane-follow.cjs +19 -0
- package/dist/subagents/lane-follow.cjs.map +1 -0
- package/dist/subagents/lane-follow.d.ts +9 -0
- package/dist/subagents/lane-follow.js +19 -0
- package/dist/subagents/lane-follow.js.map +1 -0
- package/dist/subagents/lane-model.cjs +178 -0
- package/dist/subagents/lane-model.cjs.map +1 -0
- package/dist/subagents/lane-model.d.ts +140 -0
- package/dist/subagents/lane-model.js +178 -0
- package/dist/subagents/lane-model.js.map +1 -0
- package/dist/subagents/lane-parts.cjs +517 -0
- package/dist/subagents/lane-parts.cjs.map +1 -0
- package/dist/subagents/lane-parts.d.ts +130 -0
- package/dist/subagents/lane-parts.js +517 -0
- package/dist/subagents/lane-parts.js.map +1 -0
- package/dist/subagents/subagent-lane-group.cjs +215 -0
- package/dist/subagents/subagent-lane-group.cjs.map +1 -0
- package/dist/subagents/subagent-lane-group.d.ts +67 -0
- package/dist/subagents/subagent-lane-group.js +215 -0
- package/dist/subagents/subagent-lane-group.js.map +1 -0
- package/dist/subagents/subagent-transcript-drawer.cjs +431 -0
- package/dist/subagents/subagent-transcript-drawer.cjs.map +1 -0
- package/dist/subagents/subagent-transcript-drawer.d.ts +78 -0
- package/dist/subagents/subagent-transcript-drawer.js +431 -0
- package/dist/subagents/subagent-transcript-drawer.js.map +1 -0
- package/dist/subagents/task-subagent-group.cjs +115 -0
- package/dist/subagents/task-subagent-group.cjs.map +1 -0
- package/dist/subagents/task-subagent-group.d.ts +36 -0
- package/dist/subagents/task-subagent-group.js +115 -0
- package/dist/subagents/task-subagent-group.js.map +1 -0
- package/dist/subagents/use-omitted-images-in-view.cjs +68 -0
- package/dist/subagents/use-omitted-images-in-view.cjs.map +1 -0
- package/dist/subagents/use-omitted-images-in-view.d.ts +21 -0
- package/dist/subagents/use-omitted-images-in-view.js +68 -0
- package/dist/subagents/use-omitted-images-in-view.js.map +1 -0
- package/dist/threads/Inbox.cjs +2 -2
- package/dist/threads/Inbox.cjs.map +1 -1
- package/dist/threads/SessionList.cjs +6 -6
- package/dist/threads/SessionList.cjs.map +1 -1
- package/dist/threads/SessionsPage.cjs +13 -7
- package/dist/threads/SessionsPage.cjs.map +1 -1
- package/dist/threads/SessionsPage.d.ts +10 -1
- package/dist/threads/SessionsPage.js +9 -3
- package/dist/threads/SessionsPage.js.map +1 -1
- package/dist/threads/session-list-model.cjs.map +1 -1
- package/dist/threads/session-list-model.d.ts +2 -1
- package/dist/threads/session-list-model.js.map +1 -1
- package/dist/threads/session-row-parts.cjs +3 -3
- package/dist/threads/session-row-parts.cjs.map +1 -1
- package/dist/threads/sessions-page-model.cjs +13 -5
- package/dist/threads/sessions-page-model.cjs.map +1 -1
- package/dist/threads/sessions-page-model.d.ts +7 -0
- package/dist/threads/sessions-page-model.js +11 -3
- package/dist/threads/sessions-page-model.js.map +1 -1
- package/dist/threads/sessions-page-storage.cjs +8 -8
- package/dist/threads/sessions-page-storage.cjs.map +1 -1
- package/dist/threads/sessions-page-storage.d.ts +5 -1
- package/dist/threads/sessions-page-storage.js +8 -8
- package/dist/threads/sessions-page-storage.js.map +1 -1
- package/dist/threads/statewire-thread-list.cjs +14 -2
- package/dist/threads/statewire-thread-list.cjs.map +1 -1
- package/dist/threads/statewire-thread-list.d.ts +11 -2
- package/dist/threads/statewire-thread-list.js +14 -2
- package/dist/threads/statewire-thread-list.js.map +1 -1
- package/dist/threads/use-athena-sessions.cjs +1 -0
- package/dist/threads/use-athena-sessions.cjs.map +1 -1
- package/dist/threads/use-athena-sessions.d.ts +7 -0
- package/dist/threads/use-athena-sessions.js +1 -0
- package/dist/threads/use-athena-sessions.js.map +1 -1
- package/dist/threads/use-athena-thread-agent.cjs +31 -0
- package/dist/threads/use-athena-thread-agent.cjs.map +1 -0
- package/dist/threads/use-athena-thread-agent.d.ts +38 -0
- package/dist/threads/use-athena-thread-agent.js +31 -0
- package/dist/threads/use-athena-thread-agent.js.map +1 -0
- package/dist/threads/use-athena-thread-plan-mode.cjs +18 -0
- package/dist/threads/use-athena-thread-plan-mode.cjs.map +1 -0
- package/dist/threads/use-athena-thread-plan-mode.d.ts +18 -0
- package/dist/threads/use-athena-thread-plan-mode.js +18 -0
- package/dist/threads/use-athena-thread-plan-mode.js.map +1 -0
- package/dist/threads/use-rest-conversation-history.d.ts +1 -0
- package/dist/tools/agent-creations.cjs +97 -0
- package/dist/tools/agent-creations.cjs.map +1 -0
- package/dist/tools/agent-creations.d.ts +38 -0
- package/dist/tools/agent-creations.js +97 -0
- package/dist/tools/agent-creations.js.map +1 -0
- package/dist/tools/agent-highlights.cjs +100 -0
- package/dist/tools/agent-highlights.cjs.map +1 -0
- package/dist/tools/agent-highlights.d.ts +57 -0
- package/dist/tools/agent-highlights.js +100 -0
- package/dist/tools/agent-highlights.js.map +1 -0
- package/dist/tools/append-document-tool-ui.cjs +1 -0
- package/dist/tools/append-document-tool-ui.cjs.map +1 -1
- package/dist/tools/append-document-tool-ui.d.ts +7 -0
- package/dist/tools/append-document-tool-ui.js +2 -1
- package/dist/tools/append-document-tool-ui.js.map +1 -1
- package/dist/tools/auto-open-tools.cjs +144 -71
- package/dist/tools/auto-open-tools.cjs.map +1 -1
- package/dist/tools/auto-open-tools.d.ts +131 -1
- package/dist/tools/auto-open-tools.js +145 -72
- package/dist/tools/auto-open-tools.js.map +1 -1
- package/dist/tools/browser-tool-uis.cjs +594 -0
- package/dist/tools/browser-tool-uis.cjs.map +1 -0
- package/dist/tools/browser-tool-uis.d.ts +8 -0
- package/dist/tools/browser-tool-uis.js +594 -0
- package/dist/tools/browser-tool-uis.js.map +1 -0
- package/dist/tools/computer-asset-tool-uis.cjs +313 -0
- package/dist/tools/computer-asset-tool-uis.cjs.map +1 -0
- package/dist/tools/computer-asset-tool-uis.d.ts +5 -0
- package/dist/tools/computer-asset-tool-uis.js +313 -0
- package/dist/tools/computer-asset-tool-uis.js.map +1 -0
- package/dist/tools/document-edit-tool-uis.cjs +218 -0
- package/dist/tools/document-edit-tool-uis.cjs.map +1 -0
- package/dist/tools/document-edit-tool-uis.d.ts +40 -0
- package/dist/tools/document-edit-tool-uis.js +218 -0
- package/dist/tools/document-edit-tool-uis.js.map +1 -0
- package/dist/tools/drive-tool-uis.cjs +429 -0
- package/dist/tools/drive-tool-uis.cjs.map +1 -0
- package/dist/tools/drive-tool-uis.d.ts +121 -0
- package/dist/tools/drive-tool-uis.js +429 -0
- package/dist/tools/drive-tool-uis.js.map +1 -0
- package/dist/tools/email-calendar-tool-uis.cjs +789 -0
- package/dist/tools/email-calendar-tool-uis.cjs.map +1 -0
- package/dist/tools/email-calendar-tool-uis.d.ts +129 -0
- package/dist/tools/email-calendar-tool-uis.js +789 -0
- package/dist/tools/email-calendar-tool-uis.js.map +1 -0
- package/dist/tools/ontology-tool-uis.cjs +83 -0
- package/dist/tools/ontology-tool-uis.cjs.map +1 -0
- package/dist/tools/ontology-tool-uis.d.ts +9 -0
- package/dist/tools/ontology-tool-uis.js +83 -0
- package/dist/tools/ontology-tool-uis.js.map +1 -0
- package/dist/tools/orchestration-tool-uis.cjs +586 -0
- package/dist/tools/orchestration-tool-uis.cjs.map +1 -0
- package/dist/tools/orchestration-tool-uis.d.ts +141 -0
- package/dist/tools/orchestration-tool-uis.js +586 -0
- package/dist/tools/orchestration-tool-uis.js.map +1 -0
- package/dist/tools/presentation-edit-tool-uis.cjs +516 -0
- package/dist/tools/presentation-edit-tool-uis.cjs.map +1 -0
- package/dist/tools/presentation-edit-tool-uis.d.ts +73 -0
- package/dist/tools/presentation-edit-tool-uis.js +516 -0
- package/dist/tools/presentation-edit-tool-uis.js.map +1 -0
- package/dist/tools/project-tool-uis.cjs +213 -0
- package/dist/tools/project-tool-uis.cjs.map +1 -0
- package/dist/tools/project-tool-uis.d.ts +14 -0
- package/dist/tools/project-tool-uis.js +213 -0
- package/dist/tools/project-tool-uis.js.map +1 -0
- package/dist/tools/sandbox-tool-uis.cjs +491 -0
- package/dist/tools/sandbox-tool-uis.cjs.map +1 -0
- package/dist/tools/sandbox-tool-uis.d.ts +116 -0
- package/dist/tools/sandbox-tool-uis.js +491 -0
- package/dist/tools/sandbox-tool-uis.js.map +1 -0
- package/dist/tools/sheet-query-tool-ui.cjs +138 -0
- package/dist/tools/sheet-query-tool-ui.cjs.map +1 -0
- package/dist/tools/sheet-query-tool-ui.d.ts +15 -0
- package/dist/tools/sheet-query-tool-ui.js +138 -0
- package/dist/tools/sheet-query-tool-ui.js.map +1 -0
- package/dist/tools/studio-screenshot-tool-uis.cjs +262 -0
- package/dist/tools/studio-screenshot-tool-uis.cjs.map +1 -0
- package/dist/tools/studio-screenshot-tool-uis.d.ts +52 -0
- package/dist/tools/studio-screenshot-tool-uis.js +262 -0
- package/dist/tools/studio-screenshot-tool-uis.js.map +1 -0
- package/dist/tools/subagent-task-tool-ui.cjs +24 -475
- package/dist/tools/subagent-task-tool-ui.cjs.map +1 -1
- package/dist/tools/subagent-task-tool-ui.d.ts +19 -103
- package/dist/tools/subagent-task-tool-ui.js +28 -479
- package/dist/tools/subagent-task-tool-ui.js.map +1 -1
- package/dist/tools/tool-summary.cjs +36 -0
- package/dist/tools/tool-summary.cjs.map +1 -1
- package/dist/tools/tool-summary.js +36 -0
- package/dist/tools/tool-summary.js.map +1 -1
- package/dist/tools/tool-uis.cjs +181 -53
- package/dist/tools/tool-uis.cjs.map +1 -1
- package/dist/tools/tool-uis.d.ts +40 -0
- package/dist/tools/tool-uis.js +183 -55
- package/dist/tools/tool-uis.js.map +1 -1
- package/dist/typed-interrupts/index.cjs +15 -0
- package/dist/typed-interrupts/index.cjs.map +1 -0
- package/dist/typed-interrupts/index.d.ts +20 -0
- package/dist/typed-interrupts/index.js +15 -0
- package/dist/typed-interrupts/index.js.map +1 -0
- package/dist/version.cjs +4 -0
- package/dist/version.cjs.map +1 -1
- package/dist/version.d.ts +9 -0
- package/dist/version.js +4 -0
- package/dist/version.js.map +1 -1
- package/dist/workbench/live-desktop-api.cjs +2 -1
- package/dist/workbench/live-desktop-api.cjs.map +1 -1
- package/dist/workbench/live-desktop-api.js +2 -1
- package/dist/workbench/live-desktop-api.js.map +1 -1
- package/dist/workbench/session-workbench-panes.cjs +6 -6
- package/dist/workbench/session-workbench-panes.cjs.map +1 -1
- package/dist/workbench/session-workspace-api.cjs +7 -2
- package/dist/workbench/session-workspace-api.cjs.map +1 -1
- package/dist/workbench/session-workspace-api.d.ts +10 -0
- package/dist/workbench/session-workspace-api.js +7 -2
- package/dist/workbench/session-workspace-api.js.map +1 -1
- package/package.json +28 -6
- package/dist/agent-runtime/src/chat-outbox-store.cjs +0 -510
- package/dist/agent-runtime/src/chat-outbox-store.cjs.map +0 -1
- package/dist/agent-runtime/src/chat-outbox-store.d.ts +0 -210
- package/dist/agent-runtime/src/chat-outbox-store.js +0 -510
- package/dist/agent-runtime/src/chat-outbox-store.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SessionsPage.js","sources":["../../src/threads/SessionsPage.tsx"],"sourcesContent":["/**\n * `SessionsPage` — a full-page, Devin-style session list: filter chips that\n * the server applies (status, pull requests, unread, pinned, creator, agent,\n * mode, origin, created / updated date), a title search, display options\n * (sort, direction, grouping, columns), an attention-coloured status column\n * that says what the person must do next, row actions (read, pin, archive)\n * and a CSV export of the loaded rows. Live through the thread-list\n * provider's conversation index; renders nothing outside\n * `<AthenaProvider enableThreadList>`.\n */\nimport {\n ArchiveIcon,\n CheckIcon,\n DownloadIcon,\n FilterIcon,\n MailIcon,\n MailOpenIcon,\n PinIcon,\n PlusIcon,\n RefreshCwIcon,\n SearchIcon,\n SlidersHorizontalIcon,\n XIcon,\n} from 'lucide-react';\nimport type { FC, ReactNode } from 'react';\nimport { useContext, useEffect, useMemo, useRef, useState } from 'react';\nimport { cn } from '../lib/utils';\nimport { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';\nimport { SessionListSkeleton, type SessionOpenTarget } from './SessionList';\nimport { pullRequestChip, relativeTime, sessionOriginLabel } from './session-list-model';\nimport { FOCUS_RING_CLASS, PullRequestChip, RowIconButton, StatusChip } from './session-row-parts';\nimport {\n agentLabel,\n channelLabel,\n creatorLabel,\n datePresetBounds,\n groupSessionsBy,\n runStatusLabel,\n SESSIONS_COLUMNS,\n SESSIONS_DATE_PRESETS,\n type SessionsColumnId,\n type SessionsDatePreset,\n type SessionsGroupBy,\n type SessionsLabels,\n sessionsCsv,\n sessionsFilterChips,\n plainExcerpt,\n sessionStatusChip,\n} from './sessions-page-model';\nimport {\n readSessionsPageSettings,\n type SessionsPageDisplay,\n writeSessionsPageSettings,\n} from './sessions-page-storage';\nimport {\n type AthenaSessionsQuery,\n type AthenaSessionsQueryField,\n DEFAULT_COLLAB_CHANNEL,\n normalizeSessionsQuery,\n SESSION_RUN_STATUSES,\n type SessionRunStatus,\n sessionsQueryKey,\n} from './sessions-query';\nimport {\n AthenaSessionsLiveContext,\n type AthenaStatewireThreadListState,\n type AthenaStatewireThreadSummary,\n useAthenaStatewireThreadList,\n} from './statewire-thread-list';\nimport { useAthenaSessions } from './use-athena-sessions';\n\nexport interface SessionsPageProps {\n className?: string;\n /** Heading (default \"Sessions\"). */\n title?: string;\n /**\n * Called after a row is selected (the provider's chat switches to it), so\n * a host can navigate to its chat view.\n */\n onOpenSession?: (target: SessionOpenTarget) => void;\n /** Names for collab agents and channels (filters, the Mode column, CSV); ids show otherwise. */\n labels?: SessionsLabels;\n /**\n * Namespaces what this browser remembers — \"Save as default\" and the\n * display options — so a host with several pages keeps them apart\n * (default `\"default\"`).\n */\n storageKey?: string;\n /** The filters before anything is saved as default. */\n defaultQuery?: AthenaSessionsQuery;\n /** Rows per page (default 50). */\n pageSize?: number;\n /** Offer \"New session\" (default `true`). */\n showNewSession?: boolean;\n /** Called after \"New session\" starts a fresh chat, so a host can show its chat view. */\n onNewSession?: () => void;\n}\n\n/** What each query field is called in notices. */\nconst FIELD_LABEL: Record<AthenaSessionsQueryField, string> = {\n search: 'search',\n collabAgentIds: 'agent',\n collabChannelIds: 'mode',\n startChannels: 'origin',\n createdAfter: 'created date',\n createdBefore: 'created date',\n updatedAfter: 'updated date',\n updatedBefore: 'updated date',\n favoritesOnly: 'pinned',\n unreadOnly: 'unread',\n runStatuses: 'status',\n sessionStatuses: 'session status',\n hasPullRequests: 'pull requests',\n createdByMe: 'creator',\n excludeDismissed: 'dismissed',\n excludeTriggered: 'who started it',\n sort: 'sort',\n direction: 'sort direction',\n};\n\n/** \"agent\", \"agent and mode\", \"agent, mode and unread\". */\nfunction fieldList(fields: readonly AthenaSessionsQueryField[]): string {\n const names = [...new Set(fields.map((field) => FIELD_LABEL[field]))];\n return names.length <= 1 ? (names[0] ?? '') : `${names.slice(0, -1).join(', ')} and ${names.at(-1)}`;\n}\n\nconst COLUMN_WIDTH: Record<SessionsColumnId, string> = {\n status: 'w-56',\n origin: 'w-24',\n mode: 'w-28',\n pullRequests: 'w-24',\n creator: 'w-32',\n created: 'w-24',\n updated: 'w-24',\n};\n\n/** Save `text` as a file in the browser. */\nfunction downloadText(filename: string, text: string, type: string): void {\n if (typeof document === 'undefined') return;\n const url = URL.createObjectURL(new Blob([text], { type }));\n const anchor = document.createElement('a');\n anchor.href = url;\n anchor.download = filename;\n anchor.rel = 'noopener';\n document.body.appendChild(anchor);\n anchor.click();\n anchor.remove();\n setTimeout(() => URL.revokeObjectURL(url), 0);\n}\n\nconst SECTION_HEADING_CLASS =\n 'px-3 pb-1 pt-3 text-left font-medium text-[11px] text-muted-foreground/70 uppercase tracking-wide';\n\n/** A pressable option in a filter or display menu. */\nconst MenuOption: FC<{\n label: string;\n selected: boolean;\n onSelect: () => void;\n disabled?: boolean;\n role?: 'menuitemcheckbox' | 'menuitemradio';\n}> = ({ label, selected, onSelect, disabled = false, role = 'menuitemcheckbox' }) => (\n <button\n type=\"button\"\n role={role}\n aria-checked={selected}\n disabled={disabled}\n onClick={onSelect}\n className={cn(\n 'flex w-full items-center gap-2 rounded-sm px-2 py-1 text-left text-xs transition-colors hover:bg-muted disabled:cursor-not-allowed disabled:opacity-50',\n FOCUS_RING_CLASS,\n )}\n >\n <span\n aria-hidden=\"true\"\n className={cn(\n 'flex size-3.5 shrink-0 items-center justify-center rounded-sm border border-border',\n selected && 'border-primary bg-primary text-primary-foreground',\n )}\n >\n {selected ? <CheckIcon className=\"size-3\" /> : null}\n </span>\n <span className=\"truncate\">{label}</span>\n </button>\n);\n\nconst MenuSection: FC<{ title: string; hint?: string | null; children: ReactNode }> = ({\n title,\n hint,\n children,\n}) => (\n <section aria-label={title} className=\"py-1\">\n <h4 className=\"px-2 pb-0.5 font-medium text-[11px] text-muted-foreground uppercase tracking-wide\">\n {title}\n </h4>\n {hint ? <p className=\"px-2 pb-1 text-[11px] text-muted-foreground\">{hint}</p> : null}\n {children}\n </section>\n);\n\nfunction toggleValue<T extends string>(values: readonly T[] | undefined, value: T): T[] {\n const current = values ?? [];\n return current.includes(value) ? current.filter((item) => item !== value) : [...current, value];\n}\n\nfunction datePresetOf(after: string | undefined, before: string | undefined, presets: Record<SessionsDatePreset, { after?: string; before?: string }>): SessionsDatePreset | null {\n for (const preset of SESSIONS_DATE_PRESETS) {\n const bounds = presets[preset.id];\n if ((bounds.after ?? undefined) === after && (bounds.before ?? undefined) === before) {\n return preset.id;\n }\n }\n return null;\n}\n\ninterface FilterMenuProps {\n query: AthenaSessionsQuery;\n setQuery: (update: (query: AthenaSessionsQuery) => AthenaSessionsQuery) => void;\n unavailable: ReadonlySet<AthenaSessionsQueryField>;\n agentOptions: readonly string[];\n channelOptions: readonly string[];\n originOptions: readonly string[];\n labels: SessionsLabels | undefined;\n}\n\nconst UNAVAILABLE_HINT = 'This Athena server cannot filter by this yet.';\n\n/** Every filter, stacked by kind; each option toggles at once. */\nconst FilterMenu: FC<FilterMenuProps> = ({\n query,\n setQuery,\n unavailable,\n agentOptions,\n channelOptions,\n originOptions,\n labels,\n}) => {\n // The presets' bounds are captured when the menu opens, so a selected\n // preset stays recognisable while it is open.\n const [presetBounds] = useState(() =>\n Object.fromEntries(\n SESSIONS_DATE_PRESETS.map((preset) => [preset.id, datePresetBounds(preset.id)]),\n ) as Record<SessionsDatePreset, { after?: string; before?: string }>,\n );\n const createdPreset = datePresetOf(query.createdAfter, query.createdBefore, presetBounds);\n const updatedPreset = datePresetOf(query.updatedAfter, query.updatedBefore, presetBounds);\n const setPreset = (\n kind: 'created' | 'updated',\n preset: SessionsDatePreset | null,\n ) =>\n setQuery((current) => {\n const bounds = preset ? presetBounds[preset] : {};\n return kind === 'created'\n ? { ...current, createdAfter: bounds.after, createdBefore: bounds.before }\n : { ...current, updatedAfter: bounds.after, updatedBefore: bounds.before };\n });\n const disabledHint = (field: AthenaSessionsQueryField) =>\n unavailable.has(field) ? UNAVAILABLE_HINT : null;\n\n return (\n <div role=\"menu\" aria-label=\"Filters\" className=\"max-h-[70vh] overflow-y-auto p-1\">\n <MenuSection title=\"Status\" hint={disabledHint('runStatuses')}>\n {SESSION_RUN_STATUSES.map((status) => (\n <MenuOption\n key={status}\n label={runStatusLabel(status)}\n selected={query.runStatuses?.includes(status) ?? false}\n disabled={unavailable.has('runStatuses')}\n onSelect={() =>\n setQuery((current) => ({\n ...current,\n runStatuses: toggleValue<SessionRunStatus>(current.runStatuses, status),\n }))\n }\n />\n ))}\n </MenuSection>\n <MenuSection title=\"Pull requests\" hint={disabledHint('hasPullRequests')}>\n {(\n [\n ['Has pull requests', true],\n ['No pull requests', false],\n ] as const\n ).map(([label, value]) => (\n <MenuOption\n key={label}\n role=\"menuitemradio\"\n label={label}\n selected={query.hasPullRequests === value}\n disabled={unavailable.has('hasPullRequests')}\n onSelect={() =>\n setQuery((current) => ({\n ...current,\n hasPullRequests: current.hasPullRequests === value ? undefined : value,\n }))\n }\n />\n ))}\n </MenuSection>\n <MenuSection title=\"Read and pinned\">\n <MenuOption\n label=\"Unread\"\n selected={query.unreadOnly === true}\n disabled={unavailable.has('unreadOnly')}\n onSelect={() => setQuery((current) => ({ ...current, unreadOnly: !current.unreadOnly }))}\n />\n <MenuOption\n label=\"Pinned\"\n selected={query.favoritesOnly === true}\n disabled={unavailable.has('favoritesOnly')}\n onSelect={() =>\n setQuery((current) => ({ ...current, favoritesOnly: !current.favoritesOnly }))\n }\n />\n </MenuSection>\n <MenuSection title=\"Creator\" hint={disabledHint('createdByMe')}>\n {(\n [\n ['You', true],\n ['Shared with you', false],\n ] as const\n ).map(([label, value]) => (\n <MenuOption\n key={label}\n role=\"menuitemradio\"\n label={label}\n selected={query.createdByMe === value}\n disabled={unavailable.has('createdByMe')}\n onSelect={() =>\n setQuery((current) => ({\n ...current,\n createdByMe: current.createdByMe === value ? undefined : value,\n }))\n }\n />\n ))}\n <MenuOption\n label=\"Started by a person\"\n selected={query.excludeTriggered === true}\n onSelect={() =>\n setQuery((current) => ({ ...current, excludeTriggered: !current.excludeTriggered }))\n }\n />\n </MenuSection>\n {agentOptions.length > 0 ? (\n <MenuSection title=\"Agent\" hint={disabledHint('collabAgentIds')}>\n {agentOptions.map((agentId) => (\n <MenuOption\n key={agentId}\n label={agentLabel(agentId, labels)}\n selected={query.collabAgentIds?.includes(agentId) ?? false}\n disabled={unavailable.has('collabAgentIds')}\n onSelect={() =>\n setQuery((current) => ({\n ...current,\n collabAgentIds: toggleValue(current.collabAgentIds, agentId),\n }))\n }\n />\n ))}\n </MenuSection>\n ) : null}\n {agentOptions.length > 0 ? (\n <MenuSection\n title=\"Mode\"\n hint={\n disabledHint('collabChannelIds') ??\n (query.collabAgentIds?.length ? null : 'Pick an agent first: a mode is one of its channels.')\n }\n >\n {channelOptions.map((channelId) => (\n <MenuOption\n key={channelId}\n label={channelLabel(channelId, labels)}\n selected={query.collabChannelIds?.includes(channelId) ?? false}\n disabled={unavailable.has('collabChannelIds') || !query.collabAgentIds?.length}\n onSelect={() =>\n setQuery((current) => ({\n ...current,\n collabChannelIds: toggleValue(current.collabChannelIds, channelId),\n }))\n }\n />\n ))}\n </MenuSection>\n ) : null}\n {originOptions.length > 0 ? (\n <MenuSection title=\"Origin\" hint={disabledHint('startChannels')}>\n {originOptions.map((channel) => (\n <MenuOption\n key={channel}\n label={sessionOriginLabel({ startChannel: channel, appId: null, triggerType: null }) ?? channel}\n selected={query.startChannels?.includes(channel) ?? false}\n disabled={unavailable.has('startChannels')}\n onSelect={() =>\n setQuery((current) => ({\n ...current,\n startChannels: toggleValue(current.startChannels, channel),\n }))\n }\n />\n ))}\n </MenuSection>\n ) : null}\n <MenuSection title=\"Created\">\n {SESSIONS_DATE_PRESETS.map((preset) => (\n <MenuOption\n key={preset.id}\n role=\"menuitemradio\"\n label={preset.label}\n selected={createdPreset === preset.id}\n onSelect={() => setPreset('created', createdPreset === preset.id ? null : preset.id)}\n />\n ))}\n </MenuSection>\n <MenuSection title=\"Updated\">\n {SESSIONS_DATE_PRESETS.map((preset) => (\n <MenuOption\n key={preset.id}\n role=\"menuitemradio\"\n label={preset.label}\n selected={updatedPreset === preset.id}\n onSelect={() => setPreset('updated', updatedPreset === preset.id ? null : preset.id)}\n />\n ))}\n </MenuSection>\n </div>\n );\n};\n\nconst DisplayMenu: FC<{\n query: AthenaSessionsQuery;\n setQuery: (update: (query: AthenaSessionsQuery) => AthenaSessionsQuery) => void;\n display: SessionsPageDisplay;\n setDisplay: (update: (display: SessionsPageDisplay) => SessionsPageDisplay) => void;\n}> = ({ query, setQuery, display, setDisplay }) => {\n const sort = query.sort ?? 'updated';\n const direction = query.direction ?? 'desc';\n return (\n <div role=\"menu\" aria-label=\"Display options\" className=\"p-1\">\n <MenuSection title=\"Sort by\">\n {(\n [\n ['updated', 'Last updated'],\n ['created', 'Created'],\n ] as const\n ).map(([value, label]) => (\n <MenuOption\n key={value}\n role=\"menuitemradio\"\n label={label}\n selected={sort === value}\n onSelect={() => setQuery((current) => ({ ...current, sort: value }))}\n />\n ))}\n </MenuSection>\n <MenuSection title=\"Order\">\n {(\n [\n ['desc', 'Newest first'],\n ['asc', 'Oldest first'],\n ] as const\n ).map(([value, label]) => (\n <MenuOption\n key={value}\n role=\"menuitemradio\"\n label={label}\n selected={direction === value}\n onSelect={() => setQuery((current) => ({ ...current, direction: value }))}\n />\n ))}\n </MenuSection>\n <MenuSection title=\"Group by\">\n {(\n [\n ['attention', 'What it needs'],\n ['status', 'Run status'],\n ['none', 'No grouping'],\n ] as const\n ).map(([value, label]) => (\n <MenuOption\n key={value}\n role=\"menuitemradio\"\n label={label}\n selected={display.groupBy === value}\n onSelect={() => setDisplay((current) => ({ ...current, groupBy: value }))}\n />\n ))}\n </MenuSection>\n <MenuSection title=\"Columns\">\n {SESSIONS_COLUMNS.map((column) => (\n <MenuOption\n key={column.id}\n label={column.label}\n selected={display.columns.includes(column.id)}\n onSelect={() =>\n setDisplay((current) => ({\n ...current,\n columns: current.columns.includes(column.id)\n ? current.columns.filter((id) => id !== column.id)\n : SESSIONS_COLUMNS.map((candidate) => candidate.id).filter(\n (id) => id === column.id || current.columns.includes(id),\n ),\n }))\n }\n />\n ))}\n </MenuSection>\n </div>\n );\n};\n\nconst HEADER_BUTTON_CLASS = cn(\n 'inline-flex h-8 items-center gap-1.5 rounded-md border border-border/60 px-2.5 font-medium text-muted-foreground text-xs transition-colors hover:bg-muted hover:text-foreground disabled:opacity-50',\n FOCUS_RING_CLASS,\n);\n\nconst SessionsRow: FC<{\n row: AthenaStatewireThreadSummary;\n columns: readonly SessionsColumnId[];\n isActive: boolean;\n labels: SessionsLabels | undefined;\n list: AthenaStatewireThreadListState;\n onOpen: (row: AthenaStatewireThreadSummary) => void;\n}> = ({ row, columns, isActive, labels, list, onOpen }) => {\n const status = sessionStatusChip(row);\n const excerpt = plainExcerpt(row.preview);\n const chip = pullRequestChip(row.pullRequests);\n const origin = sessionOriginLabel(row);\n const cell = (id: SessionsColumnId): ReactNode => {\n switch (id) {\n case 'status':\n return <StatusChip label={status.label} tone={status.tone} detail={status.detail} />;\n case 'origin':\n return origin ? (\n <span className=\"rounded-full border border-border/60 px-1.5 py-px text-[10px] text-muted-foreground\">\n {origin}\n </span>\n ) : null;\n case 'mode':\n return row.collabAgentId ? (\n <span className=\"truncate text-muted-foreground text-xs\">\n {channelLabel(row.collabChannelId, labels)}\n </span>\n ) : null;\n case 'pullRequests':\n return chip ? <PullRequestChip chip={chip} pullRequests={row.pullRequests ?? []} /> : null;\n case 'creator':\n return (\n <span className=\"truncate text-muted-foreground text-xs\">{creatorLabel(row.createdByMe)}</span>\n );\n case 'created':\n return (\n <span className=\"text-muted-foreground text-xs\">\n {row.createdAt ? relativeTime(row.createdAt) : ''}\n </span>\n );\n case 'updated':\n return <span className=\"text-muted-foreground text-xs\">{relativeTime(row.updatedAt)}</span>;\n }\n };\n return (\n <tr\n data-thread-id={row.id}\n data-active={isActive || undefined}\n data-unread={row.isUnread || undefined}\n onClick={() => onOpen(row)}\n className={cn(\n 'group cursor-pointer border-border/40 border-b transition-colors hover:bg-muted/40',\n isActive && 'bg-muted',\n )}\n >\n <td className=\"min-w-0 py-2 pr-2 pl-3 align-top\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <span\n role={row.isUnread ? 'img' : undefined}\n aria-label={row.isUnread ? 'Unread' : undefined}\n aria-hidden={row.isUnread ? undefined : true}\n className={cn('size-2 shrink-0 rounded-full', row.isUnread ? 'bg-primary' : 'bg-transparent')}\n />\n <button\n type=\"button\"\n onClick={(event) => {\n event.stopPropagation();\n onOpen(row);\n }}\n className={cn(\n 'min-w-0 truncate text-left text-foreground text-sm',\n row.isUnread ? 'font-semibold' : 'font-medium',\n FOCUS_RING_CLASS,\n )}\n >\n {row.title ?? 'Untitled'}\n </button>\n {row.isFavorited ? (\n <PinIcon role=\"img\" aria-label=\"Pinned\" className=\"size-3 shrink-0 fill-current text-muted-foreground\" />\n ) : null}\n </div>\n {excerpt ? <p className=\"mt-0.5 truncate pl-4 text-muted-foreground text-xs\">{excerpt}</p> : null}\n </td>\n {columns.map((id) => (\n <td key={id} data-column={id} className=\"min-w-0 truncate px-2 py-2 align-top\">\n {cell(id)}\n </td>\n ))}\n <td className=\"py-1.5 pr-2 align-top\">\n <div data-row-actions className=\"flex items-center justify-end gap-0.5\">\n <RowIconButton\n label={row.isUnread ? 'Mark read' : 'Mark unread'}\n action=\"read-state\"\n pending={list.readStatePendingThreadIds.has(row.id)}\n onClick={() =>\n list.setReadState({ threadId: row.id, isUnread: !row.isUnread, updatedAt: row.updatedAt })\n }\n >\n {row.isUnread ? <MailOpenIcon className=\"size-3.5\" aria-hidden /> : <MailIcon className=\"size-3.5\" aria-hidden />}\n </RowIconButton>\n {list.favoriteToggleAvailable ? (\n <RowIconButton\n label={row.isFavorited ? 'Unpin session' : 'Pin session'}\n action=\"pin\"\n pressed={row.isFavorited}\n pending={list.favoritePendingThreadIds.has(row.id)}\n onClick={() => list.setFavorited({ threadId: row.id, isFavorited: !row.isFavorited })}\n >\n <PinIcon className={cn('size-3.5', row.isFavorited && 'fill-current')} aria-hidden />\n </RowIconButton>\n ) : null}\n {list.archiveAvailable ? (\n <RowIconButton\n label=\"Archive session\"\n action=\"archive\"\n pending={list.archivePendingThreadIds.has(row.id)}\n onClick={() => list.archiveThread(row.id)}\n >\n <ArchiveIcon className=\"size-3.5\" aria-hidden />\n </RowIconButton>\n ) : null}\n </div>\n </td>\n </tr>\n );\n};\n\nfunction SessionsPageBody({\n className,\n title = 'Sessions',\n onOpenSession,\n labels,\n storageKey = 'default',\n defaultQuery,\n pageSize,\n showNewSession = true,\n onNewSession,\n list,\n}: SessionsPageProps & { list: AthenaStatewireThreadListState }) {\n const [initial] = useState(() => readSessionsPageSettings(storageKey));\n const [savedDefault, setSavedDefault] = useState<AthenaSessionsQuery | null>(initial.defaultQuery);\n const [query, setQueryState] = useState<AthenaSessionsQuery>(\n () => initial.defaultQuery ?? normalizeSessionsQuery(defaultQuery ?? {}),\n );\n const [display, setDisplayState] = useState<SessionsPageDisplay>(initial.display);\n const [searchInput, setSearchInput] = useState(query.search ?? '');\n\n const setQuery = (update: (current: AthenaSessionsQuery) => AthenaSessionsQuery) =>\n setQueryState((current) => normalizeSessionsQuery(update(current)));\n const setDisplay = (update: (current: SessionsPageDisplay) => SessionsPageDisplay) =>\n setDisplayState((current) => {\n const next = update(current);\n writeSessionsPageSettings(storageKey, { defaultQuery: savedDefault, display: next });\n return next;\n });\n\n // The search box types freely; the list follows a beat later.\n useEffect(() => {\n const handle = setTimeout(() => {\n setQueryState((current) => {\n const search = searchInput.trim();\n if ((current.search ?? '') === search) return current;\n return normalizeSessionsQuery({ ...current, search });\n });\n }, 250);\n return () => clearTimeout(handle);\n }, [searchInput]);\n\n const sessions = useAthenaSessions({ query, ...(pageSize ? { pageSize } : {}) });\n const unavailable = useMemo(\n () => new Set([...sessions.unsupportedFields, ...sessions.unavailableFields]),\n [sessions.unsupportedFields, sessions.unavailableFields],\n );\n\n // Filter options: every agent, channel and origin this page has shown, so\n // narrowing the list never hides the option that would widen it again.\n const seenRef = useRef({ agents: new Set<string>(), channels: new Set<string>(), origins: new Set<string>() });\n for (const row of sessions.rows) {\n if (row.collabAgentId) {\n seenRef.current.agents.add(row.collabAgentId);\n seenRef.current.channels.add(row.collabChannelId || DEFAULT_COLLAB_CHANNEL);\n }\n if (row.startChannel) seenRef.current.origins.add(row.startChannel);\n }\n const agentOptions = [\n ...new Set([...Object.keys(labels?.agents ?? {}), ...seenRef.current.agents, ...(query.collabAgentIds ?? [])]),\n ];\n const channelOptions = [\n ...new Set([\n DEFAULT_COLLAB_CHANNEL,\n ...Object.keys(labels?.channels ?? {}),\n ...seenRef.current.channels,\n ...(query.collabChannelIds ?? []),\n ]),\n ];\n const originOptions = [...new Set([...seenRef.current.origins, ...(query.startChannels ?? [])])];\n\n const chips = sessionsFilterChips(query, labels);\n const sections = groupSessionsBy(sessions.rows, display.groupBy);\n const columns = SESSIONS_COLUMNS.map((column) => column.id).filter((id) => display.columns.includes(id));\n const { search: _search, ...queryWithoutSearch } = query;\n const isSavedDefault =\n savedDefault !== null && sessionsQueryKey(savedDefault) === sessionsQueryKey(queryWithoutSearch);\n const hasFilters = chips.length > 0;\n\n const open = (row: AthenaStatewireThreadSummary) => {\n list.selectThread(row.id);\n onOpenSession?.({ threadId: row.id, title: row.title });\n };\n const saveAsDefault = () => {\n const saved = normalizeSessionsQuery(queryWithoutSearch);\n setSavedDefault(saved);\n writeSessionsPageSettings(storageKey, { defaultQuery: saved, display });\n };\n const resetToDefault = () => {\n setQueryState({ ...(savedDefault ?? normalizeSessionsQuery(defaultQuery ?? {})) });\n setSearchInput('');\n };\n const clearFilters = () => {\n setQuery((current) => ({ sort: current.sort, direction: current.direction, search: current.search }));\n };\n const removeChip = (field: AthenaSessionsQueryField) =>\n setQuery((current) => {\n const next: AthenaSessionsQuery = { ...current, [field]: undefined };\n if (field === 'collabAgentIds') next.collabChannelIds = undefined;\n return next;\n });\n const exportCsv = () =>\n downloadText(\n `sessions-${new Date().toISOString().slice(0, 10)}.csv`,\n sessionsCsv(sessions.rows, labels),\n 'text/csv;charset=utf-8',\n );\n\n // Skeletons only while there is nothing to show; a changed query keeps the\n // previous rows (narrowed by it) until its own page answers.\n const showSkeleton =\n sessions.rows.length === 0 && (!sessions.hasResolvedFirstPage || sessions.isFetching);\n\n return (\n <div\n data-testid=\"sessions-page\"\n className={cn('athena-sdk-chrome flex min-h-0 flex-col gap-3 p-4', className)}\n >\n <div className=\"flex flex-wrap items-center gap-2\">\n <h2 className=\"font-semibold text-base text-foreground\">{title}</h2>\n <span data-testid=\"sessions-count\" className=\"text-muted-foreground text-xs\">\n {sessions.rows.length}\n {sessions.hasNextPage ? '+' : ''}\n </span>\n <div className=\"flex-1\" />\n <label className=\"relative block w-64 max-w-full\">\n <SearchIcon className=\"pointer-events-none absolute top-1/2 left-2.5 size-3.5 -translate-y-1/2 text-muted-foreground\" />\n <span className=\"sr-only\">Search sessions</span>\n <input\n type=\"search\"\n value={searchInput}\n onChange={(event) => setSearchInput(event.target.value)}\n placeholder=\"Search sessions…\"\n className=\"h-8 w-full rounded-md border border-border/60 bg-muted/40 pr-2 pl-8 text-sm outline-none focus:border-primary focus:bg-background\"\n />\n </label>\n <Popover>\n <PopoverTrigger asChild>\n <button type=\"button\" className={HEADER_BUTTON_CLASS} aria-label=\"Display options\">\n <SlidersHorizontalIcon className=\"size-3.5\" aria-hidden />\n Display\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"w-56\">\n <DisplayMenu query={query} setQuery={setQuery} display={display} setDisplay={setDisplay} />\n </PopoverContent>\n </Popover>\n <button\n type=\"button\"\n onClick={exportCsv}\n disabled={sessions.rows.length === 0}\n className={HEADER_BUTTON_CLASS}\n title=\"Export the loaded sessions as CSV\"\n >\n <DownloadIcon className=\"size-3.5\" aria-hidden />\n Export CSV\n </button>\n <button\n type=\"button\"\n onClick={sessions.refresh}\n disabled={sessions.isFetching}\n className={HEADER_BUTTON_CLASS}\n aria-label=\"Refresh sessions\"\n title=\"Refresh sessions\"\n >\n <RefreshCwIcon className={cn('size-3.5', sessions.isFetching && 'animate-spin')} aria-hidden />\n </button>\n {showNewSession ? (\n <button\n type=\"button\"\n onClick={() => {\n list.newThread();\n onNewSession?.();\n }}\n className={cn(\n 'inline-flex h-8 items-center gap-1.5 rounded-md bg-primary px-3 font-medium text-primary-foreground text-xs transition-colors hover:bg-primary/90',\n FOCUS_RING_CLASS,\n )}\n >\n <PlusIcon className=\"size-3.5\" aria-hidden />\n New session\n </button>\n ) : null}\n </div>\n\n <div className=\"flex flex-wrap items-center gap-1.5\" data-testid=\"sessions-filters\">\n <Popover>\n <PopoverTrigger asChild>\n <button type=\"button\" className={HEADER_BUTTON_CLASS}>\n <FilterIcon className=\"size-3.5\" aria-hidden />\n Filter\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"w-64\">\n <FilterMenu\n query={query}\n setQuery={setQuery}\n unavailable={unavailable}\n agentOptions={agentOptions}\n channelOptions={channelOptions}\n originOptions={originOptions}\n labels={labels}\n />\n </PopoverContent>\n </Popover>\n {chips.map((chip) => (\n <span\n key={chip.field + chip.label}\n data-filter-chip={chip.field}\n className=\"inline-flex h-7 items-center gap-1 rounded-full border border-border/60 bg-muted/40 pr-1 pl-2.5 text-foreground text-xs\"\n >\n {chip.label}\n <button\n type=\"button\"\n aria-label={`Remove filter ${chip.label}`}\n onClick={() => removeChip(chip.field)}\n className={cn('rounded-full p-0.5 text-muted-foreground hover:bg-muted hover:text-foreground', FOCUS_RING_CLASS)}\n >\n <XIcon className=\"size-3\" aria-hidden />\n </button>\n </span>\n ))}\n {hasFilters ? (\n <button type=\"button\" onClick={clearFilters} className={cn('px-1.5 text-muted-foreground text-xs hover:text-foreground', FOCUS_RING_CLASS)}>\n Clear\n </button>\n ) : null}\n <div className=\"flex-1\" />\n {savedDefault !== null && !isSavedDefault ? (\n <button type=\"button\" onClick={resetToDefault} className={cn('px-1.5 text-muted-foreground text-xs hover:text-foreground', FOCUS_RING_CLASS)}>\n Reset to default\n </button>\n ) : null}\n <button\n type=\"button\"\n onClick={saveAsDefault}\n disabled={isSavedDefault}\n className={cn('px-1.5 text-muted-foreground text-xs hover:text-foreground disabled:opacity-50', FOCUS_RING_CLASS)}\n >\n {isSavedDefault ? 'Saved as default' : 'Save as default'}\n </button>\n </div>\n\n {sessions.degradedFields.length > 0 || sessions.unavailableFields.length > 0 ? (\n <p\n role=\"status\"\n data-testid=\"sessions-degraded\"\n className=\"rounded-md border border-amber-200 bg-amber-50 px-3 py-2 text-amber-900 text-xs\"\n >\n {sessions.degradedFields.length > 0\n ? `This Athena server cannot filter by ${fieldList(sessions.degradedFields)} yet, so they apply to the sessions loaded so far. `\n : ''}\n {sessions.unavailableFields.length > 0\n ? `Filtering by ${fieldList(sessions.unavailableFields)} is not available on this server yet and is off.`\n : ''}\n </p>\n ) : null}\n\n <div className=\"min-h-0 flex-1 overflow-auto\">\n {showSkeleton ? (\n <SessionListSkeleton rows={6} />\n ) : sections.length === 0 ? (\n <div data-testid=\"sessions-empty\" className=\"flex flex-col items-center gap-2 py-12 text-center\">\n <p className=\"text-muted-foreground text-sm\">\n {hasFilters || query.search ? 'No sessions match these filters.' : 'No sessions yet.'}\n </p>\n {hasFilters ? (\n <button type=\"button\" onClick={clearFilters} className={HEADER_BUTTON_CLASS}>\n Clear filters\n </button>\n ) : null}\n </div>\n ) : (\n <table className=\"w-full table-fixed border-collapse text-sm\" aria-busy={sessions.isFetching || undefined}>\n <thead>\n <tr className=\"border-border/60 border-b text-left text-[11px] text-muted-foreground uppercase tracking-wide\">\n <th scope=\"col\" className=\"py-2 pl-7 font-medium\">\n Session\n </th>\n {columns.map((id) => (\n <th key={id} scope=\"col\" className={cn('px-2 py-2 font-medium', COLUMN_WIDTH[id])}>\n {SESSIONS_COLUMNS.find((column) => column.id === id)?.label}\n </th>\n ))}\n <th scope=\"col\" className=\"w-24 py-2 pr-2\">\n <span className=\"sr-only\">Actions</span>\n </th>\n </tr>\n </thead>\n {sections.map((section) => (\n <tbody key={section.key} data-group={section.label ?? undefined}>\n {section.label ? (\n <tr>\n <th colSpan={columns.length + 2} scope=\"colgroup\" className={SECTION_HEADING_CLASS}>\n {section.label}\n <span className=\"ml-1.5 font-normal normal-case tracking-normal\">{section.items.length}</span>\n </th>\n </tr>\n ) : null}\n {section.items.map((row) => (\n <SessionsRow\n key={row.id}\n row={row}\n columns={columns}\n isActive={row.id === list.activeThreadId}\n labels={labels}\n list={list}\n onOpen={open}\n />\n ))}\n </tbody>\n ))}\n </table>\n )}\n {sessions.hasNextPage && !showSkeleton ? (\n <button\n type=\"button\"\n onClick={sessions.fetchNextPage}\n disabled={sessions.isFetchingNextPage}\n className={cn('mt-2 w-full rounded-md py-2 text-muted-foreground text-xs transition-colors hover:bg-muted disabled:opacity-50', FOCUS_RING_CLASS)}\n >\n {sessions.isFetchingNextPage ? 'Loading…' : sessions.isFetchNextPageError ? 'Retry loading more' : 'Load more'}\n </button>\n ) : null}\n </div>\n </div>\n );\n}\n\n/**\n * A full-page session list with server-side filters, display options, an\n * attention-coloured status column and CSV export. Renders nothing outside\n * `<AthenaProvider enableThreadList>`.\n */\nexport function SessionsPage(props: SessionsPageProps) {\n const list = useAthenaStatewireThreadList();\n const live = useContext(AthenaSessionsLiveContext);\n if (!list || !live) return null;\n return <SessionsPageBody {...props} list={list} />;\n}\n"],"names":["_a"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SessionsPage.js","sources":["../../src/threads/SessionsPage.tsx"],"sourcesContent":["/**\n * `SessionsPage` — a full-page, Devin-style session list: filter chips that\n * the server applies (status, pull requests, unread, pinned, creator, agent,\n * mode, origin, created / updated date), a title search, display options\n * (sort, direction, grouping, columns), an attention-coloured status column\n * that says what the person must do next, row actions (read, pin, archive)\n * and a CSV export of the loaded rows. Live through the thread-list\n * provider's conversation index; renders nothing outside\n * `<AthenaProvider enableThreadList>`.\n */\nimport {\n ArchiveIcon,\n CheckIcon,\n DownloadIcon,\n FilterIcon,\n MailIcon,\n MailOpenIcon,\n PinIcon,\n PlusIcon,\n RefreshCwIcon,\n SearchIcon,\n SlidersHorizontalIcon,\n XIcon,\n} from 'lucide-react';\nimport type { FC, ReactNode } from 'react';\nimport { useContext, useEffect, useMemo, useRef, useState } from 'react';\nimport { cn } from '../lib/utils';\nimport { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';\nimport { SessionListSkeleton, type SessionOpenTarget } from './SessionList';\nimport { pullRequestChip, relativeTime, sessionOriginLabel } from './session-list-model';\nimport { FOCUS_RING_CLASS, PullRequestChip, RowIconButton, StatusChip } from './session-row-parts';\nimport {\n agentLabel,\n channelLabel,\n creatorLabel,\n DEFAULT_HIDDEN_SESSIONS_COLUMNS,\n datePresetBounds,\n groupSessionsBy,\n runStatusLabel,\n SESSIONS_COLUMNS,\n SESSIONS_DATE_PRESETS,\n type SessionsColumnId,\n type SessionsDatePreset,\n type SessionsGroupBy,\n type SessionsLabels,\n sessionsCsv,\n sessionsFilterChips,\n plainExcerpt,\n sessionStatusChip,\n visibleSessionsColumns,\n} from './sessions-page-model';\nimport {\n DEFAULT_SESSIONS_PAGE_DISPLAY,\n readSessionsPageSettings,\n type SessionsPageDisplay,\n writeSessionsPageSettings,\n} from './sessions-page-storage';\nimport {\n type AthenaSessionsQuery,\n type AthenaSessionsQueryField,\n DEFAULT_COLLAB_CHANNEL,\n normalizeSessionsQuery,\n SESSION_RUN_STATUSES,\n type SessionRunStatus,\n sessionsQueryKey,\n} from './sessions-query';\nimport {\n AthenaSessionsLiveContext,\n type AthenaStatewireThreadListState,\n type AthenaStatewireThreadSummary,\n useAthenaStatewireThreadList,\n} from './statewire-thread-list';\nimport { useAthenaSessions } from './use-athena-sessions';\n\nexport interface SessionsPageProps {\n className?: string;\n /** Heading (default \"Sessions\"). */\n title?: string;\n /**\n * Called after a row is selected (the provider's chat switches to it), so\n * a host can navigate to its chat view.\n */\n onOpenSession?: (target: SessionOpenTarget) => void;\n /** Names for collab agents and channels (filters, the Mode column, CSV); ids show otherwise. */\n labels?: SessionsLabels;\n /**\n * Namespaces what this browser remembers — \"Save as default\" and the\n * display options — so a host with several pages keeps them apart\n * (default `\"default\"`).\n */\n storageKey?: string;\n /** The filters before anything is saved as default. */\n defaultQuery?: AthenaSessionsQuery;\n /**\n * The columns hidden until the person shows them from Display ▸ Columns;\n * every other column shows. Default `DEFAULT_HIDDEN_SESSIONS_COLUMNS` (Mode,\n * Creator, Created). An app whose sessions have no pull requests passes\n * `[...DEFAULT_HIDDEN_SESSIONS_COLUMNS, 'pullRequests']`. Read once, while\n * this browser remembers no display for `storageKey`; after that, the\n * person's own choice of columns is kept.\n */\n defaultHiddenColumns?: readonly SessionsColumnId[];\n /** Rows per page (default 50). */\n pageSize?: number;\n /** Offer \"New session\" (default `true`). */\n showNewSession?: boolean;\n /** Called after \"New session\" starts a fresh chat, so a host can show its chat view. */\n onNewSession?: () => void;\n}\n\n/** What each query field is called in notices. */\nconst FIELD_LABEL: Record<AthenaSessionsQueryField, string> = {\n search: 'search',\n collabAgentIds: 'agent',\n collabChannelIds: 'mode',\n startChannels: 'origin',\n createdAfter: 'created date',\n createdBefore: 'created date',\n updatedAfter: 'updated date',\n updatedBefore: 'updated date',\n favoritesOnly: 'pinned',\n unreadOnly: 'unread',\n runStatuses: 'status',\n sessionStatuses: 'session status',\n hasPullRequests: 'pull requests',\n createdByMe: 'creator',\n excludeDismissed: 'dismissed',\n excludeTriggered: 'who started it',\n sort: 'sort',\n direction: 'sort direction',\n};\n\n/** \"agent\", \"agent and mode\", \"agent, mode and unread\". */\nfunction fieldList(fields: readonly AthenaSessionsQueryField[]): string {\n const names = [...new Set(fields.map((field) => FIELD_LABEL[field]))];\n return names.length <= 1 ? (names[0] ?? '') : `${names.slice(0, -1).join(', ')} and ${names.at(-1)}`;\n}\n\nconst COLUMN_WIDTH: Record<SessionsColumnId, string> = {\n status: 'w-56',\n origin: 'w-24',\n mode: 'w-28',\n pullRequests: 'w-24',\n creator: 'w-32',\n created: 'w-24',\n updated: 'w-24',\n};\n\n/** Save `text` as a file in the browser. */\nfunction downloadText(filename: string, text: string, type: string): void {\n if (typeof document === 'undefined') return;\n const url = URL.createObjectURL(new Blob([text], { type }));\n const anchor = document.createElement('a');\n anchor.href = url;\n anchor.download = filename;\n anchor.rel = 'noopener';\n document.body.appendChild(anchor);\n anchor.click();\n anchor.remove();\n setTimeout(() => URL.revokeObjectURL(url), 0);\n}\n\nconst SECTION_HEADING_CLASS =\n 'px-3 pb-1 pt-3 text-left font-medium text-[11px] text-muted-foreground/70 uppercase tracking-wide';\n\n/** A pressable option in a filter or display menu. */\nconst MenuOption: FC<{\n label: string;\n selected: boolean;\n onSelect: () => void;\n disabled?: boolean;\n role?: 'menuitemcheckbox' | 'menuitemradio';\n}> = ({ label, selected, onSelect, disabled = false, role = 'menuitemcheckbox' }) => (\n <button\n type=\"button\"\n role={role}\n aria-checked={selected}\n disabled={disabled}\n onClick={onSelect}\n className={cn(\n 'flex w-full items-center gap-2 rounded-sm px-2 py-1 text-left text-xs transition-colors hover:bg-muted disabled:cursor-not-allowed disabled:opacity-50',\n FOCUS_RING_CLASS,\n )}\n >\n <span\n aria-hidden=\"true\"\n className={cn(\n 'flex size-3.5 shrink-0 items-center justify-center rounded-sm border border-border',\n selected && 'border-primary bg-primary text-primary-foreground',\n )}\n >\n {selected ? <CheckIcon className=\"size-3\" /> : null}\n </span>\n <span className=\"truncate\">{label}</span>\n </button>\n);\n\nconst MenuSection: FC<{ title: string; hint?: string | null; children: ReactNode }> = ({\n title,\n hint,\n children,\n}) => (\n <section aria-label={title} className=\"py-1\">\n <h4 className=\"px-2 pb-0.5 font-medium text-[11px] text-muted-foreground uppercase tracking-wide\">\n {title}\n </h4>\n {hint ? <p className=\"px-2 pb-1 text-[11px] text-muted-foreground\">{hint}</p> : null}\n {children}\n </section>\n);\n\nfunction toggleValue<T extends string>(values: readonly T[] | undefined, value: T): T[] {\n const current = values ?? [];\n return current.includes(value) ? current.filter((item) => item !== value) : [...current, value];\n}\n\nfunction datePresetOf(after: string | undefined, before: string | undefined, presets: Record<SessionsDatePreset, { after?: string; before?: string }>): SessionsDatePreset | null {\n for (const preset of SESSIONS_DATE_PRESETS) {\n const bounds = presets[preset.id];\n if ((bounds.after ?? undefined) === after && (bounds.before ?? undefined) === before) {\n return preset.id;\n }\n }\n return null;\n}\n\ninterface FilterMenuProps {\n query: AthenaSessionsQuery;\n setQuery: (update: (query: AthenaSessionsQuery) => AthenaSessionsQuery) => void;\n unavailable: ReadonlySet<AthenaSessionsQueryField>;\n agentOptions: readonly string[];\n channelOptions: readonly string[];\n originOptions: readonly string[];\n labels: SessionsLabels | undefined;\n}\n\nconst UNAVAILABLE_HINT = 'This Athena server cannot filter by this yet.';\n\n/** Every filter, stacked by kind; each option toggles at once. */\nconst FilterMenu: FC<FilterMenuProps> = ({\n query,\n setQuery,\n unavailable,\n agentOptions,\n channelOptions,\n originOptions,\n labels,\n}) => {\n // The presets' bounds are captured when the menu opens, so a selected\n // preset stays recognisable while it is open.\n const [presetBounds] = useState(() =>\n Object.fromEntries(\n SESSIONS_DATE_PRESETS.map((preset) => [preset.id, datePresetBounds(preset.id)]),\n ) as Record<SessionsDatePreset, { after?: string; before?: string }>,\n );\n const createdPreset = datePresetOf(query.createdAfter, query.createdBefore, presetBounds);\n const updatedPreset = datePresetOf(query.updatedAfter, query.updatedBefore, presetBounds);\n const setPreset = (\n kind: 'created' | 'updated',\n preset: SessionsDatePreset | null,\n ) =>\n setQuery((current) => {\n const bounds = preset ? presetBounds[preset] : {};\n return kind === 'created'\n ? { ...current, createdAfter: bounds.after, createdBefore: bounds.before }\n : { ...current, updatedAfter: bounds.after, updatedBefore: bounds.before };\n });\n const disabledHint = (field: AthenaSessionsQueryField) =>\n unavailable.has(field) ? UNAVAILABLE_HINT : null;\n\n return (\n <div role=\"menu\" aria-label=\"Filters\" className=\"max-h-[70vh] overflow-y-auto p-1\">\n <MenuSection title=\"Status\" hint={disabledHint('runStatuses')}>\n {SESSION_RUN_STATUSES.map((status) => (\n <MenuOption\n key={status}\n label={runStatusLabel(status)}\n selected={query.runStatuses?.includes(status) ?? false}\n disabled={unavailable.has('runStatuses')}\n onSelect={() =>\n setQuery((current) => ({\n ...current,\n runStatuses: toggleValue<SessionRunStatus>(current.runStatuses, status),\n }))\n }\n />\n ))}\n </MenuSection>\n <MenuSection title=\"Pull requests\" hint={disabledHint('hasPullRequests')}>\n {(\n [\n ['Has pull requests', true],\n ['No pull requests', false],\n ] as const\n ).map(([label, value]) => (\n <MenuOption\n key={label}\n role=\"menuitemradio\"\n label={label}\n selected={query.hasPullRequests === value}\n disabled={unavailable.has('hasPullRequests')}\n onSelect={() =>\n setQuery((current) => ({\n ...current,\n hasPullRequests: current.hasPullRequests === value ? undefined : value,\n }))\n }\n />\n ))}\n </MenuSection>\n <MenuSection title=\"Read and pinned\">\n <MenuOption\n label=\"Unread\"\n selected={query.unreadOnly === true}\n disabled={unavailable.has('unreadOnly')}\n onSelect={() => setQuery((current) => ({ ...current, unreadOnly: !current.unreadOnly }))}\n />\n <MenuOption\n label=\"Pinned\"\n selected={query.favoritesOnly === true}\n disabled={unavailable.has('favoritesOnly')}\n onSelect={() =>\n setQuery((current) => ({ ...current, favoritesOnly: !current.favoritesOnly }))\n }\n />\n </MenuSection>\n <MenuSection title=\"Creator\" hint={disabledHint('createdByMe')}>\n {(\n [\n ['You', true],\n ['Shared with you', false],\n ] as const\n ).map(([label, value]) => (\n <MenuOption\n key={label}\n role=\"menuitemradio\"\n label={label}\n selected={query.createdByMe === value}\n disabled={unavailable.has('createdByMe')}\n onSelect={() =>\n setQuery((current) => ({\n ...current,\n createdByMe: current.createdByMe === value ? undefined : value,\n }))\n }\n />\n ))}\n <MenuOption\n label=\"Started by a person\"\n selected={query.excludeTriggered === true}\n onSelect={() =>\n setQuery((current) => ({ ...current, excludeTriggered: !current.excludeTriggered }))\n }\n />\n </MenuSection>\n {agentOptions.length > 0 ? (\n <MenuSection title=\"Agent\" hint={disabledHint('collabAgentIds')}>\n {agentOptions.map((agentId) => (\n <MenuOption\n key={agentId}\n label={agentLabel(agentId, labels)}\n selected={query.collabAgentIds?.includes(agentId) ?? false}\n disabled={unavailable.has('collabAgentIds')}\n onSelect={() =>\n setQuery((current) => ({\n ...current,\n collabAgentIds: toggleValue(current.collabAgentIds, agentId),\n }))\n }\n />\n ))}\n </MenuSection>\n ) : null}\n {agentOptions.length > 0 ? (\n <MenuSection\n title=\"Mode\"\n hint={\n disabledHint('collabChannelIds') ??\n (query.collabAgentIds?.length ? null : 'Pick an agent first: a mode is one of its channels.')\n }\n >\n {channelOptions.map((channelId) => (\n <MenuOption\n key={channelId}\n label={channelLabel(channelId, labels)}\n selected={query.collabChannelIds?.includes(channelId) ?? false}\n disabled={unavailable.has('collabChannelIds') || !query.collabAgentIds?.length}\n onSelect={() =>\n setQuery((current) => ({\n ...current,\n collabChannelIds: toggleValue(current.collabChannelIds, channelId),\n }))\n }\n />\n ))}\n </MenuSection>\n ) : null}\n {originOptions.length > 0 ? (\n <MenuSection title=\"Origin\" hint={disabledHint('startChannels')}>\n {originOptions.map((channel) => (\n <MenuOption\n key={channel}\n label={sessionOriginLabel({ startChannel: channel, appId: null, triggerType: null }) ?? channel}\n selected={query.startChannels?.includes(channel) ?? false}\n disabled={unavailable.has('startChannels')}\n onSelect={() =>\n setQuery((current) => ({\n ...current,\n startChannels: toggleValue(current.startChannels, channel),\n }))\n }\n />\n ))}\n </MenuSection>\n ) : null}\n <MenuSection title=\"Created\">\n {SESSIONS_DATE_PRESETS.map((preset) => (\n <MenuOption\n key={preset.id}\n role=\"menuitemradio\"\n label={preset.label}\n selected={createdPreset === preset.id}\n onSelect={() => setPreset('created', createdPreset === preset.id ? null : preset.id)}\n />\n ))}\n </MenuSection>\n <MenuSection title=\"Updated\">\n {SESSIONS_DATE_PRESETS.map((preset) => (\n <MenuOption\n key={preset.id}\n role=\"menuitemradio\"\n label={preset.label}\n selected={updatedPreset === preset.id}\n onSelect={() => setPreset('updated', updatedPreset === preset.id ? null : preset.id)}\n />\n ))}\n </MenuSection>\n </div>\n );\n};\n\nconst DisplayMenu: FC<{\n query: AthenaSessionsQuery;\n setQuery: (update: (query: AthenaSessionsQuery) => AthenaSessionsQuery) => void;\n display: SessionsPageDisplay;\n setDisplay: (update: (display: SessionsPageDisplay) => SessionsPageDisplay) => void;\n}> = ({ query, setQuery, display, setDisplay }) => {\n const sort = query.sort ?? 'updated';\n const direction = query.direction ?? 'desc';\n return (\n <div role=\"menu\" aria-label=\"Display options\" className=\"p-1\">\n <MenuSection title=\"Sort by\">\n {(\n [\n ['updated', 'Last updated'],\n ['created', 'Created'],\n ] as const\n ).map(([value, label]) => (\n <MenuOption\n key={value}\n role=\"menuitemradio\"\n label={label}\n selected={sort === value}\n onSelect={() => setQuery((current) => ({ ...current, sort: value }))}\n />\n ))}\n </MenuSection>\n <MenuSection title=\"Order\">\n {(\n [\n ['desc', 'Newest first'],\n ['asc', 'Oldest first'],\n ] as const\n ).map(([value, label]) => (\n <MenuOption\n key={value}\n role=\"menuitemradio\"\n label={label}\n selected={direction === value}\n onSelect={() => setQuery((current) => ({ ...current, direction: value }))}\n />\n ))}\n </MenuSection>\n <MenuSection title=\"Group by\">\n {(\n [\n ['attention', 'What it needs'],\n ['status', 'Run status'],\n ['none', 'No grouping'],\n ] as const\n ).map(([value, label]) => (\n <MenuOption\n key={value}\n role=\"menuitemradio\"\n label={label}\n selected={display.groupBy === value}\n onSelect={() => setDisplay((current) => ({ ...current, groupBy: value }))}\n />\n ))}\n </MenuSection>\n <MenuSection title=\"Columns\">\n {SESSIONS_COLUMNS.map((column) => (\n <MenuOption\n key={column.id}\n label={column.label}\n selected={display.columns.includes(column.id)}\n onSelect={() =>\n setDisplay((current) => ({\n ...current,\n columns: current.columns.includes(column.id)\n ? current.columns.filter((id) => id !== column.id)\n : SESSIONS_COLUMNS.map((candidate) => candidate.id).filter(\n (id) => id === column.id || current.columns.includes(id),\n ),\n }))\n }\n />\n ))}\n </MenuSection>\n </div>\n );\n};\n\nconst HEADER_BUTTON_CLASS = cn(\n 'inline-flex h-8 items-center gap-1.5 rounded-md border border-border/60 px-2.5 font-medium text-muted-foreground text-xs transition-colors hover:bg-muted hover:text-foreground disabled:opacity-50',\n FOCUS_RING_CLASS,\n);\n\nconst SessionsRow: FC<{\n row: AthenaStatewireThreadSummary;\n columns: readonly SessionsColumnId[];\n isActive: boolean;\n labels: SessionsLabels | undefined;\n list: AthenaStatewireThreadListState;\n onOpen: (row: AthenaStatewireThreadSummary) => void;\n}> = ({ row, columns, isActive, labels, list, onOpen }) => {\n const status = sessionStatusChip(row);\n const excerpt = plainExcerpt(row.preview);\n const chip = pullRequestChip(row.pullRequests);\n const origin = sessionOriginLabel(row);\n const cell = (id: SessionsColumnId): ReactNode => {\n switch (id) {\n case 'status':\n return <StatusChip label={status.label} tone={status.tone} detail={status.detail} />;\n case 'origin':\n return origin ? (\n <span className=\"rounded-full border border-border/60 px-1.5 py-px text-[10px] text-muted-foreground\">\n {origin}\n </span>\n ) : null;\n case 'mode':\n return row.collabAgentId ? (\n <span className=\"truncate text-muted-foreground text-xs\">\n {channelLabel(row.collabChannelId, labels)}\n </span>\n ) : null;\n case 'pullRequests':\n return chip ? <PullRequestChip chip={chip} pullRequests={row.pullRequests ?? []} /> : null;\n case 'creator':\n return (\n <span className=\"truncate text-muted-foreground text-xs\">{creatorLabel(row.createdByMe)}</span>\n );\n case 'created':\n return (\n <span className=\"text-muted-foreground text-xs\">\n {row.createdAt ? relativeTime(row.createdAt) : ''}\n </span>\n );\n case 'updated':\n return <span className=\"text-muted-foreground text-xs\">{relativeTime(row.updatedAt)}</span>;\n }\n };\n return (\n <tr\n data-thread-id={row.id}\n data-active={isActive || undefined}\n data-unread={row.isUnread || undefined}\n onClick={() => onOpen(row)}\n className={cn(\n 'group cursor-pointer border-border/40 border-b transition-colors hover:bg-muted/40',\n isActive && 'bg-muted',\n )}\n >\n <td className=\"min-w-0 py-2 pr-2 pl-3 align-top\">\n <div className=\"flex min-w-0 items-center gap-2\">\n <span\n role={row.isUnread ? 'img' : undefined}\n aria-label={row.isUnread ? 'Unread' : undefined}\n aria-hidden={row.isUnread ? undefined : true}\n className={cn('size-2 shrink-0 rounded-full', row.isUnread ? 'bg-primary' : 'bg-transparent')}\n />\n <button\n type=\"button\"\n onClick={(event) => {\n event.stopPropagation();\n onOpen(row);\n }}\n className={cn(\n 'min-w-0 truncate text-left text-foreground text-sm',\n row.isUnread ? 'font-semibold' : 'font-medium',\n FOCUS_RING_CLASS,\n )}\n >\n {row.title ?? 'Untitled'}\n </button>\n {row.isFavorited ? (\n <PinIcon role=\"img\" aria-label=\"Pinned\" className=\"size-3 shrink-0 fill-current text-muted-foreground\" />\n ) : null}\n </div>\n {excerpt ? <p className=\"mt-0.5 truncate pl-4 text-muted-foreground text-xs\">{excerpt}</p> : null}\n </td>\n {columns.map((id) => (\n <td key={id} data-column={id} className=\"min-w-0 truncate px-2 py-2 align-top\">\n {cell(id)}\n </td>\n ))}\n <td className=\"py-1.5 pr-2 align-top\">\n <div data-row-actions className=\"flex items-center justify-end gap-0.5\">\n <RowIconButton\n label={row.isUnread ? 'Mark read' : 'Mark unread'}\n action=\"read-state\"\n pending={list.readStatePendingThreadIds.has(row.id)}\n onClick={() =>\n list.setReadState({ threadId: row.id, isUnread: !row.isUnread, updatedAt: row.updatedAt })\n }\n >\n {row.isUnread ? <MailOpenIcon className=\"size-3.5\" aria-hidden /> : <MailIcon className=\"size-3.5\" aria-hidden />}\n </RowIconButton>\n {list.favoriteToggleAvailable ? (\n <RowIconButton\n label={row.isFavorited ? 'Unpin session' : 'Pin session'}\n action=\"pin\"\n pressed={row.isFavorited}\n pending={list.favoritePendingThreadIds.has(row.id)}\n onClick={() => list.setFavorited({ threadId: row.id, isFavorited: !row.isFavorited })}\n >\n <PinIcon className={cn('size-3.5', row.isFavorited && 'fill-current')} aria-hidden />\n </RowIconButton>\n ) : null}\n {list.archiveAvailable ? (\n <RowIconButton\n label=\"Archive session\"\n action=\"archive\"\n pending={list.archivePendingThreadIds.has(row.id)}\n onClick={() => list.archiveThread(row.id)}\n >\n <ArchiveIcon className=\"size-3.5\" aria-hidden />\n </RowIconButton>\n ) : null}\n </div>\n </td>\n </tr>\n );\n};\n\nfunction SessionsPageBody({\n className,\n title = 'Sessions',\n onOpenSession,\n labels,\n storageKey = 'default',\n defaultQuery,\n defaultHiddenColumns = DEFAULT_HIDDEN_SESSIONS_COLUMNS,\n pageSize,\n showNewSession = true,\n onNewSession,\n list,\n}: SessionsPageProps & { list: AthenaStatewireThreadListState }) {\n const [initial] = useState(() =>\n readSessionsPageSettings(storageKey, {\n ...DEFAULT_SESSIONS_PAGE_DISPLAY,\n columns: visibleSessionsColumns(defaultHiddenColumns),\n }),\n );\n const [savedDefault, setSavedDefault] = useState<AthenaSessionsQuery | null>(initial.defaultQuery);\n const [query, setQueryState] = useState<AthenaSessionsQuery>(\n () => initial.defaultQuery ?? normalizeSessionsQuery(defaultQuery ?? {}),\n );\n const [display, setDisplayState] = useState<SessionsPageDisplay>(initial.display);\n const [searchInput, setSearchInput] = useState(query.search ?? '');\n\n const setQuery = (update: (current: AthenaSessionsQuery) => AthenaSessionsQuery) =>\n setQueryState((current) => normalizeSessionsQuery(update(current)));\n const setDisplay = (update: (current: SessionsPageDisplay) => SessionsPageDisplay) =>\n setDisplayState((current) => {\n const next = update(current);\n writeSessionsPageSettings(storageKey, { defaultQuery: savedDefault, display: next });\n return next;\n });\n\n // The search box types freely; the list follows a beat later.\n useEffect(() => {\n const handle = setTimeout(() => {\n setQueryState((current) => {\n const search = searchInput.trim();\n if ((current.search ?? '') === search) return current;\n return normalizeSessionsQuery({ ...current, search });\n });\n }, 250);\n return () => clearTimeout(handle);\n }, [searchInput]);\n\n const sessions = useAthenaSessions({ query, ...(pageSize ? { pageSize } : {}) });\n const unavailable = useMemo(\n () => new Set([...sessions.unsupportedFields, ...sessions.unavailableFields]),\n [sessions.unsupportedFields, sessions.unavailableFields],\n );\n\n // Filter options: every agent, channel and origin this page has shown, so\n // narrowing the list never hides the option that would widen it again.\n const seenRef = useRef({ agents: new Set<string>(), channels: new Set<string>(), origins: new Set<string>() });\n for (const row of sessions.rows) {\n if (row.collabAgentId) {\n seenRef.current.agents.add(row.collabAgentId);\n seenRef.current.channels.add(row.collabChannelId || DEFAULT_COLLAB_CHANNEL);\n }\n if (row.startChannel) seenRef.current.origins.add(row.startChannel);\n }\n const agentOptions = [\n ...new Set([...Object.keys(labels?.agents ?? {}), ...seenRef.current.agents, ...(query.collabAgentIds ?? [])]),\n ];\n const channelOptions = [\n ...new Set([\n DEFAULT_COLLAB_CHANNEL,\n ...Object.keys(labels?.channels ?? {}),\n ...seenRef.current.channels,\n ...(query.collabChannelIds ?? []),\n ]),\n ];\n const originOptions = [...new Set([...seenRef.current.origins, ...(query.startChannels ?? [])])];\n\n const chips = sessionsFilterChips(query, labels);\n const sections = groupSessionsBy(sessions.rows, display.groupBy);\n const columns = SESSIONS_COLUMNS.map((column) => column.id).filter((id) => display.columns.includes(id));\n const { search: _search, ...queryWithoutSearch } = query;\n const isSavedDefault =\n savedDefault !== null && sessionsQueryKey(savedDefault) === sessionsQueryKey(queryWithoutSearch);\n const hasFilters = chips.length > 0;\n\n const open = (row: AthenaStatewireThreadSummary) => {\n list.selectThread(row.id);\n onOpenSession?.({ threadId: row.id, title: row.title });\n };\n const saveAsDefault = () => {\n const saved = normalizeSessionsQuery(queryWithoutSearch);\n setSavedDefault(saved);\n writeSessionsPageSettings(storageKey, { defaultQuery: saved, display });\n };\n const resetToDefault = () => {\n setQueryState({ ...(savedDefault ?? normalizeSessionsQuery(defaultQuery ?? {})) });\n setSearchInput('');\n };\n const clearFilters = () => {\n setQuery((current) => ({ sort: current.sort, direction: current.direction, search: current.search }));\n };\n const removeChip = (field: AthenaSessionsQueryField) =>\n setQuery((current) => {\n const next: AthenaSessionsQuery = { ...current, [field]: undefined };\n if (field === 'collabAgentIds') next.collabChannelIds = undefined;\n return next;\n });\n const exportCsv = () =>\n downloadText(\n `sessions-${new Date().toISOString().slice(0, 10)}.csv`,\n sessionsCsv(sessions.rows, labels),\n 'text/csv;charset=utf-8',\n );\n\n // Skeletons only while there is nothing to show; a changed query keeps the\n // previous rows (narrowed by it) until its own page answers.\n const showSkeleton =\n sessions.rows.length === 0 && (!sessions.hasResolvedFirstPage || sessions.isFetching);\n\n return (\n <div\n data-testid=\"sessions-page\"\n className={cn('athena-sdk-chrome flex min-h-0 flex-col gap-3 p-4', className)}\n >\n <div className=\"flex flex-wrap items-center gap-2\">\n <h2 className=\"font-semibold text-base text-foreground\">{title}</h2>\n <span data-testid=\"sessions-count\" className=\"text-muted-foreground text-xs\">\n {sessions.rows.length}\n {sessions.hasNextPage ? '+' : ''}\n </span>\n <div className=\"flex-1\" />\n <label className=\"relative block w-64 max-w-full\">\n <SearchIcon className=\"pointer-events-none absolute top-1/2 left-2.5 size-3.5 -translate-y-1/2 text-muted-foreground\" />\n <span className=\"sr-only\">Search sessions</span>\n <input\n type=\"search\"\n value={searchInput}\n onChange={(event) => setSearchInput(event.target.value)}\n placeholder=\"Search sessions…\"\n className=\"h-8 w-full rounded-md border border-border/60 bg-muted/40 pr-2 pl-8 text-sm outline-none focus:border-primary focus:bg-background\"\n />\n </label>\n <Popover>\n <PopoverTrigger asChild>\n <button type=\"button\" className={HEADER_BUTTON_CLASS} aria-label=\"Display options\">\n <SlidersHorizontalIcon className=\"size-3.5\" aria-hidden />\n Display\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"w-56\">\n <DisplayMenu query={query} setQuery={setQuery} display={display} setDisplay={setDisplay} />\n </PopoverContent>\n </Popover>\n <button\n type=\"button\"\n onClick={exportCsv}\n disabled={sessions.rows.length === 0}\n className={HEADER_BUTTON_CLASS}\n title=\"Export the loaded sessions as CSV\"\n >\n <DownloadIcon className=\"size-3.5\" aria-hidden />\n Export CSV\n </button>\n <button\n type=\"button\"\n onClick={sessions.refresh}\n disabled={sessions.isFetching}\n className={HEADER_BUTTON_CLASS}\n aria-label=\"Refresh sessions\"\n title=\"Refresh sessions\"\n >\n <RefreshCwIcon className={cn('size-3.5', sessions.isFetching && 'animate-spin')} aria-hidden />\n </button>\n {showNewSession ? (\n <button\n type=\"button\"\n onClick={() => {\n list.newThread();\n onNewSession?.();\n }}\n className={cn(\n 'inline-flex h-8 items-center gap-1.5 rounded-md bg-primary px-3 font-medium text-primary-foreground text-xs transition-colors hover:bg-primary/90',\n FOCUS_RING_CLASS,\n )}\n >\n <PlusIcon className=\"size-3.5\" aria-hidden />\n New session\n </button>\n ) : null}\n </div>\n\n <div className=\"flex flex-wrap items-center gap-1.5\" data-testid=\"sessions-filters\">\n <Popover>\n <PopoverTrigger asChild>\n <button type=\"button\" className={HEADER_BUTTON_CLASS}>\n <FilterIcon className=\"size-3.5\" aria-hidden />\n Filter\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"w-64\">\n <FilterMenu\n query={query}\n setQuery={setQuery}\n unavailable={unavailable}\n agentOptions={agentOptions}\n channelOptions={channelOptions}\n originOptions={originOptions}\n labels={labels}\n />\n </PopoverContent>\n </Popover>\n {chips.map((chip) => (\n <span\n key={chip.field + chip.label}\n data-filter-chip={chip.field}\n className=\"inline-flex h-7 items-center gap-1 rounded-full border border-border/60 bg-muted/40 pr-1 pl-2.5 text-foreground text-xs\"\n >\n {chip.label}\n <button\n type=\"button\"\n aria-label={`Remove filter ${chip.label}`}\n onClick={() => removeChip(chip.field)}\n className={cn('rounded-full p-0.5 text-muted-foreground hover:bg-muted hover:text-foreground', FOCUS_RING_CLASS)}\n >\n <XIcon className=\"size-3\" aria-hidden />\n </button>\n </span>\n ))}\n {hasFilters ? (\n <button type=\"button\" onClick={clearFilters} className={cn('px-1.5 text-muted-foreground text-xs hover:text-foreground', FOCUS_RING_CLASS)}>\n Clear\n </button>\n ) : null}\n <div className=\"flex-1\" />\n {savedDefault !== null && !isSavedDefault ? (\n <button type=\"button\" onClick={resetToDefault} className={cn('px-1.5 text-muted-foreground text-xs hover:text-foreground', FOCUS_RING_CLASS)}>\n Reset to default\n </button>\n ) : null}\n <button\n type=\"button\"\n onClick={saveAsDefault}\n disabled={isSavedDefault}\n className={cn('px-1.5 text-muted-foreground text-xs hover:text-foreground disabled:opacity-50', FOCUS_RING_CLASS)}\n >\n {isSavedDefault ? 'Saved as default' : 'Save as default'}\n </button>\n </div>\n\n {sessions.degradedFields.length > 0 || sessions.unavailableFields.length > 0 ? (\n <p\n role=\"status\"\n data-testid=\"sessions-degraded\"\n className=\"rounded-md border border-amber-200 bg-amber-50 px-3 py-2 text-amber-900 text-xs\"\n >\n {sessions.degradedFields.length > 0\n ? `This Athena server cannot filter by ${fieldList(sessions.degradedFields)} yet, so they apply to the sessions loaded so far. `\n : ''}\n {sessions.unavailableFields.length > 0\n ? `Filtering by ${fieldList(sessions.unavailableFields)} is not available on this server yet and is off.`\n : ''}\n </p>\n ) : null}\n\n <div className=\"min-h-0 flex-1 overflow-auto\">\n {showSkeleton ? (\n <SessionListSkeleton rows={6} />\n ) : sections.length === 0 ? (\n <div data-testid=\"sessions-empty\" className=\"flex flex-col items-center gap-2 py-12 text-center\">\n <p className=\"text-muted-foreground text-sm\">\n {hasFilters || query.search ? 'No sessions match these filters.' : 'No sessions yet.'}\n </p>\n {hasFilters ? (\n <button type=\"button\" onClick={clearFilters} className={HEADER_BUTTON_CLASS}>\n Clear filters\n </button>\n ) : null}\n </div>\n ) : (\n <table className=\"w-full table-fixed border-collapse text-sm\" aria-busy={sessions.isFetching || undefined}>\n <thead>\n <tr className=\"border-border/60 border-b text-left text-[11px] text-muted-foreground uppercase tracking-wide\">\n <th scope=\"col\" className=\"py-2 pl-7 font-medium\">\n Session\n </th>\n {columns.map((id) => (\n <th key={id} scope=\"col\" className={cn('px-2 py-2 font-medium', COLUMN_WIDTH[id])}>\n {SESSIONS_COLUMNS.find((column) => column.id === id)?.label}\n </th>\n ))}\n <th scope=\"col\" className=\"w-24 py-2 pr-2\">\n <span className=\"sr-only\">Actions</span>\n </th>\n </tr>\n </thead>\n {sections.map((section) => (\n <tbody key={section.key} data-group={section.label ?? undefined}>\n {section.label ? (\n <tr>\n <th colSpan={columns.length + 2} scope=\"colgroup\" className={SECTION_HEADING_CLASS}>\n {section.label}\n <span className=\"ml-1.5 font-normal normal-case tracking-normal\">{section.items.length}</span>\n </th>\n </tr>\n ) : null}\n {section.items.map((row) => (\n <SessionsRow\n key={row.id}\n row={row}\n columns={columns}\n isActive={row.id === list.activeThreadId}\n labels={labels}\n list={list}\n onOpen={open}\n />\n ))}\n </tbody>\n ))}\n </table>\n )}\n {sessions.hasNextPage && !showSkeleton ? (\n <button\n type=\"button\"\n onClick={sessions.fetchNextPage}\n disabled={sessions.isFetchingNextPage}\n className={cn('mt-2 w-full rounded-md py-2 text-muted-foreground text-xs transition-colors hover:bg-muted disabled:opacity-50', FOCUS_RING_CLASS)}\n >\n {sessions.isFetchingNextPage ? 'Loading…' : sessions.isFetchNextPageError ? 'Retry loading more' : 'Load more'}\n </button>\n ) : null}\n </div>\n </div>\n );\n}\n\n/**\n * A full-page session list with server-side filters, display options, an\n * attention-coloured status column and CSV export. Renders nothing outside\n * `<AthenaProvider enableThreadList>`.\n */\nexport function SessionsPage(props: SessionsPageProps) {\n const list = useAthenaStatewireThreadList();\n const live = useContext(AthenaSessionsLiveContext);\n if (!list || !live) return null;\n return <SessionsPageBody {...props} list={list} />;\n}\n"],"names":["_a"],"mappings":";;;;;;;;;;;;;AA+GA,MAAM,cAAwD;AAAA,EAC5D,QAAQ;AAAA,EACR,gBAAgB;AAAA,EAChB,kBAAkB;AAAA,EAClB,eAAe;AAAA,EACf,cAAc;AAAA,EACd,eAAe;AAAA,EACf,cAAc;AAAA,EACd,eAAe;AAAA,EACf,eAAe;AAAA,EACf,YAAY;AAAA,EACZ,aAAa;AAAA,EACb,iBAAiB;AAAA,EACjB,iBAAiB;AAAA,EACjB,aAAa;AAAA,EACb,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB,MAAM;AAAA,EACN,WAAW;AACb;AAGA,SAAS,UAAU,QAAqD;AACtE,QAAM,QAAQ,CAAC,GAAG,IAAI,IAAI,OAAO,IAAI,CAAC,UAAU,YAAY,KAAK,CAAC,CAAC,CAAC;AACpE,SAAO,MAAM,UAAU,IAAK,MAAM,CAAC,KAAK,KAAM,GAAG,MAAM,MAAM,GAAG,EAAE,EAAE,KAAK,IAAI,CAAC,QAAQ,MAAM,GAAG,EAAE,CAAC;AACpG;AAEA,MAAM,eAAiD;AAAA,EACrD,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,MAAM;AAAA,EACN,cAAc;AAAA,EACd,SAAS;AAAA,EACT,SAAS;AAAA,EACT,SAAS;AACX;AAGA,SAAS,aAAa,UAAkB,MAAc,MAAoB;AACxE,MAAI,OAAO,aAAa,YAAa;AACrC,QAAM,MAAM,IAAI,gBAAgB,IAAI,KAAK,CAAC,IAAI,GAAG,EAAE,KAAA,CAAM,CAAC;AAC1D,QAAM,SAAS,SAAS,cAAc,GAAG;AACzC,SAAO,OAAO;AACd,SAAO,WAAW;AAClB,SAAO,MAAM;AACb,WAAS,KAAK,YAAY,MAAM;AAChC,SAAO,MAAA;AACP,SAAO,OAAA;AACP,aAAW,MAAM,IAAI,gBAAgB,GAAG,GAAG,CAAC;AAC9C;AAEA,MAAM,wBACJ;AAGF,MAAM,aAMD,CAAC,EAAE,OAAO,UAAU,UAAU,WAAW,OAAO,OAAO,mBAAA,MAC1D;AAAA,EAAC;AAAA,EAAA;AAAA,IACC,MAAK;AAAA,IACL;AAAA,IACA,gBAAc;AAAA,IACd;AAAA,IACA,SAAS;AAAA,IACT,WAAW;AAAA,MACT;AAAA,MACA;AAAA,IAAA;AAAA,IAGF,UAAA;AAAA,MAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,eAAY;AAAA,UACZ,WAAW;AAAA,YACT;AAAA,YACA,YAAY;AAAA,UAAA;AAAA,UAGb,UAAA,WAAW,oBAAC,WAAA,EAAU,WAAU,UAAS,IAAK;AAAA,QAAA;AAAA,MAAA;AAAA,MAEjD,oBAAC,QAAA,EAAK,WAAU,YAAY,UAAA,MAAA,CAAM;AAAA,IAAA;AAAA,EAAA;AACpC;AAGF,MAAM,cAAgF,CAAC;AAAA,EACrF;AAAA,EACA;AAAA,EACA;AACF,MACE,qBAAC,WAAA,EAAQ,cAAY,OAAO,WAAU,QACpC,UAAA;AAAA,EAAA,oBAAC,MAAA,EAAG,WAAU,qFACX,UAAA,OACH;AAAA,EACC,OAAO,oBAAC,KAAA,EAAE,WAAU,+CAA+C,gBAAK,IAAO;AAAA,EAC/E;AAAA,GACH;AAGF,SAAS,YAA8B,QAAkC,OAAe;AACtF,QAAM,UAAU,UAAU,CAAA;AAC1B,SAAO,QAAQ,SAAS,KAAK,IAAI,QAAQ,OAAO,CAAC,SAAS,SAAS,KAAK,IAAI,CAAC,GAAG,SAAS,KAAK;AAChG;AAEA,SAAS,aAAa,OAA2B,QAA4B,SAAqG;AAChL,aAAW,UAAU,uBAAuB;AAC1C,UAAM,SAAS,QAAQ,OAAO,EAAE;AAChC,SAAK,OAAO,SAAS,YAAe,UAAU,OAAO,UAAU,YAAe,QAAQ;AACpF,aAAO,OAAO;AAAA,IAChB;AAAA,EACF;AACA,SAAO;AACT;AAYA,MAAM,mBAAmB;AAGzB,MAAM,aAAkC,CAAC;AAAA,EACvC;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,MAAM;;AAGJ,QAAM,CAAC,YAAY,IAAI;AAAA,IAAS,MAC9B,OAAO;AAAA,MACL,sBAAsB,IAAI,CAAC,WAAW,CAAC,OAAO,IAAI,iBAAiB,OAAO,EAAE,CAAC,CAAC;AAAA,IAAA;AAAA,EAChF;AAEF,QAAM,gBAAgB,aAAa,MAAM,cAAc,MAAM,eAAe,YAAY;AACxF,QAAM,gBAAgB,aAAa,MAAM,cAAc,MAAM,eAAe,YAAY;AACxF,QAAM,YAAY,CAChB,MACA,WAEA,SAAS,CAAC,YAAY;AACpB,UAAM,SAAS,SAAS,aAAa,MAAM,IAAI,CAAA;AAC/C,WAAO,SAAS,YACZ,EAAE,GAAG,SAAS,cAAc,OAAO,OAAO,eAAe,OAAO,WAChE,EAAE,GAAG,SAAS,cAAc,OAAO,OAAO,eAAe,OAAO,OAAA;AAAA,EACtE,CAAC;AACH,QAAM,eAAe,CAAC,UACpB,YAAY,IAAI,KAAK,IAAI,mBAAmB;AAE9C,8BACG,OAAA,EAAI,MAAK,QAAO,cAAW,WAAU,WAAU,oCAC9C,UAAA;AAAA,IAAA,oBAAC,aAAA,EAAY,OAAM,UAAS,MAAM,aAAa,aAAa,GACzD,UAAA,qBAAqB,IAAI,CAAC,WAAA;;AACzB;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,OAAO,eAAe,MAAM;AAAA,UAC5B,YAAUA,MAAA,MAAM,gBAAN,gBAAAA,IAAmB,SAAS,YAAW;AAAA,UACjD,UAAU,YAAY,IAAI,aAAa;AAAA,UACvC,UAAU,MACR,SAAS,CAAC,aAAa;AAAA,YACrB,GAAG;AAAA,YACH,aAAa,YAA8B,QAAQ,aAAa,MAAM;AAAA,UAAA,EACtE;AAAA,QAAA;AAAA,QARC;AAAA,MAAA;AAAA,KAWR,GACH;AAAA,wBACC,aAAA,EAAY,OAAM,iBAAgB,MAAM,aAAa,iBAAiB,GAEnE,UAAA;AAAA,MACE,CAAC,qBAAqB,IAAI;AAAA,MAC1B,CAAC,oBAAoB,KAAK;AAAA,IAAA,EAE5B,IAAI,CAAC,CAAC,OAAO,KAAK,MAClB;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,MAAK;AAAA,QACL;AAAA,QACA,UAAU,MAAM,oBAAoB;AAAA,QACpC,UAAU,YAAY,IAAI,iBAAiB;AAAA,QAC3C,UAAU,MACR,SAAS,CAAC,aAAa;AAAA,UACrB,GAAG;AAAA,UACH,iBAAiB,QAAQ,oBAAoB,QAAQ,SAAY;AAAA,QAAA,EACjE;AAAA,MAAA;AAAA,MATC;AAAA,IAAA,CAYR,GACH;AAAA,IACA,qBAAC,aAAA,EAAY,OAAM,mBACjB,UAAA;AAAA,MAAA;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,OAAM;AAAA,UACN,UAAU,MAAM,eAAe;AAAA,UAC/B,UAAU,YAAY,IAAI,YAAY;AAAA,UACtC,UAAU,MAAM,SAAS,CAAC,aAAa,EAAE,GAAG,SAAS,YAAY,CAAC,QAAQ,aAAa;AAAA,QAAA;AAAA,MAAA;AAAA,MAEzF;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,OAAM;AAAA,UACN,UAAU,MAAM,kBAAkB;AAAA,UAClC,UAAU,YAAY,IAAI,eAAe;AAAA,UACzC,UAAU,MACR,SAAS,CAAC,aAAa,EAAE,GAAG,SAAS,eAAe,CAAC,QAAQ,gBAAgB;AAAA,QAAA;AAAA,MAAA;AAAA,IAEjF,GACF;AAAA,yBACC,aAAA,EAAY,OAAM,WAAU,MAAM,aAAa,aAAa,GAEzD,UAAA;AAAA,MAAA;AAAA,QACE,CAAC,OAAO,IAAI;AAAA,QACZ,CAAC,mBAAmB,KAAK;AAAA,MAAA,EAE3B,IAAI,CAAC,CAAC,OAAO,KAAK,MAClB;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,MAAK;AAAA,UACL;AAAA,UACA,UAAU,MAAM,gBAAgB;AAAA,UAChC,UAAU,YAAY,IAAI,aAAa;AAAA,UACvC,UAAU,MACR,SAAS,CAAC,aAAa;AAAA,YACrB,GAAG;AAAA,YACH,aAAa,QAAQ,gBAAgB,QAAQ,SAAY;AAAA,UAAA,EACzD;AAAA,QAAA;AAAA,QATC;AAAA,MAAA,CAYR;AAAA,MACD;AAAA,QAAC;AAAA,QAAA;AAAA,UACC,OAAM;AAAA,UACN,UAAU,MAAM,qBAAqB;AAAA,UACrC,UAAU,MACR,SAAS,CAAC,aAAa,EAAE,GAAG,SAAS,kBAAkB,CAAC,QAAQ,mBAAmB;AAAA,QAAA;AAAA,MAAA;AAAA,IAEvF,GACF;AAAA,IACC,aAAa,SAAS,IACrB,oBAAC,eAAY,OAAM,SAAQ,MAAM,aAAa,gBAAgB,GAC3D,UAAA,aAAa,IAAI,CAAC;;AACjB;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,OAAO,WAAW,SAAS,MAAM;AAAA,UACjC,YAAUA,MAAA,MAAM,mBAAN,gBAAAA,IAAsB,SAAS,aAAY;AAAA,UACrD,UAAU,YAAY,IAAI,gBAAgB;AAAA,UAC1C,UAAU,MACR,SAAS,CAAC,aAAa;AAAA,YACrB,GAAG;AAAA,YACH,gBAAgB,YAAY,QAAQ,gBAAgB,OAAO;AAAA,UAAA,EAC3D;AAAA,QAAA;AAAA,QARC;AAAA,MAAA;AAAA,KAWR,GACH,IACE;AAAA,IACH,aAAa,SAAS,IACrB;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,OAAM;AAAA,QACN,MACE,aAAa,kBAAkB,QAC9B,WAAM,mBAAN,mBAAsB,UAAS,OAAO;AAAA,QAGxC,UAAA,eAAe,IAAI,CAAC,cAAA;;AACnB;AAAA,YAAC;AAAA,YAAA;AAAA,cAEC,OAAO,aAAa,WAAW,MAAM;AAAA,cACrC,YAAUA,MAAA,MAAM,qBAAN,gBAAAA,IAAwB,SAAS,eAAc;AAAA,cACzD,UAAU,YAAY,IAAI,kBAAkB,KAAK,GAAC,WAAM,mBAAN,mBAAsB;AAAA,cACxE,UAAU,MACR,SAAS,CAAC,aAAa;AAAA,gBACrB,GAAG;AAAA,gBACH,kBAAkB,YAAY,QAAQ,kBAAkB,SAAS;AAAA,cAAA,EACjE;AAAA,YAAA;AAAA,YARC;AAAA,UAAA;AAAA,SAWR;AAAA,MAAA;AAAA,IAAA,IAED;AAAA,IACH,cAAc,SAAS,IACtB,oBAAC,eAAY,OAAM,UAAS,MAAM,aAAa,eAAe,GAC3D,UAAA,cAAc,IAAI,CAAC;;AAClB;AAAA,QAAC;AAAA,QAAA;AAAA,UAEC,OAAO,mBAAmB,EAAE,cAAc,SAAS,OAAO,MAAM,aAAa,KAAA,CAAM,KAAK;AAAA,UACxF,YAAUA,MAAA,MAAM,kBAAN,gBAAAA,IAAqB,SAAS,aAAY;AAAA,UACpD,UAAU,YAAY,IAAI,eAAe;AAAA,UACzC,UAAU,MACR,SAAS,CAAC,aAAa;AAAA,YACrB,GAAG;AAAA,YACH,eAAe,YAAY,QAAQ,eAAe,OAAO;AAAA,UAAA,EACzD;AAAA,QAAA;AAAA,QARC;AAAA,MAAA;AAAA,KAWR,GACH,IACE;AAAA,wBACH,aAAA,EAAY,OAAM,WAChB,UAAA,sBAAsB,IAAI,CAAC,WAC1B;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,MAAK;AAAA,QACL,OAAO,OAAO;AAAA,QACd,UAAU,kBAAkB,OAAO;AAAA,QACnC,UAAU,MAAM,UAAU,WAAW,kBAAkB,OAAO,KAAK,OAAO,OAAO,EAAE;AAAA,MAAA;AAAA,MAJ9E,OAAO;AAAA,IAAA,CAMf,GACH;AAAA,wBACC,aAAA,EAAY,OAAM,WAChB,UAAA,sBAAsB,IAAI,CAAC,WAC1B;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,MAAK;AAAA,QACL,OAAO,OAAO;AAAA,QACd,UAAU,kBAAkB,OAAO;AAAA,QACnC,UAAU,MAAM,UAAU,WAAW,kBAAkB,OAAO,KAAK,OAAO,OAAO,EAAE;AAAA,MAAA;AAAA,MAJ9E,OAAO;AAAA,IAAA,CAMf,EAAA,CACH;AAAA,EAAA,GACF;AAEJ;AAEA,MAAM,cAKD,CAAC,EAAE,OAAO,UAAU,SAAS,iBAAiB;AACjD,QAAM,OAAO,MAAM,QAAQ;AAC3B,QAAM,YAAY,MAAM,aAAa;AACrC,8BACG,OAAA,EAAI,MAAK,QAAO,cAAW,mBAAkB,WAAU,OACtD,UAAA;AAAA,IAAA,oBAAC,aAAA,EAAY,OAAM,WAEf,UAAA;AAAA,MACE,CAAC,WAAW,cAAc;AAAA,MAC1B,CAAC,WAAW,SAAS;AAAA,IAAA,EAEvB,IAAI,CAAC,CAAC,OAAO,KAAK,MAClB;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,MAAK;AAAA,QACL;AAAA,QACA,UAAU,SAAS;AAAA,QACnB,UAAU,MAAM,SAAS,CAAC,aAAa,EAAE,GAAG,SAAS,MAAM,QAAQ;AAAA,MAAA;AAAA,MAJ9D;AAAA,IAAA,CAMR,GACH;AAAA,IACA,oBAAC,aAAA,EAAY,OAAM,SAEf,UAAA;AAAA,MACE,CAAC,QAAQ,cAAc;AAAA,MACvB,CAAC,OAAO,cAAc;AAAA,IAAA,EAExB,IAAI,CAAC,CAAC,OAAO,KAAK,MAClB;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,MAAK;AAAA,QACL;AAAA,QACA,UAAU,cAAc;AAAA,QACxB,UAAU,MAAM,SAAS,CAAC,aAAa,EAAE,GAAG,SAAS,WAAW,QAAQ;AAAA,MAAA;AAAA,MAJnE;AAAA,IAAA,CAMR,GACH;AAAA,IACA,oBAAC,aAAA,EAAY,OAAM,YAEf,UAAA;AAAA,MACE,CAAC,aAAa,eAAe;AAAA,MAC7B,CAAC,UAAU,YAAY;AAAA,MACvB,CAAC,QAAQ,aAAa;AAAA,IAAA,EAExB,IAAI,CAAC,CAAC,OAAO,KAAK,MAClB;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,MAAK;AAAA,QACL;AAAA,QACA,UAAU,QAAQ,YAAY;AAAA,QAC9B,UAAU,MAAM,WAAW,CAAC,aAAa,EAAE,GAAG,SAAS,SAAS,QAAQ;AAAA,MAAA;AAAA,MAJnE;AAAA,IAAA,CAMR,GACH;AAAA,wBACC,aAAA,EAAY,OAAM,WAChB,UAAA,iBAAiB,IAAI,CAAC,WACrB;AAAA,MAAC;AAAA,MAAA;AAAA,QAEC,OAAO,OAAO;AAAA,QACd,UAAU,QAAQ,QAAQ,SAAS,OAAO,EAAE;AAAA,QAC5C,UAAU,MACR,WAAW,CAAC,aAAa;AAAA,UACvB,GAAG;AAAA,UACH,SAAS,QAAQ,QAAQ,SAAS,OAAO,EAAE,IACvC,QAAQ,QAAQ,OAAO,CAAC,OAAO,OAAO,OAAO,EAAE,IAC/C,iBAAiB,IAAI,CAAC,cAAc,UAAU,EAAE,EAAE;AAAA,YAChD,CAAC,OAAO,OAAO,OAAO,MAAM,QAAQ,QAAQ,SAAS,EAAE;AAAA,UAAA;AAAA,QACzD,EACJ;AAAA,MAAA;AAAA,MAXC,OAAO;AAAA,IAAA,CAcf,EAAA,CACH;AAAA,EAAA,GACF;AAEJ;AAEA,MAAM,sBAAsB;AAAA,EAC1B;AAAA,EACA;AACF;AAEA,MAAM,cAOD,CAAC,EAAE,KAAK,SAAS,UAAU,QAAQ,MAAM,aAAa;AACzD,QAAM,SAAS,kBAAkB,GAAG;AACpC,QAAM,UAAU,aAAa,IAAI,OAAO;AACxC,QAAM,OAAO,gBAAgB,IAAI,YAAY;AAC7C,QAAM,SAAS,mBAAmB,GAAG;AACrC,QAAM,OAAO,CAAC,OAAoC;AAChD,YAAQ,IAAA;AAAA,MACN,KAAK;AACH,eAAO,oBAAC,YAAA,EAAW,OAAO,OAAO,OAAO,MAAM,OAAO,MAAM,QAAQ,OAAO,OAAA,CAAQ;AAAA,MACpF,KAAK;AACH,eAAO,SACL,oBAAC,QAAA,EAAK,WAAU,uFACb,kBACH,IACE;AAAA,MACN,KAAK;AACH,eAAO,IAAI,gBACT,oBAAC,QAAA,EAAK,WAAU,0CACb,UAAA,aAAa,IAAI,iBAAiB,MAAM,EAAA,CAC3C,IACE;AAAA,MACN,KAAK;AACH,eAAO,2BAAQ,iBAAA,EAAgB,MAAY,cAAc,IAAI,gBAAgB,GAAC,CAAG,IAAK;AAAA,MACxF,KAAK;AACH,mCACG,QAAA,EAAK,WAAU,0CAA0C,UAAA,aAAa,IAAI,WAAW,GAAE;AAAA,MAE5F,KAAK;AACH,eACE,oBAAC,QAAA,EAAK,WAAU,iCACb,UAAA,IAAI,YAAY,aAAa,IAAI,SAAS,IAAI,GAAA,CACjD;AAAA,MAEJ,KAAK;AACH,mCAAQ,QAAA,EAAK,WAAU,iCAAiC,UAAA,aAAa,IAAI,SAAS,GAAE;AAAA,IAAA;AAAA,EAE1F;AACA,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,kBAAgB,IAAI;AAAA,MACpB,eAAa,YAAY;AAAA,MACzB,eAAa,IAAI,YAAY;AAAA,MAC7B,SAAS,MAAM,OAAO,GAAG;AAAA,MACzB,WAAW;AAAA,QACT;AAAA,QACA,YAAY;AAAA,MAAA;AAAA,MAGd,UAAA;AAAA,QAAA,qBAAC,MAAA,EAAG,WAAU,oCACZ,UAAA;AAAA,UAAA,qBAAC,OAAA,EAAI,WAAU,mCACb,UAAA;AAAA,YAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,MAAM,IAAI,WAAW,QAAQ;AAAA,gBAC7B,cAAY,IAAI,WAAW,WAAW;AAAA,gBACtC,eAAa,IAAI,WAAW,SAAY;AAAA,gBACxC,WAAW,GAAG,gCAAgC,IAAI,WAAW,eAAe,gBAAgB;AAAA,cAAA;AAAA,YAAA;AAAA,YAE9F;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,MAAK;AAAA,gBACL,SAAS,CAAC,UAAU;AAClB,wBAAM,gBAAA;AACN,yBAAO,GAAG;AAAA,gBACZ;AAAA,gBACA,WAAW;AAAA,kBACT;AAAA,kBACA,IAAI,WAAW,kBAAkB;AAAA,kBACjC;AAAA,gBAAA;AAAA,gBAGD,cAAI,SAAS;AAAA,cAAA;AAAA,YAAA;AAAA,YAEf,IAAI,cACH,oBAAC,SAAA,EAAQ,MAAK,OAAM,cAAW,UAAS,WAAU,qDAAA,CAAqD,IACrG;AAAA,UAAA,GACN;AAAA,UACC,UAAU,oBAAC,KAAA,EAAE,WAAU,sDAAsD,mBAAQ,IAAO;AAAA,QAAA,GAC/F;AAAA,QACC,QAAQ,IAAI,CAAC,2BACX,MAAA,EAAY,eAAa,IAAI,WAAU,wCACrC,UAAA,KAAK,EAAE,EAAA,GADD,EAET,CACD;AAAA,QACD,oBAAC,QAAG,WAAU,yBACZ,+BAAC,OAAA,EAAI,oBAAgB,MAAC,WAAU,yCAC9B,UAAA;AAAA,UAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO,IAAI,WAAW,cAAc;AAAA,cACpC,QAAO;AAAA,cACP,SAAS,KAAK,0BAA0B,IAAI,IAAI,EAAE;AAAA,cAClD,SAAS,MACP,KAAK,aAAa,EAAE,UAAU,IAAI,IAAI,UAAU,CAAC,IAAI,UAAU,WAAW,IAAI,WAAW;AAAA,cAG1F,UAAA,IAAI,WAAW,oBAAC,cAAA,EAAa,WAAU,YAAW,eAAW,KAAA,CAAC,IAAK,oBAAC,UAAA,EAAS,WAAU,YAAW,eAAW,KAAA,CAAC;AAAA,YAAA;AAAA,UAAA;AAAA,UAEhH,KAAK,0BACJ;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAO,IAAI,cAAc,kBAAkB;AAAA,cAC3C,QAAO;AAAA,cACP,SAAS,IAAI;AAAA,cACb,SAAS,KAAK,yBAAyB,IAAI,IAAI,EAAE;AAAA,cACjD,SAAS,MAAM,KAAK,aAAa,EAAE,UAAU,IAAI,IAAI,aAAa,CAAC,IAAI,YAAA,CAAa;AAAA,cAEpF,UAAA,oBAAC,SAAA,EAAQ,WAAW,GAAG,YAAY,IAAI,eAAe,cAAc,GAAG,eAAW,KAAA,CAAC;AAAA,YAAA;AAAA,UAAA,IAEnF;AAAA,UACH,KAAK,mBACJ;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,OAAM;AAAA,cACN,QAAO;AAAA,cACP,SAAS,KAAK,wBAAwB,IAAI,IAAI,EAAE;AAAA,cAChD,SAAS,MAAM,KAAK,cAAc,IAAI,EAAE;AAAA,cAExC,UAAA,oBAAC,aAAA,EAAY,WAAU,YAAW,eAAW,KAAA,CAAC;AAAA,YAAA;AAAA,UAAA,IAE9C;AAAA,QAAA,EAAA,CACN,EAAA,CACF;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;AAEA,SAAS,iBAAiB;AAAA,EACxB;AAAA,EACA,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA,aAAa;AAAA,EACb;AAAA,EACA,uBAAuB;AAAA,EACvB;AAAA,EACA,iBAAiB;AAAA,EACjB;AAAA,EACA;AACF,GAAiE;AAC/D,QAAM,CAAC,OAAO,IAAI;AAAA,IAAS,MACzB,yBAAyB,YAAY;AAAA,MACnC,GAAG;AAAA,MACH,SAAS,uBAAuB,oBAAoB;AAAA,IAAA,CACrD;AAAA,EAAA;AAEH,QAAM,CAAC,cAAc,eAAe,IAAI,SAAqC,QAAQ,YAAY;AACjG,QAAM,CAAC,OAAO,aAAa,IAAI;AAAA,IAC7B,MAAM,QAAQ,gBAAgB,uBAAuB,gBAAgB,CAAA,CAAE;AAAA,EAAA;AAEzE,QAAM,CAAC,SAAS,eAAe,IAAI,SAA8B,QAAQ,OAAO;AAChF,QAAM,CAAC,aAAa,cAAc,IAAI,SAAS,MAAM,UAAU,EAAE;AAEjE,QAAM,WAAW,CAAC,WAChB,cAAc,CAAC,YAAY,uBAAuB,OAAO,OAAO,CAAC,CAAC;AACpE,QAAM,aAAa,CAAC,WAClB,gBAAgB,CAAC,YAAY;AAC3B,UAAM,OAAO,OAAO,OAAO;AAC3B,8BAA0B,YAAY,EAAE,cAAc,cAAc,SAAS,MAAM;AACnF,WAAO;AAAA,EACT,CAAC;AAGH,YAAU,MAAM;AACd,UAAM,SAAS,WAAW,MAAM;AAC9B,oBAAc,CAAC,YAAY;AACzB,cAAM,SAAS,YAAY,KAAA;AAC3B,aAAK,QAAQ,UAAU,QAAQ,OAAQ,QAAO;AAC9C,eAAO,uBAAuB,EAAE,GAAG,SAAS,QAAQ;AAAA,MACtD,CAAC;AAAA,IACH,GAAG,GAAG;AACN,WAAO,MAAM,aAAa,MAAM;AAAA,EAClC,GAAG,CAAC,WAAW,CAAC;AAEhB,QAAM,WAAW,kBAAkB,EAAE,OAAO,GAAI,WAAW,EAAE,aAAa,CAAA,GAAK;AAC/E,QAAM,cAAc;AAAA,IAClB,MAAM,oBAAI,IAAI,CAAC,GAAG,SAAS,mBAAmB,GAAG,SAAS,iBAAiB,CAAC;AAAA,IAC5E,CAAC,SAAS,mBAAmB,SAAS,iBAAiB;AAAA,EAAA;AAKzD,QAAM,UAAU,OAAO,EAAE,4BAAY,IAAA,GAAe,UAAU,oBAAI,OAAe,SAAS,oBAAI,IAAA,GAAe;AAC7G,aAAW,OAAO,SAAS,MAAM;AAC/B,QAAI,IAAI,eAAe;AACrB,cAAQ,QAAQ,OAAO,IAAI,IAAI,aAAa;AAC5C,cAAQ,QAAQ,SAAS,IAAI,IAAI,mBAAmB,sBAAsB;AAAA,IAC5E;AACA,QAAI,IAAI,aAAc,SAAQ,QAAQ,QAAQ,IAAI,IAAI,YAAY;AAAA,EACpE;AACA,QAAM,eAAe;AAAA,IACnB,uBAAO,IAAI,CAAC,GAAG,OAAO,MAAK,iCAAQ,WAAU,CAAA,CAAE,GAAG,GAAG,QAAQ,QAAQ,QAAQ,GAAI,MAAM,kBAAkB,EAAG,CAAC;AAAA,EAAA;AAE/G,QAAM,iBAAiB;AAAA,IACrB,uBAAO,IAAI;AAAA,MACT;AAAA,MACA,GAAG,OAAO,MAAK,iCAAQ,aAAY,CAAA,CAAE;AAAA,MACrC,GAAG,QAAQ,QAAQ;AAAA,MACnB,GAAI,MAAM,oBAAoB,CAAA;AAAA,IAAC,CAChC;AAAA,EAAA;AAEH,QAAM,gBAAgB,CAAC,GAAG,oBAAI,IAAI,CAAC,GAAG,QAAQ,QAAQ,SAAS,GAAI,MAAM,iBAAiB,CAAA,CAAG,CAAC,CAAC;AAE/F,QAAM,QAAQ,oBAAoB,OAAO,MAAM;AAC/C,QAAM,WAAW,gBAAgB,SAAS,MAAM,QAAQ,OAAO;AAC/D,QAAM,UAAU,iBAAiB,IAAI,CAAC,WAAW,OAAO,EAAE,EAAE,OAAO,CAAC,OAAO,QAAQ,QAAQ,SAAS,EAAE,CAAC;AACvG,QAAM,EAAE,QAAQ,SAAS,GAAG,uBAAuB;AACnD,QAAM,iBACJ,iBAAiB,QAAQ,iBAAiB,YAAY,MAAM,iBAAiB,kBAAkB;AACjG,QAAM,aAAa,MAAM,SAAS;AAElC,QAAM,OAAO,CAAC,QAAsC;AAClD,SAAK,aAAa,IAAI,EAAE;AACxB,mDAAgB,EAAE,UAAU,IAAI,IAAI,OAAO,IAAI;EACjD;AACA,QAAM,gBAAgB,MAAM;AAC1B,UAAM,QAAQ,uBAAuB,kBAAkB;AACvD,oBAAgB,KAAK;AACrB,8BAA0B,YAAY,EAAE,cAAc,OAAO,SAAS;AAAA,EACxE;AACA,QAAM,iBAAiB,MAAM;AAC3B,kBAAc,EAAE,GAAI,gBAAgB,uBAAuB,gBAAgB,CAAA,CAAE,GAAI;AACjF,mBAAe,EAAE;AAAA,EACnB;AACA,QAAM,eAAe,MAAM;AACzB,aAAS,CAAC,aAAa,EAAE,MAAM,QAAQ,MAAM,WAAW,QAAQ,WAAW,QAAQ,QAAQ,OAAA,EAAS;AAAA,EACtG;AACA,QAAM,aAAa,CAAC,UAClB,SAAS,CAAC,YAAY;AACpB,UAAM,OAA4B,EAAE,GAAG,SAAS,CAAC,KAAK,GAAG,OAAA;AACzD,QAAI,UAAU,iBAAkB,MAAK,mBAAmB;AACxD,WAAO;AAAA,EACT,CAAC;AACH,QAAM,YAAY,MAChB;AAAA,IACE,iCAAgB,QAAO,cAAc,MAAM,GAAG,EAAE,CAAC;AAAA,IACjD,YAAY,SAAS,MAAM,MAAM;AAAA,IACjC;AAAA,EAAA;AAKJ,QAAM,eACJ,SAAS,KAAK,WAAW,MAAM,CAAC,SAAS,wBAAwB,SAAS;AAE5E,SACE;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,eAAY;AAAA,MACZ,WAAW,GAAG,qDAAqD,SAAS;AAAA,MAE5E,UAAA;AAAA,QAAA,qBAAC,OAAA,EAAI,WAAU,qCACb,UAAA;AAAA,UAAA,oBAAC,MAAA,EAAG,WAAU,2CAA2C,UAAA,OAAM;AAAA,UAC/D,qBAAC,QAAA,EAAK,eAAY,kBAAiB,WAAU,iCAC1C,UAAA;AAAA,YAAA,SAAS,KAAK;AAAA,YACd,SAAS,cAAc,MAAM;AAAA,UAAA,GAChC;AAAA,UACA,oBAAC,OAAA,EAAI,WAAU,SAAA,CAAS;AAAA,UACxB,qBAAC,SAAA,EAAM,WAAU,kCACf,UAAA;AAAA,YAAA,oBAAC,YAAA,EAAW,WAAU,gGAAA,CAAgG;AAAA,YACtH,oBAAC,QAAA,EAAK,WAAU,WAAU,UAAA,mBAAe;AAAA,YACzC;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC,MAAK;AAAA,gBACL,OAAO;AAAA,gBACP,UAAU,CAAC,UAAU,eAAe,MAAM,OAAO,KAAK;AAAA,gBACtD,aAAY;AAAA,gBACZ,WAAU;AAAA,cAAA;AAAA,YAAA;AAAA,UACZ,GACF;AAAA,+BACC,SAAA,EACC,UAAA;AAAA,YAAA,oBAAC,gBAAA,EAAe,SAAO,MACrB,UAAA,qBAAC,UAAA,EAAO,MAAK,UAAS,WAAW,qBAAqB,cAAW,mBAC/D,UAAA;AAAA,cAAA,oBAAC,uBAAA,EAAsB,WAAU,YAAW,eAAW,MAAC;AAAA,cAAE;AAAA,YAAA,EAAA,CAE5D,EAAA,CACF;AAAA,YACA,oBAAC,gBAAA,EAAe,OAAM,OAAM,WAAU,QACpC,UAAA,oBAAC,aAAA,EAAY,OAAc,UAAoB,SAAkB,WAAA,CAAwB,EAAA,CAC3F;AAAA,UAAA,GACF;AAAA,UACA;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS;AAAA,cACT,UAAU,SAAS,KAAK,WAAW;AAAA,cACnC,WAAW;AAAA,cACX,OAAM;AAAA,cAEN,UAAA;AAAA,gBAAA,oBAAC,cAAA,EAAa,WAAU,YAAW,eAAW,MAAC;AAAA,gBAAE;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAGnD;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS,SAAS;AAAA,cAClB,UAAU,SAAS;AAAA,cACnB,WAAW;AAAA,cACX,cAAW;AAAA,cACX,OAAM;AAAA,cAEN,UAAA,oBAAC,eAAA,EAAc,WAAW,GAAG,YAAY,SAAS,cAAc,cAAc,GAAG,eAAW,KAAA,CAAC;AAAA,YAAA;AAAA,UAAA;AAAA,UAE9F,iBACC;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS,MAAM;AACb,qBAAK,UAAA;AACL;AAAA,cACF;AAAA,cACA,WAAW;AAAA,gBACT;AAAA,gBACA;AAAA,cAAA;AAAA,cAGF,UAAA;AAAA,gBAAA,oBAAC,UAAA,EAAS,WAAU,YAAW,eAAW,MAAC;AAAA,gBAAE;AAAA,cAAA;AAAA,YAAA;AAAA,UAAA,IAG7C;AAAA,QAAA,GACN;AAAA,QAEA,qBAAC,OAAA,EAAI,WAAU,uCAAsC,eAAY,oBAC/D,UAAA;AAAA,UAAA,qBAAC,SAAA,EACC,UAAA;AAAA,YAAA,oBAAC,gBAAA,EAAe,SAAO,MACrB,UAAA,qBAAC,YAAO,MAAK,UAAS,WAAW,qBAC/B,UAAA;AAAA,cAAA,oBAAC,YAAA,EAAW,WAAU,YAAW,eAAW,MAAC;AAAA,cAAE;AAAA,YAAA,EAAA,CAEjD,EAAA,CACF;AAAA,YACA,oBAAC,gBAAA,EAAe,OAAM,SAAQ,WAAU,QACtC,UAAA;AAAA,cAAC;AAAA,cAAA;AAAA,gBACC;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,gBACA;AAAA,cAAA;AAAA,YAAA,EACF,CACF;AAAA,UAAA,GACF;AAAA,UACC,MAAM,IAAI,CAAC,SACV;AAAA,YAAC;AAAA,YAAA;AAAA,cAEC,oBAAkB,KAAK;AAAA,cACvB,WAAU;AAAA,cAET,UAAA;AAAA,gBAAA,KAAK;AAAA,gBACN;AAAA,kBAAC;AAAA,kBAAA;AAAA,oBACC,MAAK;AAAA,oBACL,cAAY,iBAAiB,KAAK,KAAK;AAAA,oBACvC,SAAS,MAAM,WAAW,KAAK,KAAK;AAAA,oBACpC,WAAW,GAAG,iFAAiF,gBAAgB;AAAA,oBAE/G,UAAA,oBAAC,OAAA,EAAM,WAAU,UAAS,eAAW,KAAA,CAAC;AAAA,kBAAA;AAAA,gBAAA;AAAA,cACxC;AAAA,YAAA;AAAA,YAZK,KAAK,QAAQ,KAAK;AAAA,UAAA,CAc1B;AAAA,UACA,aACC,oBAAC,UAAA,EAAO,MAAK,UAAS,SAAS,cAAc,WAAW,GAAG,8DAA8D,gBAAgB,GAAG,mBAE5I,IACE;AAAA,UACJ,oBAAC,OAAA,EAAI,WAAU,SAAA,CAAS;AAAA,UACvB,iBAAiB,QAAQ,CAAC,iBACzB,oBAAC,YAAO,MAAK,UAAS,SAAS,gBAAgB,WAAW,GAAG,8DAA8D,gBAAgB,GAAG,8BAE9I,IACE;AAAA,UACJ;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS;AAAA,cACT,UAAU;AAAA,cACV,WAAW,GAAG,kFAAkF,gBAAgB;AAAA,cAE/G,2BAAiB,qBAAqB;AAAA,YAAA;AAAA,UAAA;AAAA,QACzC,GACF;AAAA,QAEC,SAAS,eAAe,SAAS,KAAK,SAAS,kBAAkB,SAAS,IACzE;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,eAAY;AAAA,YACZ,WAAU;AAAA,YAET,UAAA;AAAA,cAAA,SAAS,eAAe,SAAS,IAC9B,uCAAuC,UAAU,SAAS,cAAc,CAAC,wDACzE;AAAA,cACH,SAAS,kBAAkB,SAAS,IACjC,gBAAgB,UAAU,SAAS,iBAAiB,CAAC,qDACrD;AAAA,YAAA;AAAA,UAAA;AAAA,QAAA,IAEJ;AAAA,QAEJ,qBAAC,OAAA,EAAI,WAAU,gCACZ,UAAA;AAAA,UAAA,eACC,oBAAC,qBAAA,EAAoB,MAAM,EAAA,CAAG,IAC5B,SAAS,WAAW,IACtB,qBAAC,OAAA,EAAI,eAAY,kBAAiB,WAAU,sDAC1C,UAAA;AAAA,YAAA,oBAAC,OAAE,WAAU,iCACV,wBAAc,MAAM,SAAS,qCAAqC,mBAAA,CACrE;AAAA,YACC,aACC,oBAAC,UAAA,EAAO,MAAK,UAAS,SAAS,cAAc,WAAW,qBAAqB,UAAA,gBAAA,CAE7E,IACE;AAAA,UAAA,EAAA,CACN,yBAEC,SAAA,EAAM,WAAU,8CAA6C,aAAW,SAAS,cAAc,QAC9F,UAAA;AAAA,YAAA,oBAAC,SAAA,EACC,UAAA,qBAAC,MAAA,EAAG,WAAU,iGACZ,UAAA;AAAA,cAAA,oBAAC,MAAA,EAAG,OAAM,OAAM,WAAU,yBAAwB,UAAA,WAElD;AAAA,cACC,QAAQ,IAAI,CAAC,OAAA;;AACZ,2CAAC,QAAY,OAAM,OAAM,WAAW,GAAG,yBAAyB,aAAa,EAAE,CAAC,GAC7E,WAAA,sBAAiB,KAAK,CAAC,WAAW,OAAO,OAAO,EAAE,MAAlD,mBAAqD,MAAA,GAD/C,EAET;AAAA,eACD;AAAA,cACD,oBAAC,MAAA,EAAG,OAAM,OAAM,WAAU,kBACxB,UAAA,oBAAC,QAAA,EAAK,WAAU,WAAU,UAAA,UAAA,CAAO,EAAA,CACnC;AAAA,YAAA,EAAA,CACF,EAAA,CACF;AAAA,YACC,SAAS,IAAI,CAAC,iCACZ,SAAA,EAAwB,cAAY,QAAQ,SAAS,QACnD,UAAA;AAAA,cAAA,QAAQ,QACP,oBAAC,MAAA,EACC,UAAA,qBAAC,MAAA,EAAG,SAAS,QAAQ,SAAS,GAAG,OAAM,YAAW,WAAW,uBAC1D,UAAA;AAAA,gBAAA,QAAQ;AAAA,oCACR,QAAA,EAAK,WAAU,kDAAkD,UAAA,QAAQ,MAAM,OAAA,CAAO;AAAA,cAAA,EAAA,CACzF,GACF,IACE;AAAA,cACH,QAAQ,MAAM,IAAI,CAAC,QAClB;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBAEC;AAAA,kBACA;AAAA,kBACA,UAAU,IAAI,OAAO,KAAK;AAAA,kBAC1B;AAAA,kBACA;AAAA,kBACA,QAAQ;AAAA,gBAAA;AAAA,gBANH,IAAI;AAAA,cAAA,CAQZ;AAAA,YAAA,EAAA,GAnBS,QAAQ,GAoBpB,CACD;AAAA,UAAA,GACH;AAAA,UAED,SAAS,eAAe,CAAC,eACxB;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,SAAS,SAAS;AAAA,cAClB,UAAU,SAAS;AAAA,cACnB,WAAW,GAAG,kHAAkH,gBAAgB;AAAA,cAE/I,UAAA,SAAS,qBAAqB,aAAa,SAAS,uBAAuB,uBAAuB;AAAA,YAAA;AAAA,UAAA,IAEnG;AAAA,QAAA,EAAA,CACN;AAAA,MAAA;AAAA,IAAA;AAAA,EAAA;AAGN;AAOO,SAAS,aAAa,OAA0B;AACrD,QAAM,OAAO,6BAAA;AACb,QAAM,OAAO,WAAW,yBAAyB;AACjD,MAAI,CAAC,QAAQ,CAAC,KAAM,QAAO;AAC3B,SAAO,oBAAC,kBAAA,EAAkB,GAAG,OAAO,KAAA,CAAY;AAClD;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-list-model.cjs","sources":["../../src/threads/session-list-model.ts"],"sourcesContent":["/**\n * Pure derivations behind `SessionList`: which group a session lands in,\n * which status indicator it shows, what its second line says, how its pull\n * requests collapse into one chip (and order in the list it opens), and how\n * its origin is labelled. Kept React-free so the render tests stay thin and\n * hosts that draw their own rows (`useAthenaSessionAttention`) can reuse the\n * same rules.\n */\nimport type { ConversationPullRequest } from '@athenaintel/agent-runtime';\nimport type { AthenaStatewireThreadSummary } from './statewire-thread-list';\n\nexport type SessionListGroup = 'Needs you' | 'Working' | 'Pinned' | 'Recent';\n\n/** Display order; a session appears once, in the FIRST group that applies. */\nexport const SESSION_LIST_GROUPS: readonly SessionListGroup[] = [\n 'Needs you',\n 'Working',\n 'Pinned',\n 'Recent',\n];\n\nexport function sessionListGroupOf(\n thread: Pick<AthenaStatewireThreadSummary, 'attention' | 'isFavorited'>,\n): SessionListGroup {\n if (thread.attention === 'needs_you') return 'Needs you';\n if (thread.attention === 'working') return 'Working';\n if (thread.isFavorited) return 'Pinned';\n return 'Recent';\n}\n\nexport interface SessionListSection {\n /** `null` for the single ungrouped section. */\n group: SessionListGroup | null;\n items: AthenaStatewireThreadSummary[];\n}\n\n/** Sections in display order; empty groups are omitted and row order is kept within a group. */\nexport function groupSessions(\n threads: readonly AthenaStatewireThreadSummary[],\n grouped: boolean,\n): SessionListSection[] {\n if (!grouped) return threads.length > 0 ? [{ group: null, items: [...threads] }] : [];\n const byGroup = new Map<SessionListGroup, AthenaStatewireThreadSummary[]>();\n for (const thread of threads) {\n const group = sessionListGroupOf(thread);\n const items = byGroup.get(group) ?? [];\n items.push(thread);\n byGroup.set(group, items);\n }\n return SESSION_LIST_GROUPS.flatMap((group) => {\n const items = byGroup.get(group);\n return items ? [{ group, items }] : [];\n });\n}\n\n/**\n * The status indicator at the head of a row: `needs_you` an orange dot,\n * `working` a spinner, `unread` (and not needs-you) a blue dot, `watching` a\n * clock, otherwise none. One indicator per row, in that precedence.\n */\nexport type SessionIndicator = 'needs_you' | 'working' | 'unread' | 'watching' | null;\n\nexport function sessionIndicator(\n thread: Pick<AthenaStatewireThreadSummary, 'attention' | 'isUnread'>,\n): SessionIndicator {\n if (thread.attention === 'needs_you') return 'needs_you';\n if (thread.attention === 'working') return 'working';\n if (thread.isUnread) return 'unread';\n if (thread.attention === 'watching') return 'watching';\n return null;\n}\n\nexport type SessionLineTone = 'needs_you' | 'ready' | 'error' | 'muted';\n\nexport interface SessionSecondaryLine {\n kind: 'next_action' | 'updated';\n text: string;\n tone: SessionLineTone;\n}\n\n/** \"5m ago\" / \"3h ago\" / \"2d ago\"; a locale date past a week; empty for an unparseable value. */\nexport function relativeTime(value: string, now: number = Date.now()): string {\n const timestamp = Date.parse(value);\n if (!Number.isFinite(timestamp)) return '';\n const minutes = Math.floor(Math.max(0, now - timestamp) / 60_000);\n if (minutes < 1) return 'just now';\n if (minutes < 60) return `${minutes}m ago`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours}h ago`;\n const days = Math.floor(hours / 24);\n return days < 7 ? `${days}d ago` : new Date(timestamp).toLocaleDateString();\n}\n\n/**\n * The row's second line: the server's next action coloured by attention\n * (needs-you orange, ready green, error red), else the muted relative time\n * of the last update.\n */\nexport function sessionSecondaryLine(\n thread: Pick<AthenaStatewireThreadSummary, 'attention' | 'nextAction' | 'updatedAt'>,\n now: number = Date.now(),\n): SessionSecondaryLine {\n const nextAction = thread.nextAction?.trim();\n if (nextAction) {\n const tone: SessionLineTone =\n thread.attention === 'needs_you'\n ? 'needs_you'\n : thread.attention === 'ready'\n ? 'ready'\n : thread.attention === 'error'\n ? 'error'\n : 'muted';\n return { kind: 'next_action', text: nextAction, tone };\n }\n return { kind: 'updated', text: relativeTime(thread.updatedAt, now), tone: 'muted' };\n}\n\nexport type PullRequestChipState = 'open' | 'draft' | 'merged' | 'closed';\n\nexport function pullRequestChipState(\n pullRequest: Pick<ConversationPullRequest, 'state' | 'isDraft'>,\n): PullRequestChipState {\n if (pullRequest.state === 'MERGED') return 'merged';\n if (pullRequest.state === 'CLOSED') return 'closed';\n return pullRequest.isDraft ? 'draft' : 'open';\n}\n\nexport interface PullRequestChip {\n /** State of the primary pull request (the one the chip links to). */\n state: PullRequestChipState;\n count: number;\n /** `#123` for one pull request, `3 PRs` for several. */\n label: string;\n url: string;\n title: string;\n checksState: ConversationPullRequest['checksState'];\n reviewDecision: string | null;\n}\n\nfunction pullRequestRank(pullRequest: ConversationPullRequest): number {\n return pullRequest.state === 'OPEN' ? (pullRequest.isDraft ? 1 : 0) : 2;\n}\n\nfunction updatedAtMs(pullRequest: ConversationPullRequest): number {\n const timestamp = Date.parse(pullRequest.updatedAt);\n return Number.isFinite(timestamp) ? timestamp : 0;\n}\n\n/**\n * A session's pull requests in the order its chip and its pull-request list\n * show them: the ones still in flight first (open before draft), then the\n * most recently updated. The first is the one the chip stands for.\n */\nexport function orderedPullRequests(\n pullRequests: readonly ConversationPullRequest[] | null | undefined,\n): ConversationPullRequest[] {\n if (!pullRequests) return [];\n return [...pullRequests].sort(\n (a, b) => pullRequestRank(a) - pullRequestRank(b) || updatedAtMs(b) - updatedAtMs(a),\n );\n}\n\n/** One chip per row, or `null` when the session opened no pull request (or none is known). */\nexport function pullRequestChip(\n pullRequests: readonly ConversationPullRequest[] | null | undefined,\n): PullRequestChip | null {\n if (!pullRequests || pullRequests.length === 0) return null;\n const primary = orderedPullRequests(pullRequests)[0];\n if (!primary) return null;\n return {\n state: pullRequestChipState(primary),\n count: pullRequests.length,\n label: pullRequests.length === 1 ? `#${primary.number}` : `${pullRequests.length} PRs`,\n url: primary.url,\n title: primary.title,\n checksState: primary.checksState,\n reviewDecision: primary.reviewDecision,\n };\n}\n\n/** The origin badge of a session started in the Athena web app (Olympus or an SDK app in a browser tab). */\nexport const WEB_APP_ORIGIN_LABEL = 'Athena';\n\n/**\n * Which rows `SessionList` badges with their origin: every one, only those\n * started somewhere other than the web app (Slack, GitHub, Chrome, an Office\n * host …), or none.\n */\nexport type SessionOriginBadges = 'all' | 'external' | 'none';\n\nconst CHANNEL_LABELS: Record<string, string> = {\n web: WEB_APP_ORIGIN_LABEL,\n olympus: WEB_APP_ORIGIN_LABEL,\n github: 'GitHub',\n api: 'API',\n email: 'Email',\n agent_email: 'Email',\n slack: 'Slack',\n sms: 'SMS',\n teams: 'Teams',\n task: 'Task',\n orchestration: 'Orchestration',\n computer: 'Computer',\n voice: 'Voice',\n mobile: 'Mobile',\n};\n\nfunction humanize(value: string): string {\n const words = value.replace(/^athena[-_]/, '').replace(/[-_.]+/g, ' ').trim();\n return words ? words.charAt(0).toUpperCase() + words.slice(1) : '';\n}\n\n/**\n * The origin badge: the client app when it is a recognizable surface\n * (Chrome, an Office host, mobile, a computer asset), else the start channel,\n * else a non-manual trigger; `null` when nothing is known.\n */\nexport function sessionOriginLabel(\n thread: Pick<AthenaStatewireThreadSummary, 'startChannel' | 'appId' | 'triggerType'>,\n): string | null {\n const appId = thread.appId?.trim().toLowerCase() ?? '';\n if (appId) {\n if (appId.includes('chrome')) return 'Chrome';\n if (appId.includes('powerpoint')) return 'PowerPoint';\n if (appId.includes('word')) return 'Word';\n if (appId.includes('excel')) return 'Excel';\n if (appId.includes('office')) return 'Office';\n if (appId.includes('mobile')) return 'Mobile';\n if (appId.startsWith('asset_')) return 'Computer';\n if (CHANNEL_LABELS[appId]) return CHANNEL_LABELS[appId];\n }\n const channel = thread.startChannel?.trim().toLowerCase() ?? '';\n if (channel) return CHANNEL_LABELS[channel] ?? humanize(channel);\n if (appId) return humanize(appId) || null;\n const trigger = thread.triggerType?.trim().toLowerCase() ?? '';\n if (trigger && trigger !== 'manual') return humanize(trigger) || null;\n return null;\n}\n\n/**\n * Client app ids that are the Athena web app itself: Olympus, and the\n * standalone app template, whose sessions carry no start channel when the\n * app does not report one (and would otherwise read as \"App\").\n */\nconst WEB_APP_IDS = new Set(['web', 'olympus', 'athena-app']);\n\n/** The origin badge a row shows under `badges` (`sessionOriginLabel`, filtered). */\nexport function sessionOriginBadge(\n thread: Pick<AthenaStatewireThreadSummary, 'startChannel' | 'appId' | 'triggerType'>,\n badges: SessionOriginBadges,\n): string | null {\n if (badges === 'none') return null;\n const origin = sessionOriginLabel(thread);\n if (badges === 'external') {\n const appId = thread.appId?.trim().toLowerCase() ?? '';\n if (origin === WEB_APP_ORIGIN_LABEL || WEB_APP_IDS.has(appId)) return null;\n }\n return origin;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"session-list-model.cjs","sources":["../../src/threads/session-list-model.ts"],"sourcesContent":["/**\n * Pure derivations behind `SessionList`: which group a session lands in,\n * which status indicator it shows, what its second line says, how its pull\n * requests collapse into one chip (and order in the list it opens), and how\n * its origin is labelled. Kept React-free so the render tests stay thin and\n * hosts that draw their own rows (`useAthenaSessionAttention`) can reuse the\n * same rules. Published alone as `@athenaintel/react/session-list-model`, so a\n * host's shell can draw a session's chips without loading the chat.\n */\nimport type { ConversationPullRequest } from '@athenaintel/agent-runtime';\nimport type { AthenaStatewireThreadSummary } from './statewire-thread-list';\n\nexport type SessionListGroup = 'Needs you' | 'Working' | 'Pinned' | 'Recent';\n\n/** Display order; a session appears once, in the FIRST group that applies. */\nexport const SESSION_LIST_GROUPS: readonly SessionListGroup[] = [\n 'Needs you',\n 'Working',\n 'Pinned',\n 'Recent',\n];\n\nexport function sessionListGroupOf(\n thread: Pick<AthenaStatewireThreadSummary, 'attention' | 'isFavorited'>,\n): SessionListGroup {\n if (thread.attention === 'needs_you') return 'Needs you';\n if (thread.attention === 'working') return 'Working';\n if (thread.isFavorited) return 'Pinned';\n return 'Recent';\n}\n\nexport interface SessionListSection {\n /** `null` for the single ungrouped section. */\n group: SessionListGroup | null;\n items: AthenaStatewireThreadSummary[];\n}\n\n/** Sections in display order; empty groups are omitted and row order is kept within a group. */\nexport function groupSessions(\n threads: readonly AthenaStatewireThreadSummary[],\n grouped: boolean,\n): SessionListSection[] {\n if (!grouped) return threads.length > 0 ? [{ group: null, items: [...threads] }] : [];\n const byGroup = new Map<SessionListGroup, AthenaStatewireThreadSummary[]>();\n for (const thread of threads) {\n const group = sessionListGroupOf(thread);\n const items = byGroup.get(group) ?? [];\n items.push(thread);\n byGroup.set(group, items);\n }\n return SESSION_LIST_GROUPS.flatMap((group) => {\n const items = byGroup.get(group);\n return items ? [{ group, items }] : [];\n });\n}\n\n/**\n * The status indicator at the head of a row: `needs_you` an orange dot,\n * `working` a spinner, `unread` (and not needs-you) a blue dot, `watching` a\n * clock, otherwise none. One indicator per row, in that precedence.\n */\nexport type SessionIndicator = 'needs_you' | 'working' | 'unread' | 'watching' | null;\n\nexport function sessionIndicator(\n thread: Pick<AthenaStatewireThreadSummary, 'attention' | 'isUnread'>,\n): SessionIndicator {\n if (thread.attention === 'needs_you') return 'needs_you';\n if (thread.attention === 'working') return 'working';\n if (thread.isUnread) return 'unread';\n if (thread.attention === 'watching') return 'watching';\n return null;\n}\n\nexport type SessionLineTone = 'needs_you' | 'ready' | 'error' | 'muted';\n\nexport interface SessionSecondaryLine {\n kind: 'next_action' | 'updated';\n text: string;\n tone: SessionLineTone;\n}\n\n/** \"5m ago\" / \"3h ago\" / \"2d ago\"; a locale date past a week; empty for an unparseable value. */\nexport function relativeTime(value: string, now: number = Date.now()): string {\n const timestamp = Date.parse(value);\n if (!Number.isFinite(timestamp)) return '';\n const minutes = Math.floor(Math.max(0, now - timestamp) / 60_000);\n if (minutes < 1) return 'just now';\n if (minutes < 60) return `${minutes}m ago`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours}h ago`;\n const days = Math.floor(hours / 24);\n return days < 7 ? `${days}d ago` : new Date(timestamp).toLocaleDateString();\n}\n\n/**\n * The row's second line: the server's next action coloured by attention\n * (needs-you orange, ready green, error red), else the muted relative time\n * of the last update.\n */\nexport function sessionSecondaryLine(\n thread: Pick<AthenaStatewireThreadSummary, 'attention' | 'nextAction' | 'updatedAt'>,\n now: number = Date.now(),\n): SessionSecondaryLine {\n const nextAction = thread.nextAction?.trim();\n if (nextAction) {\n const tone: SessionLineTone =\n thread.attention === 'needs_you'\n ? 'needs_you'\n : thread.attention === 'ready'\n ? 'ready'\n : thread.attention === 'error'\n ? 'error'\n : 'muted';\n return { kind: 'next_action', text: nextAction, tone };\n }\n return { kind: 'updated', text: relativeTime(thread.updatedAt, now), tone: 'muted' };\n}\n\nexport type PullRequestChipState = 'open' | 'draft' | 'merged' | 'closed';\n\nexport function pullRequestChipState(\n pullRequest: Pick<ConversationPullRequest, 'state' | 'isDraft'>,\n): PullRequestChipState {\n if (pullRequest.state === 'MERGED') return 'merged';\n if (pullRequest.state === 'CLOSED') return 'closed';\n return pullRequest.isDraft ? 'draft' : 'open';\n}\n\nexport interface PullRequestChip {\n /** State of the primary pull request (the one the chip links to). */\n state: PullRequestChipState;\n count: number;\n /** `#123` for one pull request, `3 PRs` for several. */\n label: string;\n url: string;\n title: string;\n checksState: ConversationPullRequest['checksState'];\n reviewDecision: string | null;\n}\n\nfunction pullRequestRank(pullRequest: ConversationPullRequest): number {\n return pullRequest.state === 'OPEN' ? (pullRequest.isDraft ? 1 : 0) : 2;\n}\n\nfunction updatedAtMs(pullRequest: ConversationPullRequest): number {\n const timestamp = Date.parse(pullRequest.updatedAt);\n return Number.isFinite(timestamp) ? timestamp : 0;\n}\n\n/**\n * A session's pull requests in the order its chip and its pull-request list\n * show them: the ones still in flight first (open before draft), then the\n * most recently updated. The first is the one the chip stands for.\n */\nexport function orderedPullRequests(\n pullRequests: readonly ConversationPullRequest[] | null | undefined,\n): ConversationPullRequest[] {\n if (!pullRequests) return [];\n return [...pullRequests].sort(\n (a, b) => pullRequestRank(a) - pullRequestRank(b) || updatedAtMs(b) - updatedAtMs(a),\n );\n}\n\n/** One chip per row, or `null` when the session opened no pull request (or none is known). */\nexport function pullRequestChip(\n pullRequests: readonly ConversationPullRequest[] | null | undefined,\n): PullRequestChip | null {\n if (!pullRequests || pullRequests.length === 0) return null;\n const primary = orderedPullRequests(pullRequests)[0];\n if (!primary) return null;\n return {\n state: pullRequestChipState(primary),\n count: pullRequests.length,\n label: pullRequests.length === 1 ? `#${primary.number}` : `${pullRequests.length} PRs`,\n url: primary.url,\n title: primary.title,\n checksState: primary.checksState,\n reviewDecision: primary.reviewDecision,\n };\n}\n\n/** The origin badge of a session started in the Athena web app (Olympus or an SDK app in a browser tab). */\nexport const WEB_APP_ORIGIN_LABEL = 'Athena';\n\n/**\n * Which rows `SessionList` badges with their origin: every one, only those\n * started somewhere other than the web app (Slack, GitHub, Chrome, an Office\n * host …), or none.\n */\nexport type SessionOriginBadges = 'all' | 'external' | 'none';\n\nconst CHANNEL_LABELS: Record<string, string> = {\n web: WEB_APP_ORIGIN_LABEL,\n olympus: WEB_APP_ORIGIN_LABEL,\n github: 'GitHub',\n api: 'API',\n email: 'Email',\n agent_email: 'Email',\n slack: 'Slack',\n sms: 'SMS',\n teams: 'Teams',\n task: 'Task',\n orchestration: 'Orchestration',\n computer: 'Computer',\n voice: 'Voice',\n mobile: 'Mobile',\n};\n\nfunction humanize(value: string): string {\n const words = value.replace(/^athena[-_]/, '').replace(/[-_.]+/g, ' ').trim();\n return words ? words.charAt(0).toUpperCase() + words.slice(1) : '';\n}\n\n/**\n * The origin badge: the client app when it is a recognizable surface\n * (Chrome, an Office host, mobile, a computer asset), else the start channel,\n * else a non-manual trigger; `null` when nothing is known.\n */\nexport function sessionOriginLabel(\n thread: Pick<AthenaStatewireThreadSummary, 'startChannel' | 'appId' | 'triggerType'>,\n): string | null {\n const appId = thread.appId?.trim().toLowerCase() ?? '';\n if (appId) {\n if (appId.includes('chrome')) return 'Chrome';\n if (appId.includes('powerpoint')) return 'PowerPoint';\n if (appId.includes('word')) return 'Word';\n if (appId.includes('excel')) return 'Excel';\n if (appId.includes('office')) return 'Office';\n if (appId.includes('mobile')) return 'Mobile';\n if (appId.startsWith('asset_')) return 'Computer';\n if (CHANNEL_LABELS[appId]) return CHANNEL_LABELS[appId];\n }\n const channel = thread.startChannel?.trim().toLowerCase() ?? '';\n if (channel) return CHANNEL_LABELS[channel] ?? humanize(channel);\n if (appId) return humanize(appId) || null;\n const trigger = thread.triggerType?.trim().toLowerCase() ?? '';\n if (trigger && trigger !== 'manual') return humanize(trigger) || null;\n return null;\n}\n\n/**\n * Client app ids that are the Athena web app itself: Olympus, and the\n * standalone app template, whose sessions carry no start channel when the\n * app does not report one (and would otherwise read as \"App\").\n */\nconst WEB_APP_IDS = new Set(['web', 'olympus', 'athena-app']);\n\n/** The origin badge a row shows under `badges` (`sessionOriginLabel`, filtered). */\nexport function sessionOriginBadge(\n thread: Pick<AthenaStatewireThreadSummary, 'startChannel' | 'appId' | 'triggerType'>,\n badges: SessionOriginBadges,\n): string | null {\n if (badges === 'none') return null;\n const origin = sessionOriginLabel(thread);\n if (badges === 'external') {\n const appId = thread.appId?.trim().toLowerCase() ?? '';\n if (origin === WEB_APP_ORIGIN_LABEL || WEB_APP_IDS.has(appId)) return null;\n }\n return origin;\n}\n"],"names":[],"mappings":";;AAeO,MAAM,sBAAmD;AAAA,EAC9D;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEO,SAAS,mBACd,QACkB;AAClB,MAAI,OAAO,cAAc,YAAa,QAAO;AAC7C,MAAI,OAAO,cAAc,UAAW,QAAO;AAC3C,MAAI,OAAO,YAAa,QAAO;AAC/B,SAAO;AACT;AASO,SAAS,cACd,SACA,SACsB;AACtB,MAAI,CAAC,QAAS,QAAO,QAAQ,SAAS,IAAI,CAAC,EAAE,OAAO,MAAM,OAAO,CAAC,GAAG,OAAO,EAAA,CAAG,IAAI,CAAA;AACnF,QAAM,8BAAc,IAAA;AACpB,aAAW,UAAU,SAAS;AAC5B,UAAM,QAAQ,mBAAmB,MAAM;AACvC,UAAM,QAAQ,QAAQ,IAAI,KAAK,KAAK,CAAA;AACpC,UAAM,KAAK,MAAM;AACjB,YAAQ,IAAI,OAAO,KAAK;AAAA,EAC1B;AACA,SAAO,oBAAoB,QAAQ,CAAC,UAAU;AAC5C,UAAM,QAAQ,QAAQ,IAAI,KAAK;AAC/B,WAAO,QAAQ,CAAC,EAAE,OAAO,MAAA,CAAO,IAAI,CAAA;AAAA,EACtC,CAAC;AACH;AASO,SAAS,iBACd,QACkB;AAClB,MAAI,OAAO,cAAc,YAAa,QAAO;AAC7C,MAAI,OAAO,cAAc,UAAW,QAAO;AAC3C,MAAI,OAAO,SAAU,QAAO;AAC5B,MAAI,OAAO,cAAc,WAAY,QAAO;AAC5C,SAAO;AACT;AAWO,SAAS,aAAa,OAAe,MAAc,KAAK,OAAe;AAC5E,QAAM,YAAY,KAAK,MAAM,KAAK;AAClC,MAAI,CAAC,OAAO,SAAS,SAAS,EAAG,QAAO;AACxC,QAAM,UAAU,KAAK,MAAM,KAAK,IAAI,GAAG,MAAM,SAAS,IAAI,GAAM;AAChE,MAAI,UAAU,EAAG,QAAO;AACxB,MAAI,UAAU,GAAI,QAAO,GAAG,OAAO;AACnC,QAAM,QAAQ,KAAK,MAAM,UAAU,EAAE;AACrC,MAAI,QAAQ,GAAI,QAAO,GAAG,KAAK;AAC/B,QAAM,OAAO,KAAK,MAAM,QAAQ,EAAE;AAClC,SAAO,OAAO,IAAI,GAAG,IAAI,UAAU,IAAI,KAAK,SAAS,EAAE,mBAAA;AACzD;AAOO,SAAS,qBACd,QACA,MAAc,KAAK,OACG;;AACtB,QAAM,cAAa,YAAO,eAAP,mBAAmB;AACtC,MAAI,YAAY;AACd,UAAM,OACJ,OAAO,cAAc,cACjB,cACA,OAAO,cAAc,UACnB,UACA,OAAO,cAAc,UACnB,UACA;AACV,WAAO,EAAE,MAAM,eAAe,MAAM,YAAY,KAAA;AAAA,EAClD;AACA,SAAO,EAAE,MAAM,WAAW,MAAM,aAAa,OAAO,WAAW,GAAG,GAAG,MAAM,QAAA;AAC7E;AAIO,SAAS,qBACd,aACsB;AACtB,MAAI,YAAY,UAAU,SAAU,QAAO;AAC3C,MAAI,YAAY,UAAU,SAAU,QAAO;AAC3C,SAAO,YAAY,UAAU,UAAU;AACzC;AAcA,SAAS,gBAAgB,aAA8C;AACrE,SAAO,YAAY,UAAU,SAAU,YAAY,UAAU,IAAI,IAAK;AACxE;AAEA,SAAS,YAAY,aAA8C;AACjE,QAAM,YAAY,KAAK,MAAM,YAAY,SAAS;AAClD,SAAO,OAAO,SAAS,SAAS,IAAI,YAAY;AAClD;AAOO,SAAS,oBACd,cAC2B;AAC3B,MAAI,CAAC,aAAc,QAAO,CAAA;AAC1B,SAAO,CAAC,GAAG,YAAY,EAAE;AAAA,IACvB,CAAC,GAAG,MAAM,gBAAgB,CAAC,IAAI,gBAAgB,CAAC,KAAK,YAAY,CAAC,IAAI,YAAY,CAAC;AAAA,EAAA;AAEvF;AAGO,SAAS,gBACd,cACwB;AACxB,MAAI,CAAC,gBAAgB,aAAa,WAAW,EAAG,QAAO;AACvD,QAAM,UAAU,oBAAoB,YAAY,EAAE,CAAC;AACnD,MAAI,CAAC,QAAS,QAAO;AACrB,SAAO;AAAA,IACL,OAAO,qBAAqB,OAAO;AAAA,IACnC,OAAO,aAAa;AAAA,IACpB,OAAO,aAAa,WAAW,IAAI,IAAI,QAAQ,MAAM,KAAK,GAAG,aAAa,MAAM;AAAA,IAChF,KAAK,QAAQ;AAAA,IACb,OAAO,QAAQ;AAAA,IACf,aAAa,QAAQ;AAAA,IACrB,gBAAgB,QAAQ;AAAA,EAAA;AAE5B;AAGO,MAAM,uBAAuB;AASpC,MAAM,iBAAyC;AAAA,EAC7C,KAAK;AAAA,EACL,SAAS;AAAA,EACT,QAAQ;AAAA,EACR,KAAK;AAAA,EACL,OAAO;AAAA,EACP,aAAa;AAAA,EACb,OAAO;AAAA,EACP,KAAK;AAAA,EACL,OAAO;AAAA,EACP,MAAM;AAAA,EACN,eAAe;AAAA,EACf,UAAU;AAAA,EACV,OAAO;AAAA,EACP,QAAQ;AACV;AAEA,SAAS,SAAS,OAAuB;AACvC,QAAM,QAAQ,MAAM,QAAQ,eAAe,EAAE,EAAE,QAAQ,WAAW,GAAG,EAAE,KAAA;AACvE,SAAO,QAAQ,MAAM,OAAO,CAAC,EAAE,gBAAgB,MAAM,MAAM,CAAC,IAAI;AAClE;AAOO,SAAS,mBACd,QACe;;AACf,QAAM,UAAQ,YAAO,UAAP,mBAAc,OAAO,kBAAiB;AACpD,MAAI,OAAO;AACT,QAAI,MAAM,SAAS,QAAQ,EAAG,QAAO;AACrC,QAAI,MAAM,SAAS,YAAY,EAAG,QAAO;AACzC,QAAI,MAAM,SAAS,MAAM,EAAG,QAAO;AACnC,QAAI,MAAM,SAAS,OAAO,EAAG,QAAO;AACpC,QAAI,MAAM,SAAS,QAAQ,EAAG,QAAO;AACrC,QAAI,MAAM,SAAS,QAAQ,EAAG,QAAO;AACrC,QAAI,MAAM,WAAW,QAAQ,EAAG,QAAO;AACvC,QAAI,eAAe,KAAK,EAAG,QAAO,eAAe,KAAK;AAAA,EACxD;AACA,QAAM,YAAU,YAAO,iBAAP,mBAAqB,OAAO,kBAAiB;AAC7D,MAAI,QAAS,QAAO,eAAe,OAAO,KAAK,SAAS,OAAO;AAC/D,MAAI,MAAO,QAAO,SAAS,KAAK,KAAK;AACrC,QAAM,YAAU,YAAO,gBAAP,mBAAoB,OAAO,kBAAiB;AAC5D,MAAI,WAAW,YAAY,SAAU,QAAO,SAAS,OAAO,KAAK;AACjE,SAAO;AACT;AAOA,MAAM,cAAc,oBAAI,IAAI,CAAC,OAAO,WAAW,YAAY,CAAC;AAGrD,SAAS,mBACd,QACA,QACe;;AACf,MAAI,WAAW,OAAQ,QAAO;AAC9B,QAAM,SAAS,mBAAmB,MAAM;AACxC,MAAI,WAAW,YAAY;AACzB,UAAM,UAAQ,YAAO,UAAP,mBAAc,OAAO,kBAAiB;AACpD,QAAI,WAAW,wBAAwB,YAAY,IAAI,KAAK,EAAG,QAAO;AAAA,EACxE;AACA,SAAO;AACT;;;;;;;;;;;;;"}
|
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
* requests collapse into one chip (and order in the list it opens), and how
|
|
5
5
|
* its origin is labelled. Kept React-free so the render tests stay thin and
|
|
6
6
|
* hosts that draw their own rows (`useAthenaSessionAttention`) can reuse the
|
|
7
|
-
* same rules.
|
|
7
|
+
* same rules. Published alone as `@athenaintel/react/session-list-model`, so a
|
|
8
|
+
* host's shell can draw a session's chips without loading the chat.
|
|
8
9
|
*/
|
|
9
10
|
import type { ConversationPullRequest } from '../agent-runtime/src/index';
|
|
10
11
|
import type { AthenaStatewireThreadSummary } from './statewire-thread-list';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-list-model.js","sources":["../../src/threads/session-list-model.ts"],"sourcesContent":["/**\n * Pure derivations behind `SessionList`: which group a session lands in,\n * which status indicator it shows, what its second line says, how its pull\n * requests collapse into one chip (and order in the list it opens), and how\n * its origin is labelled. Kept React-free so the render tests stay thin and\n * hosts that draw their own rows (`useAthenaSessionAttention`) can reuse the\n * same rules.\n */\nimport type { ConversationPullRequest } from '@athenaintel/agent-runtime';\nimport type { AthenaStatewireThreadSummary } from './statewire-thread-list';\n\nexport type SessionListGroup = 'Needs you' | 'Working' | 'Pinned' | 'Recent';\n\n/** Display order; a session appears once, in the FIRST group that applies. */\nexport const SESSION_LIST_GROUPS: readonly SessionListGroup[] = [\n 'Needs you',\n 'Working',\n 'Pinned',\n 'Recent',\n];\n\nexport function sessionListGroupOf(\n thread: Pick<AthenaStatewireThreadSummary, 'attention' | 'isFavorited'>,\n): SessionListGroup {\n if (thread.attention === 'needs_you') return 'Needs you';\n if (thread.attention === 'working') return 'Working';\n if (thread.isFavorited) return 'Pinned';\n return 'Recent';\n}\n\nexport interface SessionListSection {\n /** `null` for the single ungrouped section. */\n group: SessionListGroup | null;\n items: AthenaStatewireThreadSummary[];\n}\n\n/** Sections in display order; empty groups are omitted and row order is kept within a group. */\nexport function groupSessions(\n threads: readonly AthenaStatewireThreadSummary[],\n grouped: boolean,\n): SessionListSection[] {\n if (!grouped) return threads.length > 0 ? [{ group: null, items: [...threads] }] : [];\n const byGroup = new Map<SessionListGroup, AthenaStatewireThreadSummary[]>();\n for (const thread of threads) {\n const group = sessionListGroupOf(thread);\n const items = byGroup.get(group) ?? [];\n items.push(thread);\n byGroup.set(group, items);\n }\n return SESSION_LIST_GROUPS.flatMap((group) => {\n const items = byGroup.get(group);\n return items ? [{ group, items }] : [];\n });\n}\n\n/**\n * The status indicator at the head of a row: `needs_you` an orange dot,\n * `working` a spinner, `unread` (and not needs-you) a blue dot, `watching` a\n * clock, otherwise none. One indicator per row, in that precedence.\n */\nexport type SessionIndicator = 'needs_you' | 'working' | 'unread' | 'watching' | null;\n\nexport function sessionIndicator(\n thread: Pick<AthenaStatewireThreadSummary, 'attention' | 'isUnread'>,\n): SessionIndicator {\n if (thread.attention === 'needs_you') return 'needs_you';\n if (thread.attention === 'working') return 'working';\n if (thread.isUnread) return 'unread';\n if (thread.attention === 'watching') return 'watching';\n return null;\n}\n\nexport type SessionLineTone = 'needs_you' | 'ready' | 'error' | 'muted';\n\nexport interface SessionSecondaryLine {\n kind: 'next_action' | 'updated';\n text: string;\n tone: SessionLineTone;\n}\n\n/** \"5m ago\" / \"3h ago\" / \"2d ago\"; a locale date past a week; empty for an unparseable value. */\nexport function relativeTime(value: string, now: number = Date.now()): string {\n const timestamp = Date.parse(value);\n if (!Number.isFinite(timestamp)) return '';\n const minutes = Math.floor(Math.max(0, now - timestamp) / 60_000);\n if (minutes < 1) return 'just now';\n if (minutes < 60) return `${minutes}m ago`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours}h ago`;\n const days = Math.floor(hours / 24);\n return days < 7 ? `${days}d ago` : new Date(timestamp).toLocaleDateString();\n}\n\n/**\n * The row's second line: the server's next action coloured by attention\n * (needs-you orange, ready green, error red), else the muted relative time\n * of the last update.\n */\nexport function sessionSecondaryLine(\n thread: Pick<AthenaStatewireThreadSummary, 'attention' | 'nextAction' | 'updatedAt'>,\n now: number = Date.now(),\n): SessionSecondaryLine {\n const nextAction = thread.nextAction?.trim();\n if (nextAction) {\n const tone: SessionLineTone =\n thread.attention === 'needs_you'\n ? 'needs_you'\n : thread.attention === 'ready'\n ? 'ready'\n : thread.attention === 'error'\n ? 'error'\n : 'muted';\n return { kind: 'next_action', text: nextAction, tone };\n }\n return { kind: 'updated', text: relativeTime(thread.updatedAt, now), tone: 'muted' };\n}\n\nexport type PullRequestChipState = 'open' | 'draft' | 'merged' | 'closed';\n\nexport function pullRequestChipState(\n pullRequest: Pick<ConversationPullRequest, 'state' | 'isDraft'>,\n): PullRequestChipState {\n if (pullRequest.state === 'MERGED') return 'merged';\n if (pullRequest.state === 'CLOSED') return 'closed';\n return pullRequest.isDraft ? 'draft' : 'open';\n}\n\nexport interface PullRequestChip {\n /** State of the primary pull request (the one the chip links to). */\n state: PullRequestChipState;\n count: number;\n /** `#123` for one pull request, `3 PRs` for several. */\n label: string;\n url: string;\n title: string;\n checksState: ConversationPullRequest['checksState'];\n reviewDecision: string | null;\n}\n\nfunction pullRequestRank(pullRequest: ConversationPullRequest): number {\n return pullRequest.state === 'OPEN' ? (pullRequest.isDraft ? 1 : 0) : 2;\n}\n\nfunction updatedAtMs(pullRequest: ConversationPullRequest): number {\n const timestamp = Date.parse(pullRequest.updatedAt);\n return Number.isFinite(timestamp) ? timestamp : 0;\n}\n\n/**\n * A session's pull requests in the order its chip and its pull-request list\n * show them: the ones still in flight first (open before draft), then the\n * most recently updated. The first is the one the chip stands for.\n */\nexport function orderedPullRequests(\n pullRequests: readonly ConversationPullRequest[] | null | undefined,\n): ConversationPullRequest[] {\n if (!pullRequests) return [];\n return [...pullRequests].sort(\n (a, b) => pullRequestRank(a) - pullRequestRank(b) || updatedAtMs(b) - updatedAtMs(a),\n );\n}\n\n/** One chip per row, or `null` when the session opened no pull request (or none is known). */\nexport function pullRequestChip(\n pullRequests: readonly ConversationPullRequest[] | null | undefined,\n): PullRequestChip | null {\n if (!pullRequests || pullRequests.length === 0) return null;\n const primary = orderedPullRequests(pullRequests)[0];\n if (!primary) return null;\n return {\n state: pullRequestChipState(primary),\n count: pullRequests.length,\n label: pullRequests.length === 1 ? `#${primary.number}` : `${pullRequests.length} PRs`,\n url: primary.url,\n title: primary.title,\n checksState: primary.checksState,\n reviewDecision: primary.reviewDecision,\n };\n}\n\n/** The origin badge of a session started in the Athena web app (Olympus or an SDK app in a browser tab). */\nexport const WEB_APP_ORIGIN_LABEL = 'Athena';\n\n/**\n * Which rows `SessionList` badges with their origin: every one, only those\n * started somewhere other than the web app (Slack, GitHub, Chrome, an Office\n * host …), or none.\n */\nexport type SessionOriginBadges = 'all' | 'external' | 'none';\n\nconst CHANNEL_LABELS: Record<string, string> = {\n web: WEB_APP_ORIGIN_LABEL,\n olympus: WEB_APP_ORIGIN_LABEL,\n github: 'GitHub',\n api: 'API',\n email: 'Email',\n agent_email: 'Email',\n slack: 'Slack',\n sms: 'SMS',\n teams: 'Teams',\n task: 'Task',\n orchestration: 'Orchestration',\n computer: 'Computer',\n voice: 'Voice',\n mobile: 'Mobile',\n};\n\nfunction humanize(value: string): string {\n const words = value.replace(/^athena[-_]/, '').replace(/[-_.]+/g, ' ').trim();\n return words ? words.charAt(0).toUpperCase() + words.slice(1) : '';\n}\n\n/**\n * The origin badge: the client app when it is a recognizable surface\n * (Chrome, an Office host, mobile, a computer asset), else the start channel,\n * else a non-manual trigger; `null` when nothing is known.\n */\nexport function sessionOriginLabel(\n thread: Pick<AthenaStatewireThreadSummary, 'startChannel' | 'appId' | 'triggerType'>,\n): string | null {\n const appId = thread.appId?.trim().toLowerCase() ?? '';\n if (appId) {\n if (appId.includes('chrome')) return 'Chrome';\n if (appId.includes('powerpoint')) return 'PowerPoint';\n if (appId.includes('word')) return 'Word';\n if (appId.includes('excel')) return 'Excel';\n if (appId.includes('office')) return 'Office';\n if (appId.includes('mobile')) return 'Mobile';\n if (appId.startsWith('asset_')) return 'Computer';\n if (CHANNEL_LABELS[appId]) return CHANNEL_LABELS[appId];\n }\n const channel = thread.startChannel?.trim().toLowerCase() ?? '';\n if (channel) return CHANNEL_LABELS[channel] ?? humanize(channel);\n if (appId) return humanize(appId) || null;\n const trigger = thread.triggerType?.trim().toLowerCase() ?? '';\n if (trigger && trigger !== 'manual') return humanize(trigger) || null;\n return null;\n}\n\n/**\n * Client app ids that are the Athena web app itself: Olympus, and the\n * standalone app template, whose sessions carry no start channel when the\n * app does not report one (and would otherwise read as \"App\").\n */\nconst WEB_APP_IDS = new Set(['web', 'olympus', 'athena-app']);\n\n/** The origin badge a row shows under `badges` (`sessionOriginLabel`, filtered). */\nexport function sessionOriginBadge(\n thread: Pick<AthenaStatewireThreadSummary, 'startChannel' | 'appId' | 'triggerType'>,\n badges: SessionOriginBadges,\n): string | null {\n if (badges === 'none') return null;\n const origin = sessionOriginLabel(thread);\n if (badges === 'external') {\n const appId = thread.appId?.trim().toLowerCase() ?? '';\n if (origin === WEB_APP_ORIGIN_LABEL || WEB_APP_IDS.has(appId)) return null;\n }\n return origin;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"session-list-model.js","sources":["../../src/threads/session-list-model.ts"],"sourcesContent":["/**\n * Pure derivations behind `SessionList`: which group a session lands in,\n * which status indicator it shows, what its second line says, how its pull\n * requests collapse into one chip (and order in the list it opens), and how\n * its origin is labelled. Kept React-free so the render tests stay thin and\n * hosts that draw their own rows (`useAthenaSessionAttention`) can reuse the\n * same rules. Published alone as `@athenaintel/react/session-list-model`, so a\n * host's shell can draw a session's chips without loading the chat.\n */\nimport type { ConversationPullRequest } from '@athenaintel/agent-runtime';\nimport type { AthenaStatewireThreadSummary } from './statewire-thread-list';\n\nexport type SessionListGroup = 'Needs you' | 'Working' | 'Pinned' | 'Recent';\n\n/** Display order; a session appears once, in the FIRST group that applies. */\nexport const SESSION_LIST_GROUPS: readonly SessionListGroup[] = [\n 'Needs you',\n 'Working',\n 'Pinned',\n 'Recent',\n];\n\nexport function sessionListGroupOf(\n thread: Pick<AthenaStatewireThreadSummary, 'attention' | 'isFavorited'>,\n): SessionListGroup {\n if (thread.attention === 'needs_you') return 'Needs you';\n if (thread.attention === 'working') return 'Working';\n if (thread.isFavorited) return 'Pinned';\n return 'Recent';\n}\n\nexport interface SessionListSection {\n /** `null` for the single ungrouped section. */\n group: SessionListGroup | null;\n items: AthenaStatewireThreadSummary[];\n}\n\n/** Sections in display order; empty groups are omitted and row order is kept within a group. */\nexport function groupSessions(\n threads: readonly AthenaStatewireThreadSummary[],\n grouped: boolean,\n): SessionListSection[] {\n if (!grouped) return threads.length > 0 ? [{ group: null, items: [...threads] }] : [];\n const byGroup = new Map<SessionListGroup, AthenaStatewireThreadSummary[]>();\n for (const thread of threads) {\n const group = sessionListGroupOf(thread);\n const items = byGroup.get(group) ?? [];\n items.push(thread);\n byGroup.set(group, items);\n }\n return SESSION_LIST_GROUPS.flatMap((group) => {\n const items = byGroup.get(group);\n return items ? [{ group, items }] : [];\n });\n}\n\n/**\n * The status indicator at the head of a row: `needs_you` an orange dot,\n * `working` a spinner, `unread` (and not needs-you) a blue dot, `watching` a\n * clock, otherwise none. One indicator per row, in that precedence.\n */\nexport type SessionIndicator = 'needs_you' | 'working' | 'unread' | 'watching' | null;\n\nexport function sessionIndicator(\n thread: Pick<AthenaStatewireThreadSummary, 'attention' | 'isUnread'>,\n): SessionIndicator {\n if (thread.attention === 'needs_you') return 'needs_you';\n if (thread.attention === 'working') return 'working';\n if (thread.isUnread) return 'unread';\n if (thread.attention === 'watching') return 'watching';\n return null;\n}\n\nexport type SessionLineTone = 'needs_you' | 'ready' | 'error' | 'muted';\n\nexport interface SessionSecondaryLine {\n kind: 'next_action' | 'updated';\n text: string;\n tone: SessionLineTone;\n}\n\n/** \"5m ago\" / \"3h ago\" / \"2d ago\"; a locale date past a week; empty for an unparseable value. */\nexport function relativeTime(value: string, now: number = Date.now()): string {\n const timestamp = Date.parse(value);\n if (!Number.isFinite(timestamp)) return '';\n const minutes = Math.floor(Math.max(0, now - timestamp) / 60_000);\n if (minutes < 1) return 'just now';\n if (minutes < 60) return `${minutes}m ago`;\n const hours = Math.floor(minutes / 60);\n if (hours < 24) return `${hours}h ago`;\n const days = Math.floor(hours / 24);\n return days < 7 ? `${days}d ago` : new Date(timestamp).toLocaleDateString();\n}\n\n/**\n * The row's second line: the server's next action coloured by attention\n * (needs-you orange, ready green, error red), else the muted relative time\n * of the last update.\n */\nexport function sessionSecondaryLine(\n thread: Pick<AthenaStatewireThreadSummary, 'attention' | 'nextAction' | 'updatedAt'>,\n now: number = Date.now(),\n): SessionSecondaryLine {\n const nextAction = thread.nextAction?.trim();\n if (nextAction) {\n const tone: SessionLineTone =\n thread.attention === 'needs_you'\n ? 'needs_you'\n : thread.attention === 'ready'\n ? 'ready'\n : thread.attention === 'error'\n ? 'error'\n : 'muted';\n return { kind: 'next_action', text: nextAction, tone };\n }\n return { kind: 'updated', text: relativeTime(thread.updatedAt, now), tone: 'muted' };\n}\n\nexport type PullRequestChipState = 'open' | 'draft' | 'merged' | 'closed';\n\nexport function pullRequestChipState(\n pullRequest: Pick<ConversationPullRequest, 'state' | 'isDraft'>,\n): PullRequestChipState {\n if (pullRequest.state === 'MERGED') return 'merged';\n if (pullRequest.state === 'CLOSED') return 'closed';\n return pullRequest.isDraft ? 'draft' : 'open';\n}\n\nexport interface PullRequestChip {\n /** State of the primary pull request (the one the chip links to). */\n state: PullRequestChipState;\n count: number;\n /** `#123` for one pull request, `3 PRs` for several. */\n label: string;\n url: string;\n title: string;\n checksState: ConversationPullRequest['checksState'];\n reviewDecision: string | null;\n}\n\nfunction pullRequestRank(pullRequest: ConversationPullRequest): number {\n return pullRequest.state === 'OPEN' ? (pullRequest.isDraft ? 1 : 0) : 2;\n}\n\nfunction updatedAtMs(pullRequest: ConversationPullRequest): number {\n const timestamp = Date.parse(pullRequest.updatedAt);\n return Number.isFinite(timestamp) ? timestamp : 0;\n}\n\n/**\n * A session's pull requests in the order its chip and its pull-request list\n * show them: the ones still in flight first (open before draft), then the\n * most recently updated. The first is the one the chip stands for.\n */\nexport function orderedPullRequests(\n pullRequests: readonly ConversationPullRequest[] | null | undefined,\n): ConversationPullRequest[] {\n if (!pullRequests) return [];\n return [...pullRequests].sort(\n (a, b) => pullRequestRank(a) - pullRequestRank(b) || updatedAtMs(b) - updatedAtMs(a),\n );\n}\n\n/** One chip per row, or `null` when the session opened no pull request (or none is known). */\nexport function pullRequestChip(\n pullRequests: readonly ConversationPullRequest[] | null | undefined,\n): PullRequestChip | null {\n if (!pullRequests || pullRequests.length === 0) return null;\n const primary = orderedPullRequests(pullRequests)[0];\n if (!primary) return null;\n return {\n state: pullRequestChipState(primary),\n count: pullRequests.length,\n label: pullRequests.length === 1 ? `#${primary.number}` : `${pullRequests.length} PRs`,\n url: primary.url,\n title: primary.title,\n checksState: primary.checksState,\n reviewDecision: primary.reviewDecision,\n };\n}\n\n/** The origin badge of a session started in the Athena web app (Olympus or an SDK app in a browser tab). */\nexport const WEB_APP_ORIGIN_LABEL = 'Athena';\n\n/**\n * Which rows `SessionList` badges with their origin: every one, only those\n * started somewhere other than the web app (Slack, GitHub, Chrome, an Office\n * host …), or none.\n */\nexport type SessionOriginBadges = 'all' | 'external' | 'none';\n\nconst CHANNEL_LABELS: Record<string, string> = {\n web: WEB_APP_ORIGIN_LABEL,\n olympus: WEB_APP_ORIGIN_LABEL,\n github: 'GitHub',\n api: 'API',\n email: 'Email',\n agent_email: 'Email',\n slack: 'Slack',\n sms: 'SMS',\n teams: 'Teams',\n task: 'Task',\n orchestration: 'Orchestration',\n computer: 'Computer',\n voice: 'Voice',\n mobile: 'Mobile',\n};\n\nfunction humanize(value: string): string {\n const words = value.replace(/^athena[-_]/, '').replace(/[-_.]+/g, ' ').trim();\n return words ? words.charAt(0).toUpperCase() + words.slice(1) : '';\n}\n\n/**\n * The origin badge: the client app when it is a recognizable surface\n * (Chrome, an Office host, mobile, a computer asset), else the start channel,\n * else a non-manual trigger; `null` when nothing is known.\n */\nexport function sessionOriginLabel(\n thread: Pick<AthenaStatewireThreadSummary, 'startChannel' | 'appId' | 'triggerType'>,\n): string | null {\n const appId = thread.appId?.trim().toLowerCase() ?? '';\n if (appId) {\n if (appId.includes('chrome')) return 'Chrome';\n if (appId.includes('powerpoint')) return 'PowerPoint';\n if (appId.includes('word')) return 'Word';\n if (appId.includes('excel')) return 'Excel';\n if (appId.includes('office')) return 'Office';\n if (appId.includes('mobile')) return 'Mobile';\n if (appId.startsWith('asset_')) return 'Computer';\n if (CHANNEL_LABELS[appId]) return CHANNEL_LABELS[appId];\n }\n const channel = thread.startChannel?.trim().toLowerCase() ?? '';\n if (channel) return CHANNEL_LABELS[channel] ?? humanize(channel);\n if (appId) return humanize(appId) || null;\n const trigger = thread.triggerType?.trim().toLowerCase() ?? '';\n if (trigger && trigger !== 'manual') return humanize(trigger) || null;\n return null;\n}\n\n/**\n * Client app ids that are the Athena web app itself: Olympus, and the\n * standalone app template, whose sessions carry no start channel when the\n * app does not report one (and would otherwise read as \"App\").\n */\nconst WEB_APP_IDS = new Set(['web', 'olympus', 'athena-app']);\n\n/** The origin badge a row shows under `badges` (`sessionOriginLabel`, filtered). */\nexport function sessionOriginBadge(\n thread: Pick<AthenaStatewireThreadSummary, 'startChannel' | 'appId' | 'triggerType'>,\n badges: SessionOriginBadges,\n): string | null {\n if (badges === 'none') return null;\n const origin = sessionOriginLabel(thread);\n if (badges === 'external') {\n const appId = thread.appId?.trim().toLowerCase() ?? '';\n if (origin === WEB_APP_ORIGIN_LABEL || WEB_APP_IDS.has(appId)) return null;\n }\n return origin;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
4
|
const popover = require("../ui/popover.cjs");
|
|
5
5
|
const pullRequestDisplay = require("./pull-request-display.cjs");
|
|
6
|
-
const
|
|
6
|
+
const threads_sessionListModel = require("./session-list-model.cjs");
|
|
7
7
|
const cnfast = require("cnfast");
|
|
8
8
|
const FOCUS_RING_CLASS = "outline-none focus-visible:ring-2 focus-visible:ring-ring/60 focus-visible:ring-offset-0";
|
|
9
9
|
const stopPropagation = (event) => event.stopPropagation();
|
|
@@ -12,7 +12,7 @@ const PullRequestListRow = ({
|
|
|
12
12
|
pullRequest,
|
|
13
13
|
showRepo
|
|
14
14
|
}) => {
|
|
15
|
-
const state =
|
|
15
|
+
const state = threads_sessionListModel.pullRequestChipState(pullRequest);
|
|
16
16
|
const Icon = pullRequestDisplay.PR_STATE_ICON[state];
|
|
17
17
|
const meta = [
|
|
18
18
|
showRepo ? `${pullRequest.repoFullName} #${pullRequest.number}` : `#${pullRequest.number}`,
|
|
@@ -64,7 +64,7 @@ const PullRequestChip = ({ chip, pullRequests }) => {
|
|
|
64
64
|
);
|
|
65
65
|
}
|
|
66
66
|
const listLabel = `${chip.count} pull requests`;
|
|
67
|
-
const ordered =
|
|
67
|
+
const ordered = threads_sessionListModel.orderedPullRequests(pullRequests);
|
|
68
68
|
const repositories = new Set(ordered.map((pullRequest) => pullRequest.repoFullName));
|
|
69
69
|
const sharedRepository = repositories.size === 1 ? ((_a = ordered[0]) == null ? void 0 : _a.repoFullName) ?? null : null;
|
|
70
70
|
return /* @__PURE__ */ jsxRuntime.jsxs(popover.Popover, { children: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-row-parts.cjs","sources":["../../src/threads/session-row-parts.tsx"],"sourcesContent":["/**\n * Row pieces every SDK session list shares (`SessionList`, `SessionsPage`,\n * `Inbox`): the focus ring, the pull-request chip and its list, the\n * attention-toned status chip, and a labelled icon action that never selects\n * its row.\n */\nimport type { ConversationPullRequest } from '@athenaintel/agent-runtime';\nimport type { FC, MouseEvent, ReactNode } from 'react';\nimport { cn } from '../lib/utils';\nimport { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';\nimport { PR_CHECKS_LABEL, PR_STATE_CLASS, PR_STATE_ICON } from './pull-request-display';\nimport {\n orderedPullRequests,\n type PullRequestChip as PullRequestChipModel,\n pullRequestChipState,\n} from './session-list-model';\nimport type { SessionStatusTone } from './sessions-page-model';\n\n/** The focus treatment every row control and action shares. */\nexport const FOCUS_RING_CLASS =\n 'outline-none focus-visible:ring-2 focus-visible:ring-ring/60 focus-visible:ring-offset-0';\n\nexport const stopPropagation = (event: MouseEvent) => event.stopPropagation();\n\nconst PR_CHIP_CLASS =\n 'inline-flex h-4 shrink-0 items-center gap-1 rounded-full border border-border/60 px-1.5 font-medium text-[11px] leading-none transition-colors hover:bg-muted';\n\n/**\n * One row of the pull-request list: the state icon, the title, and the\n * number, state and checks beneath it (the repository too when the list\n * spans several), as a link to GitHub in a new tab.\n */\nconst PullRequestListRow: FC<{ pullRequest: ConversationPullRequest; showRepo: boolean }> = ({\n pullRequest,\n showRepo,\n}) => {\n const state = pullRequestChipState(pullRequest);\n const Icon = PR_STATE_ICON[state];\n const meta = [\n showRepo ? `${pullRequest.repoFullName} #${pullRequest.number}` : `#${pullRequest.number}`,\n state,\n PR_CHECKS_LABEL[pullRequest.checksState],\n ]\n .filter(Boolean)\n .join(' · ');\n return (\n <li>\n <a\n href={pullRequest.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n data-pr-state={state}\n className={cn(\n 'flex items-start gap-2 rounded-sm px-2 py-1.5 text-xs transition-colors hover:bg-muted',\n FOCUS_RING_CLASS,\n )}\n >\n <Icon className={cn('mt-0.5 size-3.5 shrink-0', PR_STATE_CLASS[state])} aria-hidden />\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-foreground\">\n {pullRequest.title || `#${pullRequest.number}`}\n </span>\n <span className=\"block truncate text-muted-foreground\">{meta}</span>\n </span>\n </a>\n </li>\n );\n};\n\n/**\n * The session's pull-request chip; a sibling of the row button (never nested\n * inside it) so the markup stays valid and a click on it never selects the\n * row. One pull request: a link to it. Several: a button that opens all of\n * them — in flight first, then the most recently updated — each a link to\n * GitHub.\n */\nexport const PullRequestChip: FC<{\n chip: PullRequestChipModel;\n pullRequests: readonly ConversationPullRequest[];\n}> = ({ chip, pullRequests }) => {\n const Icon = PR_STATE_ICON[chip.state];\n if (chip.count === 1) {\n return (\n <a\n href={chip.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n onClick={stopPropagation}\n title={chip.title}\n aria-label={`Pull request ${chip.label}, ${chip.state}`}\n data-pr-state={chip.state}\n data-pr-count={chip.count}\n className={cn(PR_CHIP_CLASS, FOCUS_RING_CLASS, PR_STATE_CLASS[chip.state])}\n >\n <Icon className=\"size-3\" aria-hidden />\n {chip.label}\n </a>\n );\n }\n const listLabel = `${chip.count} pull requests`;\n const ordered = orderedPullRequests(pullRequests);\n // One repository (the usual case) is named once in the header, so each\n // row's meta line has room for its state and checks.\n const repositories = new Set(ordered.map((pullRequest) => pullRequest.repoFullName));\n const sharedRepository = repositories.size === 1 ? (ordered[0]?.repoFullName ?? null) : null;\n return (\n <Popover>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n onClick={stopPropagation}\n aria-label={`${chip.label}: show all ${listLabel}`}\n data-pr-state={chip.state}\n data-pr-count={chip.count}\n className={cn(PR_CHIP_CLASS, FOCUS_RING_CLASS, PR_STATE_CLASS[chip.state])}\n >\n <Icon className=\"size-3\" aria-hidden />\n {chip.label}\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"w-80 p-0\" aria-label={listLabel} data-pr-list=\"\">\n <p className=\"truncate border-b border-border px-3 py-2 font-medium text-muted-foreground text-xs\">\n {sharedRepository ? `${listLabel} in ${sharedRepository}` : listLabel}\n </p>\n <ul className=\"max-h-72 overflow-y-auto p-1\">\n {ordered.map((pullRequest) => (\n <PullRequestListRow\n key={`${pullRequest.repoFullName}#${pullRequest.number}`}\n pullRequest={pullRequest}\n showRepo={sharedRepository === null}\n />\n ))}\n </ul>\n </PopoverContent>\n </Popover>\n );\n};\n\n/** One colour per attention tone: the chip's dot and its text. */\nexport const STATUS_TONE_CLASS: Record<SessionStatusTone, { dot: string; text: string }> = {\n needs_you: { dot: 'bg-orange-500', text: 'text-orange-700' },\n working: { dot: 'bg-blue-500 animate-pulse', text: 'text-blue-700' },\n ready: { dot: 'bg-green-500', text: 'text-green-700' },\n watching: { dot: 'bg-violet-400', text: 'text-violet-700' },\n done: { dot: 'bg-muted-foreground/50', text: 'text-muted-foreground' },\n error: { dot: 'bg-red-500', text: 'text-red-700' },\n muted: { dot: 'bg-muted-foreground/30', text: 'text-muted-foreground' },\n};\n\n/** A coloured dot and a label (truncated, with the full text as its tooltip). */\nexport const StatusChip: FC<{\n label: string;\n tone: SessionStatusTone;\n detail?: string | null;\n className?: string;\n}> = ({ label, tone, detail, className }) => (\n <span\n data-status-tone={tone}\n title={detail ?? label}\n className={cn(\n 'inline-flex min-w-0 max-w-full items-center gap-1.5 font-medium text-xs',\n STATUS_TONE_CLASS[tone].text,\n className,\n )}\n >\n <span aria-hidden=\"true\" className={cn('size-2 shrink-0 rounded-full', STATUS_TONE_CLASS[tone].dot)} />\n <span className=\"truncate\">{label}</span>\n </span>\n);\n\n/**\n * A labelled icon action on a row: a sibling of the row control (a click\n * never selects the row), disabled while its write is in flight, revealed on\n * row hover or focus unless `alwaysVisible`.\n */\nexport const RowIconButton: FC<{\n label: string;\n action: string;\n onClick: () => void;\n pending?: boolean;\n pressed?: boolean;\n alwaysVisible?: boolean;\n children: ReactNode;\n}> = ({ label, action, onClick, pending = false, pressed, alwaysVisible = false, children }) => (\n <button\n type=\"button\"\n onClick={(event) => {\n event.stopPropagation();\n if (!pending) onClick();\n }}\n disabled={pending}\n aria-busy={pending || undefined}\n aria-pressed={pressed}\n aria-label={label}\n title={label}\n data-action={action}\n className={cn(\n 'rounded p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:cursor-wait disabled:opacity-60',\n FOCUS_RING_CLASS,\n !alwaysVisible &&\n !pending &&\n 'opacity-0 focus-visible:opacity-100 group-focus-within:opacity-100 group-hover:opacity-100',\n )}\n >\n {children}\n </button>\n);\n"],"names":["pullRequestChipState","PR_STATE_ICON","PR_CHECKS_LABEL","jsxs","cn","jsx","PR_STATE_CLASS","orderedPullRequests","Popover","PopoverTrigger","PopoverContent"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"session-row-parts.cjs","sources":["../../src/threads/session-row-parts.tsx"],"sourcesContent":["/**\n * Row pieces every SDK session list shares (`SessionList`, `SessionsPage`,\n * `Inbox`): the focus ring, the pull-request chip and its list, the\n * attention-toned status chip, and a labelled icon action that never selects\n * its row.\n */\nimport type { ConversationPullRequest } from '@athenaintel/agent-runtime';\nimport type { FC, MouseEvent, ReactNode } from 'react';\nimport { cn } from '../lib/utils';\nimport { Popover, PopoverContent, PopoverTrigger } from '../ui/popover';\nimport { PR_CHECKS_LABEL, PR_STATE_CLASS, PR_STATE_ICON } from './pull-request-display';\nimport {\n orderedPullRequests,\n type PullRequestChip as PullRequestChipModel,\n pullRequestChipState,\n} from './session-list-model';\nimport type { SessionStatusTone } from './sessions-page-model';\n\n/** The focus treatment every row control and action shares. */\nexport const FOCUS_RING_CLASS =\n 'outline-none focus-visible:ring-2 focus-visible:ring-ring/60 focus-visible:ring-offset-0';\n\nexport const stopPropagation = (event: MouseEvent) => event.stopPropagation();\n\nconst PR_CHIP_CLASS =\n 'inline-flex h-4 shrink-0 items-center gap-1 rounded-full border border-border/60 px-1.5 font-medium text-[11px] leading-none transition-colors hover:bg-muted';\n\n/**\n * One row of the pull-request list: the state icon, the title, and the\n * number, state and checks beneath it (the repository too when the list\n * spans several), as a link to GitHub in a new tab.\n */\nconst PullRequestListRow: FC<{ pullRequest: ConversationPullRequest; showRepo: boolean }> = ({\n pullRequest,\n showRepo,\n}) => {\n const state = pullRequestChipState(pullRequest);\n const Icon = PR_STATE_ICON[state];\n const meta = [\n showRepo ? `${pullRequest.repoFullName} #${pullRequest.number}` : `#${pullRequest.number}`,\n state,\n PR_CHECKS_LABEL[pullRequest.checksState],\n ]\n .filter(Boolean)\n .join(' · ');\n return (\n <li>\n <a\n href={pullRequest.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n data-pr-state={state}\n className={cn(\n 'flex items-start gap-2 rounded-sm px-2 py-1.5 text-xs transition-colors hover:bg-muted',\n FOCUS_RING_CLASS,\n )}\n >\n <Icon className={cn('mt-0.5 size-3.5 shrink-0', PR_STATE_CLASS[state])} aria-hidden />\n <span className=\"min-w-0 flex-1\">\n <span className=\"block truncate text-foreground\">\n {pullRequest.title || `#${pullRequest.number}`}\n </span>\n <span className=\"block truncate text-muted-foreground\">{meta}</span>\n </span>\n </a>\n </li>\n );\n};\n\n/**\n * The session's pull-request chip; a sibling of the row button (never nested\n * inside it) so the markup stays valid and a click on it never selects the\n * row. One pull request: a link to it. Several: a button that opens all of\n * them — in flight first, then the most recently updated — each a link to\n * GitHub.\n */\nexport const PullRequestChip: FC<{\n chip: PullRequestChipModel;\n pullRequests: readonly ConversationPullRequest[];\n}> = ({ chip, pullRequests }) => {\n const Icon = PR_STATE_ICON[chip.state];\n if (chip.count === 1) {\n return (\n <a\n href={chip.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n onClick={stopPropagation}\n title={chip.title}\n aria-label={`Pull request ${chip.label}, ${chip.state}`}\n data-pr-state={chip.state}\n data-pr-count={chip.count}\n className={cn(PR_CHIP_CLASS, FOCUS_RING_CLASS, PR_STATE_CLASS[chip.state])}\n >\n <Icon className=\"size-3\" aria-hidden />\n {chip.label}\n </a>\n );\n }\n const listLabel = `${chip.count} pull requests`;\n const ordered = orderedPullRequests(pullRequests);\n // One repository (the usual case) is named once in the header, so each\n // row's meta line has room for its state and checks.\n const repositories = new Set(ordered.map((pullRequest) => pullRequest.repoFullName));\n const sharedRepository = repositories.size === 1 ? (ordered[0]?.repoFullName ?? null) : null;\n return (\n <Popover>\n <PopoverTrigger asChild>\n <button\n type=\"button\"\n onClick={stopPropagation}\n aria-label={`${chip.label}: show all ${listLabel}`}\n data-pr-state={chip.state}\n data-pr-count={chip.count}\n className={cn(PR_CHIP_CLASS, FOCUS_RING_CLASS, PR_STATE_CLASS[chip.state])}\n >\n <Icon className=\"size-3\" aria-hidden />\n {chip.label}\n </button>\n </PopoverTrigger>\n <PopoverContent align=\"end\" className=\"w-80 p-0\" aria-label={listLabel} data-pr-list=\"\">\n <p className=\"truncate border-b border-border px-3 py-2 font-medium text-muted-foreground text-xs\">\n {sharedRepository ? `${listLabel} in ${sharedRepository}` : listLabel}\n </p>\n <ul className=\"max-h-72 overflow-y-auto p-1\">\n {ordered.map((pullRequest) => (\n <PullRequestListRow\n key={`${pullRequest.repoFullName}#${pullRequest.number}`}\n pullRequest={pullRequest}\n showRepo={sharedRepository === null}\n />\n ))}\n </ul>\n </PopoverContent>\n </Popover>\n );\n};\n\n/** One colour per attention tone: the chip's dot and its text. */\nexport const STATUS_TONE_CLASS: Record<SessionStatusTone, { dot: string; text: string }> = {\n needs_you: { dot: 'bg-orange-500', text: 'text-orange-700' },\n working: { dot: 'bg-blue-500 animate-pulse', text: 'text-blue-700' },\n ready: { dot: 'bg-green-500', text: 'text-green-700' },\n watching: { dot: 'bg-violet-400', text: 'text-violet-700' },\n done: { dot: 'bg-muted-foreground/50', text: 'text-muted-foreground' },\n error: { dot: 'bg-red-500', text: 'text-red-700' },\n muted: { dot: 'bg-muted-foreground/30', text: 'text-muted-foreground' },\n};\n\n/** A coloured dot and a label (truncated, with the full text as its tooltip). */\nexport const StatusChip: FC<{\n label: string;\n tone: SessionStatusTone;\n detail?: string | null;\n className?: string;\n}> = ({ label, tone, detail, className }) => (\n <span\n data-status-tone={tone}\n title={detail ?? label}\n className={cn(\n 'inline-flex min-w-0 max-w-full items-center gap-1.5 font-medium text-xs',\n STATUS_TONE_CLASS[tone].text,\n className,\n )}\n >\n <span aria-hidden=\"true\" className={cn('size-2 shrink-0 rounded-full', STATUS_TONE_CLASS[tone].dot)} />\n <span className=\"truncate\">{label}</span>\n </span>\n);\n\n/**\n * A labelled icon action on a row: a sibling of the row control (a click\n * never selects the row), disabled while its write is in flight, revealed on\n * row hover or focus unless `alwaysVisible`.\n */\nexport const RowIconButton: FC<{\n label: string;\n action: string;\n onClick: () => void;\n pending?: boolean;\n pressed?: boolean;\n alwaysVisible?: boolean;\n children: ReactNode;\n}> = ({ label, action, onClick, pending = false, pressed, alwaysVisible = false, children }) => (\n <button\n type=\"button\"\n onClick={(event) => {\n event.stopPropagation();\n if (!pending) onClick();\n }}\n disabled={pending}\n aria-busy={pending || undefined}\n aria-pressed={pressed}\n aria-label={label}\n title={label}\n data-action={action}\n className={cn(\n 'rounded p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground disabled:cursor-wait disabled:opacity-60',\n FOCUS_RING_CLASS,\n !alwaysVisible &&\n !pending &&\n 'opacity-0 focus-visible:opacity-100 group-focus-within:opacity-100 group-hover:opacity-100',\n )}\n >\n {children}\n </button>\n);\n"],"names":["pullRequestChipState","PR_STATE_ICON","PR_CHECKS_LABEL","jsxs","cn","jsx","PR_STATE_CLASS","orderedPullRequests","Popover","PopoverTrigger","PopoverContent"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const sessionsQuery = require("./sessions-query.cjs");
|
|
4
|
-
const
|
|
4
|
+
const threads_sessionListModel = require("./session-list-model.cjs");
|
|
5
5
|
function mergedPullRequestOf(row) {
|
|
6
6
|
const pullRequests = row.pullRequests ?? [];
|
|
7
7
|
if (pullRequests.length === 0 || pullRequests.some((pr) => pr.state === "OPEN")) return null;
|
|
@@ -134,9 +134,15 @@ const SESSIONS_COLUMNS = [
|
|
|
134
134
|
{ id: "created", label: "Created", defaultVisible: false },
|
|
135
135
|
{ id: "updated", label: "Updated", defaultVisible: true }
|
|
136
136
|
];
|
|
137
|
-
const
|
|
138
|
-
(column) => column.defaultVisible
|
|
137
|
+
const DEFAULT_HIDDEN_SESSIONS_COLUMNS = SESSIONS_COLUMNS.filter(
|
|
138
|
+
(column) => !column.defaultVisible
|
|
139
139
|
).map((column) => column.id);
|
|
140
|
+
function visibleSessionsColumns(hidden) {
|
|
141
|
+
return SESSIONS_COLUMNS.map((column) => column.id).filter((id) => !hidden.includes(id));
|
|
142
|
+
}
|
|
143
|
+
const DEFAULT_VISIBLE_SESSIONS_COLUMNS = visibleSessionsColumns(
|
|
144
|
+
DEFAULT_HIDDEN_SESSIONS_COLUMNS
|
|
145
|
+
);
|
|
140
146
|
function humanizeId(value) {
|
|
141
147
|
const words = value.replace(/^asset_/, "").replace(/[-_]+/g, " ").trim();
|
|
142
148
|
if (/^[0-9a-f]{8} ?[0-9a-f]{4}/i.test(words)) return `${words.slice(0, 8)}…`;
|
|
@@ -209,7 +215,7 @@ function sessionsFilterChips(query, labels) {
|
|
|
209
215
|
field: "startChannels",
|
|
210
216
|
label: `Origin: ${join(
|
|
211
217
|
query.startChannels.map(
|
|
212
|
-
(channel) =>
|
|
218
|
+
(channel) => threads_sessionListModel.sessionOriginLabel({ startChannel: channel, appId: null, triggerType: null }) ?? channel
|
|
213
219
|
)
|
|
214
220
|
)}`
|
|
215
221
|
});
|
|
@@ -273,7 +279,7 @@ function sessionsCsv(rows, labels) {
|
|
|
273
279
|
row.attention ?? "",
|
|
274
280
|
row.runStatus ?? "",
|
|
275
281
|
row.sessionStatus ?? "",
|
|
276
|
-
|
|
282
|
+
threads_sessionListModel.sessionOriginLabel(row) ?? "",
|
|
277
283
|
row.collabAgentId ? agentLabel(row.collabAgentId, labels) : "",
|
|
278
284
|
row.collabAgentId ? channelLabel(row.collabChannelId, labels) : "",
|
|
279
285
|
(row.pullRequests ?? []).map((pr) => `${pr.repoFullName}#${pr.number} (${pr.state})`).join("; "),
|
|
@@ -287,6 +293,7 @@ function sessionsCsv(rows, labels) {
|
|
|
287
293
|
});
|
|
288
294
|
return [header.map(csvCell).join(","), ...lines].join("\r\n");
|
|
289
295
|
}
|
|
296
|
+
exports.DEFAULT_HIDDEN_SESSIONS_COLUMNS = DEFAULT_HIDDEN_SESSIONS_COLUMNS;
|
|
290
297
|
exports.DEFAULT_VISIBLE_SESSIONS_COLUMNS = DEFAULT_VISIBLE_SESSIONS_COLUMNS;
|
|
291
298
|
exports.SESSIONS_COLUMNS = SESSIONS_COLUMNS;
|
|
292
299
|
exports.SESSIONS_DATE_PRESETS = SESSIONS_DATE_PRESETS;
|
|
@@ -302,4 +309,5 @@ exports.sessionStatusChip = sessionStatusChip;
|
|
|
302
309
|
exports.sessionStatusLabel = sessionStatusLabel;
|
|
303
310
|
exports.sessionsCsv = sessionsCsv;
|
|
304
311
|
exports.sessionsFilterChips = sessionsFilterChips;
|
|
312
|
+
exports.visibleSessionsColumns = visibleSessionsColumns;
|
|
305
313
|
//# sourceMappingURL=sessions-page-model.cjs.map
|