@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
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
import { useSyncExternalStore } from "react";
|
|
2
|
+
import { withAddressedAgents, readAddressedAgents } from "./addressed-agents.js";
|
|
3
|
+
const MAX_DEEP_AGENT_NAMED_AGENTS = 8;
|
|
4
|
+
const OWN_ASSISTANT_AGENT_REF = "assistant";
|
|
5
|
+
const COLLAB_AGENT_REF_PREFIX = "collab_agent:";
|
|
6
|
+
const NO_NAMED_AGENTS = Object.freeze([]);
|
|
7
|
+
function normalizeNamedAgents(agents) {
|
|
8
|
+
const seen = /* @__PURE__ */ new Set();
|
|
9
|
+
const normalized = [];
|
|
10
|
+
for (const agent of agents) {
|
|
11
|
+
const ref = agent.ref.trim();
|
|
12
|
+
if (!ref || seen.has(ref)) continue;
|
|
13
|
+
seen.add(ref);
|
|
14
|
+
normalized.push(ref === agent.ref ? agent : { ...agent, ref });
|
|
15
|
+
if (normalized.length === MAX_DEEP_AGENT_NAMED_AGENTS) break;
|
|
16
|
+
}
|
|
17
|
+
return normalized.length === 0 ? NO_NAMED_AGENTS : normalized;
|
|
18
|
+
}
|
|
19
|
+
function sameNamedAgents(a, b) {
|
|
20
|
+
return a.length === b.length && a.every(
|
|
21
|
+
(agent, index) => {
|
|
22
|
+
var _a, _b, _c;
|
|
23
|
+
return agent.ref === ((_a = b[index]) == null ? void 0 : _a.ref) && agent.name === ((_b = b[index]) == null ? void 0 : _b.name) && agent.assetId === ((_c = b[index]) == null ? void 0 : _c.assetId);
|
|
24
|
+
}
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
function namedAgentRefs(agents) {
|
|
28
|
+
const refs = [];
|
|
29
|
+
for (const agent of agents) {
|
|
30
|
+
const ref = agent.ref.trim();
|
|
31
|
+
if (!ref || refs.includes(ref)) continue;
|
|
32
|
+
refs.push(ref);
|
|
33
|
+
if (refs.length === MAX_DEEP_AGENT_NAMED_AGENTS) break;
|
|
34
|
+
}
|
|
35
|
+
return refs;
|
|
36
|
+
}
|
|
37
|
+
function setBounded(map, key, value, limit) {
|
|
38
|
+
map.delete(key);
|
|
39
|
+
map.set(key, value);
|
|
40
|
+
while (map.size > limit) {
|
|
41
|
+
const oldest = map.keys().next();
|
|
42
|
+
if (oldest.done) break;
|
|
43
|
+
map.delete(oldest.value);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function createNamedAgentsStore(initial) {
|
|
47
|
+
let state = initial;
|
|
48
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
49
|
+
return {
|
|
50
|
+
get state() {
|
|
51
|
+
return state;
|
|
52
|
+
},
|
|
53
|
+
setState(update) {
|
|
54
|
+
const next = update(state);
|
|
55
|
+
if (Object.is(next, state)) return;
|
|
56
|
+
state = next;
|
|
57
|
+
for (const listener of [...listeners]) listener();
|
|
58
|
+
},
|
|
59
|
+
subscribe(listener) {
|
|
60
|
+
listeners.add(listener);
|
|
61
|
+
return () => {
|
|
62
|
+
listeners.delete(listener);
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
const deepAgentNamedAgentsStore = createNamedAgentsStore({
|
|
68
|
+
byThread: {}
|
|
69
|
+
});
|
|
70
|
+
const namedAgentsSeen = /* @__PURE__ */ new Map();
|
|
71
|
+
const NAMED_AGENTS_SEEN_KEPT = 200;
|
|
72
|
+
function writeNamedAgents(threadId, agents) {
|
|
73
|
+
for (const agent of agents) setBounded(namedAgentsSeen, agent.ref, agent, NAMED_AGENTS_SEEN_KEPT);
|
|
74
|
+
deepAgentNamedAgentsStore.setState((state) => {
|
|
75
|
+
if (sameNamedAgents(state.byThread[threadId] ?? NO_NAMED_AGENTS, agents)) return state;
|
|
76
|
+
const byThread = { ...state.byThread };
|
|
77
|
+
if (agents.length === 0) delete byThread[threadId];
|
|
78
|
+
else byThread[threadId] = agents;
|
|
79
|
+
return { byThread };
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
function useDeepAgentNamedAgents(threadId) {
|
|
83
|
+
const read = () => readDeepAgentNamedAgents(threadId);
|
|
84
|
+
return useSyncExternalStore(deepAgentNamedAgentsStore.subscribe, read, read);
|
|
85
|
+
}
|
|
86
|
+
function readDeepAgentNamedAgents(threadId) {
|
|
87
|
+
return deepAgentNamedAgentsStore.state.byThread[threadId] ?? NO_NAMED_AGENTS;
|
|
88
|
+
}
|
|
89
|
+
function addDeepAgentNamedAgent({
|
|
90
|
+
threadId,
|
|
91
|
+
agent
|
|
92
|
+
}) {
|
|
93
|
+
const current = readDeepAgentNamedAgents(threadId);
|
|
94
|
+
const ref = agent.ref.trim();
|
|
95
|
+
if (!threadId || !ref || current.length >= MAX_DEEP_AGENT_NAMED_AGENTS || current.some((named) => named.ref === ref)) {
|
|
96
|
+
return false;
|
|
97
|
+
}
|
|
98
|
+
writeNamedAgents(threadId, normalizeNamedAgents([...current, agent]));
|
|
99
|
+
return true;
|
|
100
|
+
}
|
|
101
|
+
function removeDeepAgentNamedAgent({
|
|
102
|
+
threadId,
|
|
103
|
+
ref
|
|
104
|
+
}) {
|
|
105
|
+
const current = readDeepAgentNamedAgents(threadId);
|
|
106
|
+
if (!current.some((agent) => agent.ref === ref)) return;
|
|
107
|
+
writeNamedAgents(threadId, normalizeNamedAgents(current.filter((agent) => agent.ref !== ref)));
|
|
108
|
+
}
|
|
109
|
+
const SENT_TEXTS_KEPT_PER_THREAD = 20;
|
|
110
|
+
const THREADS_WITH_SENT_TEXTS_KEPT = 50;
|
|
111
|
+
const WITHDRAWAL_RESTORES_KEPT = 20;
|
|
112
|
+
const sentTextNamedAgents = /* @__PURE__ */ new Map();
|
|
113
|
+
const withdrawalRestores = /* @__PURE__ */ new Map();
|
|
114
|
+
function rememberDeepAgentSentNamedAgents({
|
|
115
|
+
threadId,
|
|
116
|
+
text,
|
|
117
|
+
agents
|
|
118
|
+
}) {
|
|
119
|
+
if (!threadId) return;
|
|
120
|
+
const named = normalizeNamedAgents(agents);
|
|
121
|
+
const texts = sentTextNamedAgents.get(threadId);
|
|
122
|
+
if (named.length === 0) {
|
|
123
|
+
texts == null ? void 0 : texts.delete(text);
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
const kept = texts ?? /* @__PURE__ */ new Map();
|
|
127
|
+
setBounded(kept, text, named, SENT_TEXTS_KEPT_PER_THREAD);
|
|
128
|
+
setBounded(sentTextNamedAgents, threadId, kept, THREADS_WITH_SENT_TEXTS_KEPT);
|
|
129
|
+
}
|
|
130
|
+
function restoreDeepAgentSentNamedAgents({
|
|
131
|
+
threadId,
|
|
132
|
+
text,
|
|
133
|
+
withdrawnMessageId
|
|
134
|
+
}) {
|
|
135
|
+
var _a;
|
|
136
|
+
const named = ((_a = sentTextNamedAgents.get(threadId)) == null ? void 0 : _a.get(text)) ?? NO_NAMED_AGENTS;
|
|
137
|
+
const restored = named.filter((agent) => addDeepAgentNamedAgent({ threadId, agent }));
|
|
138
|
+
if (withdrawnMessageId !== void 0 && restored.length > 0) {
|
|
139
|
+
setBounded(
|
|
140
|
+
withdrawalRestores,
|
|
141
|
+
withdrawnMessageId,
|
|
142
|
+
{ threadId, agents: restored },
|
|
143
|
+
WITHDRAWAL_RESTORES_KEPT
|
|
144
|
+
);
|
|
145
|
+
}
|
|
146
|
+
return restored;
|
|
147
|
+
}
|
|
148
|
+
const NAMED_AGENTS_STAGED_TTL_MS = 1e4;
|
|
149
|
+
const stagedForSend = /* @__PURE__ */ new Map();
|
|
150
|
+
function stageDeepAgentNamedAgentsForSend({
|
|
151
|
+
threadId,
|
|
152
|
+
agents
|
|
153
|
+
}) {
|
|
154
|
+
if (!threadId) return;
|
|
155
|
+
const refs = namedAgentRefs(agents);
|
|
156
|
+
if (refs.length === 0) {
|
|
157
|
+
stagedForSend.delete(threadId);
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
stagedForSend.set(threadId, { refs, stagedAt: Date.now() });
|
|
161
|
+
}
|
|
162
|
+
function takeStagedDeepAgentNamedAgents(threadId) {
|
|
163
|
+
const staged = stagedForSend.get(threadId);
|
|
164
|
+
stagedForSend.delete(threadId);
|
|
165
|
+
if (staged === void 0 || Date.now() - staged.stagedAt > NAMED_AGENTS_STAGED_TTL_MS) {
|
|
166
|
+
return void 0;
|
|
167
|
+
}
|
|
168
|
+
return staged.refs;
|
|
169
|
+
}
|
|
170
|
+
function stagedNamedAgentsMessageMetadata(threadId) {
|
|
171
|
+
return withAddressedAgents(void 0, takeStagedDeepAgentNamedAgents(threadId));
|
|
172
|
+
}
|
|
173
|
+
function deepAgentOutboxAddressedAgents(agents) {
|
|
174
|
+
const refs = namedAgentRefs(agents);
|
|
175
|
+
return refs.length === 0 ? void 0 : refs;
|
|
176
|
+
}
|
|
177
|
+
function namedAgentsForRefsSeen(refs) {
|
|
178
|
+
const agents = [];
|
|
179
|
+
for (const ref of refs) {
|
|
180
|
+
const seen = namedAgentsSeen.get(ref);
|
|
181
|
+
if (seen) agents.push(seen);
|
|
182
|
+
else if (ref === OWN_ASSISTANT_AGENT_REF) {
|
|
183
|
+
agents.push({ ref, name: OWN_ASSISTANT_DISPLAY_NAME, assetId: null });
|
|
184
|
+
} else if (ref.startsWith(COLLAB_AGENT_REF_PREFIX)) {
|
|
185
|
+
agents.push({ ref, name: "Untitled agent", assetId: ref.slice(COLLAB_AGENT_REF_PREFIX.length) });
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
return agents;
|
|
189
|
+
}
|
|
190
|
+
function giveBackDeepAgentOutboxNamedAgents(entry, {
|
|
191
|
+
namedAgentsForRefs = namedAgentsForRefsSeen
|
|
192
|
+
} = {}) {
|
|
193
|
+
const refs = readAddressedAgents(entry.metadata);
|
|
194
|
+
if (!refs || refs.length === 0) return NO_NAMED_AGENTS;
|
|
195
|
+
return namedAgentsForRefs(refs).filter(
|
|
196
|
+
(agent) => addDeepAgentNamedAgent({ threadId: entry.threadId, agent })
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
function chatAgentNamingOffered({ isAdmin }) {
|
|
200
|
+
return isAdmin;
|
|
201
|
+
}
|
|
202
|
+
const OWN_ASSISTANT_DISPLAY_NAME = "Athena";
|
|
203
|
+
const OWN_ASSISTANT_OFFERED_AGENT = Object.freeze({
|
|
204
|
+
ref: OWN_ASSISTANT_AGENT_REF,
|
|
205
|
+
name: OWN_ASSISTANT_DISPLAY_NAME,
|
|
206
|
+
assetId: null,
|
|
207
|
+
icon: "Bot"
|
|
208
|
+
});
|
|
209
|
+
function collabAgentOfferedAgent({
|
|
210
|
+
assetId,
|
|
211
|
+
name,
|
|
212
|
+
icon
|
|
213
|
+
}) {
|
|
214
|
+
return {
|
|
215
|
+
ref: `${COLLAB_AGENT_REF_PREFIX}${assetId}`,
|
|
216
|
+
name: name || "Untitled agent",
|
|
217
|
+
assetId,
|
|
218
|
+
icon: icon || "Bot"
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
function offeredDeepAgentNamedAgents({
|
|
222
|
+
collabAgents,
|
|
223
|
+
named
|
|
224
|
+
}) {
|
|
225
|
+
if (named.length >= MAX_DEEP_AGENT_NAMED_AGENTS) return [];
|
|
226
|
+
const taken = new Set(named.map((agent) => agent.ref));
|
|
227
|
+
const offered = [];
|
|
228
|
+
for (const agent of [OWN_ASSISTANT_OFFERED_AGENT, ...collabAgents]) {
|
|
229
|
+
if (taken.has(agent.ref)) continue;
|
|
230
|
+
taken.add(agent.ref);
|
|
231
|
+
offered.push(agent);
|
|
232
|
+
}
|
|
233
|
+
return offered;
|
|
234
|
+
}
|
|
235
|
+
function namedAgentsLimitMessage(leftOut) {
|
|
236
|
+
const names = new Intl.ListFormat("en", { style: "long", type: "conjunction" }).format(leftOut);
|
|
237
|
+
return `A message names at most ${MAX_DEEP_AGENT_NAMED_AGENTS} agents, so ${names} ${leftOut.length === 1 ? "wasn't" : "weren't"} added.`;
|
|
238
|
+
}
|
|
239
|
+
function nameDeepAgentMentionedAgents({
|
|
240
|
+
threadId,
|
|
241
|
+
agents
|
|
242
|
+
}) {
|
|
243
|
+
const leftOut = [];
|
|
244
|
+
for (const agent of agents) {
|
|
245
|
+
const named = readDeepAgentNamedAgents(threadId);
|
|
246
|
+
if (named.some((entry) => entry.ref === agent.ref.trim())) continue;
|
|
247
|
+
if (named.length >= MAX_DEEP_AGENT_NAMED_AGENTS) {
|
|
248
|
+
leftOut.push(agent.name);
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
addDeepAgentNamedAgent({
|
|
252
|
+
threadId,
|
|
253
|
+
agent: { ref: agent.ref, name: agent.name, assetId: agent.assetId }
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
return leftOut;
|
|
257
|
+
}
|
|
258
|
+
let namedAgentsIdentity = null;
|
|
259
|
+
function forgetAllDeepAgentNamedAgents() {
|
|
260
|
+
stagedForSend.clear();
|
|
261
|
+
sentTextNamedAgents.clear();
|
|
262
|
+
withdrawalRestores.clear();
|
|
263
|
+
namedAgentsSeen.clear();
|
|
264
|
+
namedAgentsIdentity = null;
|
|
265
|
+
deepAgentNamedAgentsStore.setState(() => ({ byThread: {} }));
|
|
266
|
+
}
|
|
267
|
+
function keepDeepAgentNamedAgentsForIdentity(identity) {
|
|
268
|
+
if (namedAgentsIdentity !== null && namedAgentsIdentity !== identity) {
|
|
269
|
+
forgetAllDeepAgentNamedAgents();
|
|
270
|
+
}
|
|
271
|
+
namedAgentsIdentity = identity;
|
|
272
|
+
}
|
|
273
|
+
export {
|
|
274
|
+
COLLAB_AGENT_REF_PREFIX,
|
|
275
|
+
MAX_DEEP_AGENT_NAMED_AGENTS,
|
|
276
|
+
NAMED_AGENTS_STAGED_TTL_MS,
|
|
277
|
+
OWN_ASSISTANT_AGENT_REF,
|
|
278
|
+
OWN_ASSISTANT_DISPLAY_NAME,
|
|
279
|
+
OWN_ASSISTANT_OFFERED_AGENT,
|
|
280
|
+
addDeepAgentNamedAgent,
|
|
281
|
+
chatAgentNamingOffered,
|
|
282
|
+
collabAgentOfferedAgent,
|
|
283
|
+
deepAgentNamedAgentsStore,
|
|
284
|
+
deepAgentOutboxAddressedAgents,
|
|
285
|
+
forgetAllDeepAgentNamedAgents,
|
|
286
|
+
giveBackDeepAgentOutboxNamedAgents,
|
|
287
|
+
keepDeepAgentNamedAgentsForIdentity,
|
|
288
|
+
nameDeepAgentMentionedAgents,
|
|
289
|
+
namedAgentRefs,
|
|
290
|
+
namedAgentsLimitMessage,
|
|
291
|
+
offeredDeepAgentNamedAgents,
|
|
292
|
+
readDeepAgentNamedAgents,
|
|
293
|
+
rememberDeepAgentSentNamedAgents,
|
|
294
|
+
removeDeepAgentNamedAgent,
|
|
295
|
+
restoreDeepAgentSentNamedAgents,
|
|
296
|
+
stageDeepAgentNamedAgentsForSend,
|
|
297
|
+
stagedNamedAgentsMessageMetadata,
|
|
298
|
+
takeStagedDeepAgentNamedAgents,
|
|
299
|
+
useDeepAgentNamedAgents
|
|
300
|
+
};
|
|
301
|
+
//# sourceMappingURL=named-agents.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"named-agents.js","sources":["../../../../agent-runtime/src/named-agents.ts"],"sourcesContent":["import { useSyncExternalStore } from 'react';\nimport { ADDRESSED_AGENTS_METADATA_KEY, readAddressedAgents, withAddressedAgents } from './addressed-agents';\nimport type { ChatOutboxEntry } from './chat-outbox-entry';\n\n/**\n * The agents a message names (identity v7 D13): one conversation has many participants, and\n * each message goes to the agents it names, each answering in its own turn, in the order named.\n * agora reads the names from the message itself (`message.metadata.addressedAgents`,\n * `addressed-agents.ts`) ahead of the run config's `addressed_agents`, and checks every one of them\n * (the collab overlay's VIEW gate, a colleague's assistant refused, the history re-check), so the\n * client only presents what the person can pick and never gates.\n *\n * Every chat that names agents runs on this one module: Olympus's deep-agent composer (whose\n * `deep-agent-named-agents.ts` re-exports it) and the SDK's `AthenaChat` (and so Athena Desktop),\n * so naming an agent means the same thing, and reaches agora as the same payload, in both. What a\n * composer's `@` menu offers to name is {@link offeredDeepAgentNamedAgents}.\n *\n * - **The chips.** The agents the composer's To line names for each thread, in the order named\n * (`set` / `add` / `remove` / `clear`, read with {@link useDeepAgentNamedAgents}). They stay\n * for every message until the person changes them. Anything may set a thread's chips; its\n * composer shows them. Kept in memory for the page, and dropped when the signed-in identity\n * changes ({@link keepDeepAgentNamedAgentsForIdentity}).\n * - **The send.** statewire captures a new message's metadata once, as it journals it\n * (`getMessageMetadata`), without saying which message it is for. So the composer stages the\n * chips for its next send right before `aui.composer.send`\n * ({@link stageDeepAgentNamedAgentsForSend}), and the runtime's getter takes them for the message\n * that follows ({@link takeStagedDeepAgentNamedAgents}, {@link stagedNamedAgentsMessageMetadata}).\n * The names then travel with the message: a send that waits, is retried after a failure, or is\n * posted again by a page reloaded meanwhile names its own agents, whatever the conversation's\n * context says by then, so no send waits for another's. A slot nobody takes expires.\n * - **The chat outbox.** A message held while Athena can't be reached carries its names on its\n * message the same way (`ChatOutbox.hold({ addressedAgents })`,\n * {@link deepAgentOutboxAddressedAgents}); its Cancel gives them back as chips with its text\n * ({@link giveBackDeepAgentOutboxNamedAgents}).\n *\n * Text a send carried that comes back to the composer (a failed send handed back, an early Stop)\n * brings its chips back ({@link restoreDeepAgentSentNamedAgents}).\n *\n * State is per copy of this module: Olympus runs agent-runtime from source, and the SDK bundles\n * its own copy, whose composer and runtime share it.\n */\n\n/**\n * The message metadata key of the agents a message names (agora:\n * `agent_refs.ADDRESSED_AGENTS_METADATA_KEY`, read in place of the run config's and never kept on\n * the turn the transcript records).\n */\nexport const DEEP_AGENT_MESSAGE_ADDRESSED_AGENTS_KEY = ADDRESSED_AGENTS_METADATA_KEY;\n\nexport interface DeepAgentNamedAgent {\n /** What the send names: `collab_agent:<asset id>`, or `assistant` (the sender's own assistant). */\n ref: string;\n /** What the chip shows. */\n name: string;\n /** The collab agent asset behind `ref`; `null` for the sender's own assistant. */\n assetId: string | null;\n}\n\n/** agora takes at most this many names on one message. */\nexport const MAX_DEEP_AGENT_NAMED_AGENTS = 8;\n\n/** The ref of the sender's own assistant. */\nexport const OWN_ASSISTANT_AGENT_REF = 'assistant';\n\n/** The prefix of a collab agent's ref (`collab_agent:<asset id>`). */\nexport const COLLAB_AGENT_REF_PREFIX = 'collab_agent:';\n\nconst NO_NAMED_AGENTS: readonly DeepAgentNamedAgent[] = Object.freeze([]);\n\n/** Each agent once (by ref, the first kept), in the order named, at most eight; blank refs dropped. */\nfunction normalizeNamedAgents(\n agents: readonly DeepAgentNamedAgent[]\n): readonly DeepAgentNamedAgent[] {\n const seen = new Set<string>();\n const normalized: DeepAgentNamedAgent[] = [];\n for (const agent of agents) {\n const ref = agent.ref.trim();\n if (!ref || seen.has(ref)) continue;\n seen.add(ref);\n normalized.push(ref === agent.ref ? agent : { ...agent, ref });\n if (normalized.length === MAX_DEEP_AGENT_NAMED_AGENTS) break;\n }\n return normalized.length === 0 ? NO_NAMED_AGENTS : normalized;\n}\n\nfunction sameNamedAgents(\n a: readonly DeepAgentNamedAgent[],\n b: readonly DeepAgentNamedAgent[]\n): boolean {\n return (\n a.length === b.length &&\n a.every(\n (agent, index) =>\n agent.ref === b[index]?.ref &&\n agent.name === b[index]?.name &&\n agent.assetId === b[index]?.assetId\n )\n );\n}\n\n/** The refs a message naming `agents` sends: in the order named, each once, at most eight. */\nexport function namedAgentRefs(agents: readonly Pick<DeepAgentNamedAgent, 'ref'>[]): string[] {\n const refs: string[] = [];\n for (const agent of agents) {\n const ref = agent.ref.trim();\n if (!ref || refs.includes(ref)) continue;\n refs.push(ref);\n if (refs.length === MAX_DEEP_AGENT_NAMED_AGENTS) break;\n }\n return refs;\n}\n\n/** What a send naming `agents` names, as one key: two sends name the same agents when equal. */\nexport function namedAgentsKey(agents: readonly Pick<DeepAgentNamedAgent, 'ref'>[]): string {\n return namedAgentRefs(agents).join('\\n');\n}\n\n/**\n * Named agents read back from storage (a draft kept across a reload, a message waiting in the chat\n * outbox): a list of `{ ref, name, assetId }` with a non-empty ref and name and an asset id that is\n * a string or `null`, each agent once, at most eight. Anything else reads as naming none, entry by\n * entry, so a newer build's extra fields never break an older reader.\n */\nexport function parseDeepAgentNamedAgents(value: unknown): readonly DeepAgentNamedAgent[] {\n if (!Array.isArray(value)) return NO_NAMED_AGENTS;\n const agents: DeepAgentNamedAgent[] = [];\n for (const item of value) {\n if (typeof item !== 'object' || item === null) continue;\n const ref: unknown = Reflect.get(item, 'ref');\n const name: unknown = Reflect.get(item, 'name');\n const assetId: unknown = Reflect.get(item, 'assetId');\n if (typeof ref !== 'string' || !ref.trim() || typeof name !== 'string' || !name.trim())\n continue;\n if (assetId !== null && typeof assetId !== 'string') continue;\n agents.push({ ref, name, assetId });\n }\n return normalizeNamedAgents(agents);\n}\n\n/** A small map that keeps its newest `limit` entries (insertion order is age). */\nfunction setBounded<K, V>(map: Map<K, V>, key: K, value: V, limit: number): void {\n map.delete(key);\n map.set(key, value);\n while (map.size > limit) {\n const oldest = map.keys().next();\n if (oldest.done) break;\n map.delete(oldest.value);\n }\n}\n\n// ── The stores ──────────────────────────────────────────────────────────────\n\n/** A value its readers follow: a write that changes it tells every listener, synchronously. */\nexport interface NamedAgentsStore<T> {\n readonly state: T;\n /** Replace the value with what `update` returns; returning the value it was given changes nothing. */\n setState: (update: (state: T) => T) => void;\n /** Called after every change; returns the unsubscribe function. */\n subscribe: (listener: () => void) => () => void;\n}\n\nfunction createNamedAgentsStore<T>(initial: T): NamedAgentsStore<T> {\n let state = initial;\n const listeners = new Set<() => void>();\n return {\n get state() {\n return state;\n },\n setState(update) {\n const next = update(state);\n if (Object.is(next, state)) return;\n state = next;\n for (const listener of [...listeners]) listener();\n },\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n };\n}\n\n// ── The chips ───────────────────────────────────────────────────────────────\n\ninterface DeepAgentNamedAgentsState {\n /** Each thread's named agents (its composer's chips), in the order named. */\n byThread: Readonly<Record<string, readonly DeepAgentNamedAgent[]>>;\n}\n\nexport const deepAgentNamedAgentsStore = createNamedAgentsStore<DeepAgentNamedAgentsState>({\n byThread: {},\n});\n\n// process-local: client-only — the last name and asset this page gave each agent it named, so a\n// message given back with only its refs comes back with the chips it was sent with.\nconst namedAgentsSeen = new Map<string, DeepAgentNamedAgent>();\nconst NAMED_AGENTS_SEEN_KEPT = 200;\n\nfunction writeNamedAgents(threadId: string, agents: readonly DeepAgentNamedAgent[]): void {\n for (const agent of agents) setBounded(namedAgentsSeen, agent.ref, agent, NAMED_AGENTS_SEEN_KEPT);\n deepAgentNamedAgentsStore.setState((state) => {\n if (sameNamedAgents(state.byThread[threadId] ?? NO_NAMED_AGENTS, agents)) return state;\n const byThread = { ...state.byThread };\n if (agents.length === 0) delete byThread[threadId];\n else byThread[threadId] = agents;\n return { byThread };\n });\n}\n\n/** The agents `threadId`'s composer names for its next message, in the order named. */\nexport function useDeepAgentNamedAgents(threadId: string): readonly DeepAgentNamedAgent[] {\n const read = (): readonly DeepAgentNamedAgent[] => readDeepAgentNamedAgents(threadId);\n return useSyncExternalStore(deepAgentNamedAgentsStore.subscribe, read, read);\n}\n\n/** Imperative read of {@link useDeepAgentNamedAgents} (for send paths and handlers). */\nexport function readDeepAgentNamedAgents(threadId: string): readonly DeepAgentNamedAgent[] {\n return deepAgentNamedAgentsStore.state.byThread[threadId] ?? NO_NAMED_AGENTS;\n}\n\n/**\n * Listen for `threadId`'s chips changing (the composer keeps them with its draft). Another\n * thread's change notifies nothing. Returns the unsubscribe function.\n */\nexport function subscribeDeepAgentNamedAgents({\n threadId,\n listener,\n}: {\n threadId: string;\n listener: () => void;\n}): () => void {\n let agents = readDeepAgentNamedAgents(threadId);\n return deepAgentNamedAgentsStore.subscribe(() => {\n const next = readDeepAgentNamedAgents(threadId);\n if (next === agents) return;\n agents = next;\n listener();\n });\n}\n\n/** Name exactly `agents` for `threadId`'s next message (each once, in order, at most eight). */\nexport function setDeepAgentNamedAgents({\n threadId,\n agents,\n}: {\n threadId: string;\n agents: readonly DeepAgentNamedAgent[];\n}): void {\n if (!threadId) return;\n writeNamedAgents(threadId, normalizeNamedAgents(agents));\n}\n\n/**\n * Name one more agent, after those already named. `false` when nothing changed: it is named\n * already, eight are named, or its ref is blank.\n */\nexport function addDeepAgentNamedAgent({\n threadId,\n agent,\n}: {\n threadId: string;\n agent: DeepAgentNamedAgent;\n}): boolean {\n const current = readDeepAgentNamedAgents(threadId);\n const ref = agent.ref.trim();\n if (\n !threadId ||\n !ref ||\n current.length >= MAX_DEEP_AGENT_NAMED_AGENTS ||\n current.some((named) => named.ref === ref)\n ) {\n return false;\n }\n writeNamedAgents(threadId, normalizeNamedAgents([...current, agent]));\n return true;\n}\n\nexport function removeDeepAgentNamedAgent({\n threadId,\n ref,\n}: {\n threadId: string;\n ref: string;\n}): void {\n const current = readDeepAgentNamedAgents(threadId);\n if (!current.some((agent) => agent.ref === ref)) return;\n writeNamedAgents(threadId, normalizeNamedAgents(current.filter((agent) => agent.ref !== ref)));\n}\n\nexport function clearDeepAgentNamedAgents({ threadId }: { threadId: string }): void {\n writeNamedAgents(threadId, NO_NAMED_AGENTS);\n}\n\n/**\n * Clear `threadId`'s chips once the message that named `agents` has left, but only while they\n * still are those agents: names changed since the message was sent (while it waited behind a\n * loading conversation) belong to the next message and stay. Returns whether they were cleared.\n */\nexport function clearDeepAgentNamedAgentsIfUnchanged({\n threadId,\n agents,\n}: {\n threadId: string;\n agents: readonly DeepAgentNamedAgent[];\n}): boolean {\n const current = readDeepAgentNamedAgents(threadId);\n if (current.length === 0) return false;\n if (namedAgentRefs(current).join('\\n') !== namedAgentRefs(agents).join('\\n')) return false;\n clearDeepAgentNamedAgents({ threadId });\n return true;\n}\n\n// ── Text that comes back to the composer ────────────────────────────────────\n\n/** How many sent texts each thread remembers the names of, and how many threads. */\nconst SENT_TEXTS_KEPT_PER_THREAD = 20;\nconst THREADS_WITH_SENT_TEXTS_KEPT = 50;\nconst WITHDRAWAL_RESTORES_KEPT = 20;\n\n// process-local: client-only — the names each recent send carried, per thread by its sent text\n// (the verbatim text the runtime hands back), so text that comes back brings its chips back.\nconst sentTextNamedAgents = new Map<string, Map<string, readonly DeepAgentNamedAgent[]>>();\n\n// process-local: client-only — the chips an early Stop gave back, by the withdrawn message, so a\n// contradicted withdrawal takes them away again.\nconst withdrawalRestores = new Map<\n string,\n { threadId: string; agents: readonly DeepAgentNamedAgent[] }\n>();\n\n/** Remember the names a send of `text` carried (a send naming none forgets earlier ones). */\nexport function rememberDeepAgentSentNamedAgents({\n threadId,\n text,\n agents,\n}: {\n threadId: string;\n text: string;\n agents: readonly DeepAgentNamedAgent[];\n}): void {\n if (!threadId) return;\n const named = normalizeNamedAgents(agents);\n const texts = sentTextNamedAgents.get(threadId);\n if (named.length === 0) {\n texts?.delete(text);\n return;\n }\n const kept = texts ?? new Map<string, readonly DeepAgentNamedAgent[]>();\n setBounded(kept, text, named, SENT_TEXTS_KEPT_PER_THREAD);\n setBounded(sentTextNamedAgents, threadId, kept, THREADS_WITH_SENT_TEXTS_KEPT);\n}\n\n/**\n * Text a send carried came back to `threadId`'s composer (a failed send handed back, an early\n * Stop): the names it carried come back as chips, after any named since (each once, at most\n * eight). `withdrawnMessageId` marks an early Stop's turn, whose chips go again if the run\n * answers it after all ({@link undoDeepAgentWithdrawalNamedAgents}). Returns the agents put back.\n */\nexport function restoreDeepAgentSentNamedAgents({\n threadId,\n text,\n withdrawnMessageId,\n}: {\n threadId: string;\n text: string;\n withdrawnMessageId?: string;\n}): readonly DeepAgentNamedAgent[] {\n const named = sentTextNamedAgents.get(threadId)?.get(text) ?? NO_NAMED_AGENTS;\n const restored = named.filter((agent) => addDeepAgentNamedAgent({ threadId, agent }));\n if (withdrawnMessageId !== undefined && restored.length > 0) {\n setBounded(\n withdrawalRestores,\n withdrawnMessageId,\n { threadId, agents: restored },\n WITHDRAWAL_RESTORES_KEPT\n );\n }\n return restored;\n}\n\n/**\n * The run answered a turn its sender took back after all (an early Stop contradicted): the chips\n * that came back with its text go again, except any taken off since.\n */\nexport function undoDeepAgentWithdrawalNamedAgents({ messageId }: { messageId: string }): void {\n const restore = withdrawalRestores.get(messageId);\n if (!restore) return;\n withdrawalRestores.delete(messageId);\n for (const agent of restore.agents) {\n removeDeepAgentNamedAgent({ threadId: restore.threadId, ref: agent.ref });\n }\n}\n\n/** A withdrawal settled without undoing its restore (the editor changed since): forget it. */\nexport function forgetDeepAgentWithdrawalNamedAgents({ messageId }: { messageId: string }): void {\n withdrawalRestores.delete(messageId);\n}\n\n// ── The send ────────────────────────────────────────────────────────────────\n\n/** How long staged names wait for the message they were staged for before they expire. */\nexport const NAMED_AGENTS_STAGED_TTL_MS = 10_000;\n\n// process-local: client-only — the names each thread's composer staged for the message it submits\n// next, taken once by the runtime's `getMessageMetadata`.\nconst stagedForSend = new Map<string, { refs: readonly string[]; stagedAt: number }>();\n\n/**\n * Stage `agents` as the names of the message `threadId`'s composer submits next. Call right before\n * the send (`aui.composer.send`): the runtime's `getMessageMetadata` takes them for that message\n * ({@link takeStagedDeepAgentNamedAgents}). A send naming none stages nothing and lets an earlier\n * slot go.\n */\nexport function stageDeepAgentNamedAgentsForSend({\n threadId,\n agents,\n}: {\n threadId: string;\n agents: readonly DeepAgentNamedAgent[];\n}): void {\n if (!threadId) return;\n const refs = namedAgentRefs(agents);\n if (refs.length === 0) {\n stagedForSend.delete(threadId);\n return;\n }\n stagedForSend.set(threadId, { refs, stagedAt: Date.now() });\n}\n\n/**\n * The refs staged for the message `threadId` journals now, taking the slot (`undefined`: none\n * staged, or staged more than {@link NAMED_AGENTS_STAGED_TTL_MS} ago).\n */\nexport function takeStagedDeepAgentNamedAgents(threadId: string): readonly string[] | undefined {\n const staged = stagedForSend.get(threadId);\n stagedForSend.delete(threadId);\n if (staged === undefined || Date.now() - staged.stagedAt > NAMED_AGENTS_STAGED_TTL_MS) {\n return undefined;\n }\n return staged.refs;\n}\n\n/**\n * The metadata of the message `threadId` journals now, for a runtime's `getMessageMetadata` (the\n * SDK's): the names staged for it under {@link DEEP_AGENT_MESSAGE_ADDRESSED_AGENTS_KEY}, taking the\n * slot, or `undefined` when none are staged (the message then names none of its own). Olympus's\n * runtime takes the slot itself, falling back to the conversation's default agent.\n */\nexport function stagedNamedAgentsMessageMetadata(\n threadId: string\n): Record<string, unknown> | undefined {\n return withAddressedAgents(undefined, takeStagedDeepAgentNamedAgents(threadId));\n}\n\n// ── The chat outbox ─────────────────────────────────────────────────────────\n\n/**\n * The agents a message held in the chat outbox names (`ChatOutbox.hold`'s `addressedAgents`, kept\n * on its message): its chips' refs, or `undefined` when it names none (it then goes out as a send\n * naming none does).\n */\nexport function deepAgentOutboxAddressedAgents(\n agents: readonly DeepAgentNamedAgent[]\n): string[] | undefined {\n const refs = namedAgentRefs(agents);\n return refs.length === 0 ? undefined : refs;\n}\n\n/**\n * The chips for refs a message carries, named as this page last named those agents: the person's\n * own assistant as the menu names it, a collab agent the page never named as \"Untitled agent\",\n * and any other ref not at all.\n */\nfunction namedAgentsForRefsSeen(refs: readonly string[]): DeepAgentNamedAgent[] {\n const agents: DeepAgentNamedAgent[] = [];\n for (const ref of refs) {\n const seen = namedAgentsSeen.get(ref);\n if (seen) agents.push(seen);\n else if (ref === OWN_ASSISTANT_AGENT_REF) {\n agents.push({ ref, name: OWN_ASSISTANT_DISPLAY_NAME, assetId: null });\n } else if (ref.startsWith(COLLAB_AGENT_REF_PREFIX)) {\n agents.push({ ref, name: 'Untitled agent', assetId: ref.slice(COLLAB_AGENT_REF_PREFIX.length) });\n }\n }\n return agents;\n}\n\n/**\n * A waiting message went back to the composer (Cancel, or the ask's Edit): the agents it named\n * (`message.metadata.addressedAgents`) come back as chips with its text, after any named since.\n * The message keeps only refs, so each chip is named by `namedAgentsForRefs` (a host's agent list,\n * as its `@` menu names them), else as this page last named it. Returns the agents put back.\n */\nexport function giveBackDeepAgentOutboxNamedAgents(\n entry: Pick<ChatOutboxEntry, 'threadId' | 'metadata'>,\n {\n namedAgentsForRefs = namedAgentsForRefsSeen,\n }: { namedAgentsForRefs?: (refs: readonly string[]) => readonly DeepAgentNamedAgent[] } = {}\n): readonly DeepAgentNamedAgent[] {\n const refs = readAddressedAgents(entry.metadata);\n if (!refs || refs.length === 0) return NO_NAMED_AGENTS;\n return namedAgentsForRefs(refs).filter((agent) =>\n addDeepAgentNamedAgent({ threadId: entry.threadId, agent })\n );\n}\n\n// ── What a composer's `@` menu offers ───────────────────────────────────────\n\n/**\n * Whether the `@` menu's Agents section is offered to Athena admins alone, for now (#50245). One\n * switch for every chat that names agents (Olympus's composer, the SDK's `AthenaChat`): while it\n * is `true`, only an admin is offered the section, and only an admin's root search finds an agent.\n * It decides who is offered the menu, nothing more: agora checks every name a message carries.\n */\nexport const CHAT_AGENT_NAMING_ADMIN_ONLY = true;\n\n/** Whether a viewer is offered the `@` menu's Agents section ({@link CHAT_AGENT_NAMING_ADMIN_ONLY}). */\nexport function chatAgentNamingOffered({ isAdmin }: { isAdmin: boolean }): boolean {\n return !CHAT_AGENT_NAMING_ADMIN_ONLY || isAdmin;\n}\n\n/** An agent a composer's `@` menu offers to name. */\nexport interface DeepAgentOfferedAgent extends DeepAgentNamedAgent {\n /** A Lucide icon name for the menu row. */\n icon: string;\n}\n\n/** What the person's own assistant is called in the menu and on its chip. */\nexport const OWN_ASSISTANT_DISPLAY_NAME = 'Athena';\n\n/** The person's own assistant, as the menu offers it. */\nexport const OWN_ASSISTANT_OFFERED_AGENT: DeepAgentOfferedAgent = Object.freeze({\n ref: OWN_ASSISTANT_AGENT_REF,\n name: OWN_ASSISTANT_DISPLAY_NAME,\n assetId: null,\n icon: 'Bot',\n});\n\n/** A collab agent as the menu offers it: its ref, its name (else \"Untitled agent\"), its icon (else a bot). */\nexport function collabAgentOfferedAgent({\n assetId,\n name,\n icon,\n}: {\n assetId: string;\n name: string;\n icon?: string | null;\n}): DeepAgentOfferedAgent {\n return {\n ref: `${COLLAB_AGENT_REF_PREFIX}${assetId}`,\n name: name || 'Untitled agent',\n assetId,\n icon: icon || 'Bot',\n };\n}\n\n/**\n * The agents a composer's `@` menu offers to name: the person's own assistant\n * ({@link OWN_ASSISTANT_OFFERED_AGENT}), then `collabAgents` (the collab agents the composer's agent\n * picker lists) in their order, each once, minus the ones already named; none once eight are named.\n */\nexport function offeredDeepAgentNamedAgents({\n collabAgents,\n named,\n}: {\n collabAgents: readonly DeepAgentOfferedAgent[];\n named: readonly DeepAgentNamedAgent[];\n}): DeepAgentOfferedAgent[] {\n if (named.length >= MAX_DEEP_AGENT_NAMED_AGENTS) return [];\n const taken = new Set(named.map((agent) => agent.ref));\n const offered: DeepAgentOfferedAgent[] = [];\n for (const agent of [OWN_ASSISTANT_OFFERED_AGENT, ...collabAgents]) {\n if (taken.has(agent.ref)) continue;\n taken.add(agent.ref);\n offered.push(agent);\n }\n return offered;\n}\n\n/** What the composer says when a choice would name more agents than one message takes. */\nexport function namedAgentsLimitMessage(leftOut: readonly string[]): string {\n const names = new Intl.ListFormat('en', { style: 'long', type: 'conjunction' }).format(leftOut);\n return `A message names at most ${MAX_DEEP_AGENT_NAMED_AGENTS} agents, so ${names} ${\n leftOut.length === 1 ? \"wasn't\" : \"weren't\"\n } added.`;\n}\n\n/**\n * Name `agents` for `threadId`'s next message, in the order given, after those already named.\n * Returns the names of the ones left out because eight were named; an agent named already is\n * not left out, it simply stays where it is.\n */\nexport function nameDeepAgentMentionedAgents({\n threadId,\n agents,\n}: {\n threadId: string;\n agents: readonly DeepAgentNamedAgent[];\n}): string[] {\n const leftOut: string[] = [];\n for (const agent of agents) {\n const named = readDeepAgentNamedAgents(threadId);\n if (named.some((entry) => entry.ref === agent.ref.trim())) continue;\n if (named.length >= MAX_DEEP_AGENT_NAMED_AGENTS) {\n leftOut.push(agent.name);\n continue;\n }\n addDeepAgentNamedAgent({\n threadId,\n agent: { ref: agent.ref, name: agent.name, assetId: agent.assetId },\n });\n }\n return leftOut;\n}\n\n// ── The signed-in identity ──────────────────────────────────────────────────\n\n// process-local: client-only — the signed-in identity this page's names were made under.\nlet namedAgentsIdentity: string | null = null;\n\n/** Drop every chip, staged send and remembered name in this page. */\nexport function forgetAllDeepAgentNamedAgents(): void {\n stagedForSend.clear();\n sentTextNamedAgents.clear();\n withdrawalRestores.clear();\n namedAgentsSeen.clear();\n namedAgentsIdentity = null;\n deepAgentNamedAgentsStore.setState(() => ({ byThread: {} }));\n}\n\n/**\n * `identity` is signed in (Olympus's `DeepAgentSessionLoginReset`, the SDK's `AthenaChat`): names\n * this page made under another identity (an account switch in the page or another tab, an\n * impersonation starting or ending, someone else signing in without a reload) are not this\n * person's to send, so they all go.\n */\nexport function keepDeepAgentNamedAgentsForIdentity(identity: string): void {\n if (namedAgentsIdentity !== null && namedAgentsIdentity !== identity) {\n forgetAllDeepAgentNamedAgents();\n }\n namedAgentsIdentity = identity;\n}\n"],"names":[],"mappings":";;AA2DO,MAAM,8BAA8B;AAGpC,MAAM,0BAA0B;AAGhC,MAAM,0BAA0B;AAEvC,MAAM,kBAAkD,OAAO,OAAO,EAAE;AAGxE,SAAS,qBACP,QACgC;AAChC,QAAM,2BAAW,IAAA;AACjB,QAAM,aAAoC,CAAA;AAC1C,aAAW,SAAS,QAAQ;AAC1B,UAAM,MAAM,MAAM,IAAI,KAAA;AACtB,QAAI,CAAC,OAAO,KAAK,IAAI,GAAG,EAAG;AAC3B,SAAK,IAAI,GAAG;AACZ,eAAW,KAAK,QAAQ,MAAM,MAAM,QAAQ,EAAE,GAAG,OAAO,KAAK;AAC7D,QAAI,WAAW,WAAW,4BAA6B;AAAA,EACzD;AACA,SAAO,WAAW,WAAW,IAAI,kBAAkB;AACrD;AAEA,SAAS,gBACP,GACA,GACS;AACT,SACE,EAAE,WAAW,EAAE,UACf,EAAE;AAAA,IACA,CAAC,OAAO;;AACN,mBAAM,UAAQ,OAAE,KAAK,MAAP,mBAAU,QACxB,MAAM,WAAS,OAAE,KAAK,MAAP,mBAAU,SACzB,MAAM,cAAY,OAAE,KAAK,MAAP,mBAAU;AAAA;AAAA,EAAA;AAGpC;AAGO,SAAS,eAAe,QAA+D;AAC5F,QAAM,OAAiB,CAAA;AACvB,aAAW,SAAS,QAAQ;AAC1B,UAAM,MAAM,MAAM,IAAI,KAAA;AACtB,QAAI,CAAC,OAAO,KAAK,SAAS,GAAG,EAAG;AAChC,SAAK,KAAK,GAAG;AACb,QAAI,KAAK,WAAW,4BAA6B;AAAA,EACnD;AACA,SAAO;AACT;AA8BA,SAAS,WAAiB,KAAgB,KAAQ,OAAU,OAAqB;AAC/E,MAAI,OAAO,GAAG;AACd,MAAI,IAAI,KAAK,KAAK;AAClB,SAAO,IAAI,OAAO,OAAO;AACvB,UAAM,SAAS,IAAI,KAAA,EAAO,KAAA;AAC1B,QAAI,OAAO,KAAM;AACjB,QAAI,OAAO,OAAO,KAAK;AAAA,EACzB;AACF;AAaA,SAAS,uBAA0B,SAAiC;AAClE,MAAI,QAAQ;AACZ,QAAM,gCAAgB,IAAA;AACtB,SAAO;AAAA,IACL,IAAI,QAAQ;AACV,aAAO;AAAA,IACT;AAAA,IACA,SAAS,QAAQ;AACf,YAAM,OAAO,OAAO,KAAK;AACzB,UAAI,OAAO,GAAG,MAAM,KAAK,EAAG;AAC5B,cAAQ;AACR,iBAAW,YAAY,CAAC,GAAG,SAAS,EAAG,UAAA;AAAA,IACzC;AAAA,IACA,UAAU,UAAU;AAClB,gBAAU,IAAI,QAAQ;AACtB,aAAO,MAAM;AACX,kBAAU,OAAO,QAAQ;AAAA,MAC3B;AAAA,IACF;AAAA,EAAA;AAEJ;AASO,MAAM,4BAA4B,uBAAkD;AAAA,EACzF,UAAU,CAAA;AACZ,CAAC;AAID,MAAM,sCAAsB,IAAA;AAC5B,MAAM,yBAAyB;AAE/B,SAAS,iBAAiB,UAAkB,QAA8C;AACxF,aAAW,SAAS,OAAQ,YAAW,iBAAiB,MAAM,KAAK,OAAO,sBAAsB;AAChG,4BAA0B,SAAS,CAAC,UAAU;AAC5C,QAAI,gBAAgB,MAAM,SAAS,QAAQ,KAAK,iBAAiB,MAAM,EAAG,QAAO;AACjF,UAAM,WAAW,EAAE,GAAG,MAAM,SAAA;AAC5B,QAAI,OAAO,WAAW,EAAG,QAAO,SAAS,QAAQ;AAAA,QAC5C,UAAS,QAAQ,IAAI;AAC1B,WAAO,EAAE,SAAA;AAAA,EACX,CAAC;AACH;AAGO,SAAS,wBAAwB,UAAkD;AACxF,QAAM,OAAO,MAAsC,yBAAyB,QAAQ;AACpF,SAAO,qBAAqB,0BAA0B,WAAW,MAAM,IAAI;AAC7E;AAGO,SAAS,yBAAyB,UAAkD;AACzF,SAAO,0BAA0B,MAAM,SAAS,QAAQ,KAAK;AAC/D;AAsCO,SAAS,uBAAuB;AAAA,EACrC;AAAA,EACA;AACF,GAGY;AACV,QAAM,UAAU,yBAAyB,QAAQ;AACjD,QAAM,MAAM,MAAM,IAAI,KAAA;AACtB,MACE,CAAC,YACD,CAAC,OACD,QAAQ,UAAU,+BAClB,QAAQ,KAAK,CAAC,UAAU,MAAM,QAAQ,GAAG,GACzC;AACA,WAAO;AAAA,EACT;AACA,mBAAiB,UAAU,qBAAqB,CAAC,GAAG,SAAS,KAAK,CAAC,CAAC;AACpE,SAAO;AACT;AAEO,SAAS,0BAA0B;AAAA,EACxC;AAAA,EACA;AACF,GAGS;AACP,QAAM,UAAU,yBAAyB,QAAQ;AACjD,MAAI,CAAC,QAAQ,KAAK,CAAC,UAAU,MAAM,QAAQ,GAAG,EAAG;AACjD,mBAAiB,UAAU,qBAAqB,QAAQ,OAAO,CAAC,UAAU,MAAM,QAAQ,GAAG,CAAC,CAAC;AAC/F;AA4BA,MAAM,6BAA6B;AACnC,MAAM,+BAA+B;AACrC,MAAM,2BAA2B;AAIjC,MAAM,0CAA0B,IAAA;AAIhC,MAAM,yCAAyB,IAAA;AAMxB,SAAS,iCAAiC;AAAA,EAC/C;AAAA,EACA;AAAA,EACA;AACF,GAIS;AACP,MAAI,CAAC,SAAU;AACf,QAAM,QAAQ,qBAAqB,MAAM;AACzC,QAAM,QAAQ,oBAAoB,IAAI,QAAQ;AAC9C,MAAI,MAAM,WAAW,GAAG;AACtB,mCAAO,OAAO;AACd;AAAA,EACF;AACA,QAAM,OAAO,SAAS,oBAAI,IAAA;AAC1B,aAAW,MAAM,MAAM,OAAO,0BAA0B;AACxD,aAAW,qBAAqB,UAAU,MAAM,4BAA4B;AAC9E;AAQO,SAAS,gCAAgC;AAAA,EAC9C;AAAA,EACA;AAAA,EACA;AACF,GAImC;;AACjC,QAAM,UAAQ,yBAAoB,IAAI,QAAQ,MAAhC,mBAAmC,IAAI,UAAS;AAC9D,QAAM,WAAW,MAAM,OAAO,CAAC,UAAU,uBAAuB,EAAE,UAAU,MAAA,CAAO,CAAC;AACpF,MAAI,uBAAuB,UAAa,SAAS,SAAS,GAAG;AAC3D;AAAA,MACE;AAAA,MACA;AAAA,MACA,EAAE,UAAU,QAAQ,SAAA;AAAA,MACpB;AAAA,IAAA;AAAA,EAEJ;AACA,SAAO;AACT;AAuBO,MAAM,6BAA6B;AAI1C,MAAM,oCAAoB,IAAA;AAQnB,SAAS,iCAAiC;AAAA,EAC/C;AAAA,EACA;AACF,GAGS;AACP,MAAI,CAAC,SAAU;AACf,QAAM,OAAO,eAAe,MAAM;AAClC,MAAI,KAAK,WAAW,GAAG;AACrB,kBAAc,OAAO,QAAQ;AAC7B;AAAA,EACF;AACA,gBAAc,IAAI,UAAU,EAAE,MAAM,UAAU,KAAK,IAAA,GAAO;AAC5D;AAMO,SAAS,+BAA+B,UAAiD;AAC9F,QAAM,SAAS,cAAc,IAAI,QAAQ;AACzC,gBAAc,OAAO,QAAQ;AAC7B,MAAI,WAAW,UAAa,KAAK,QAAQ,OAAO,WAAW,4BAA4B;AACrF,WAAO;AAAA,EACT;AACA,SAAO,OAAO;AAChB;AAQO,SAAS,iCACd,UACqC;AACrC,SAAO,oBAAoB,QAAW,+BAA+B,QAAQ,CAAC;AAChF;AASO,SAAS,+BACd,QACsB;AACtB,QAAM,OAAO,eAAe,MAAM;AAClC,SAAO,KAAK,WAAW,IAAI,SAAY;AACzC;AAOA,SAAS,uBAAuB,MAAgD;AAC9E,QAAM,SAAgC,CAAA;AACtC,aAAW,OAAO,MAAM;AACtB,UAAM,OAAO,gBAAgB,IAAI,GAAG;AACpC,QAAI,KAAM,QAAO,KAAK,IAAI;AAAA,aACjB,QAAQ,yBAAyB;AACxC,aAAO,KAAK,EAAE,KAAK,MAAM,4BAA4B,SAAS,MAAM;AAAA,IACtE,WAAW,IAAI,WAAW,uBAAuB,GAAG;AAClD,aAAO,KAAK,EAAE,KAAK,MAAM,kBAAkB,SAAS,IAAI,MAAM,wBAAwB,MAAM,EAAA,CAAG;AAAA,IACjG;AAAA,EACF;AACA,SAAO;AACT;AAQO,SAAS,mCACd,OACA;AAAA,EACE,qBAAqB;AACvB,IAA0F,IAC1D;AAChC,QAAM,OAAO,oBAAoB,MAAM,QAAQ;AAC/C,MAAI,CAAC,QAAQ,KAAK,WAAW,EAAG,QAAO;AACvC,SAAO,mBAAmB,IAAI,EAAE;AAAA,IAAO,CAAC,UACtC,uBAAuB,EAAE,UAAU,MAAM,UAAU,OAAO;AAAA,EAAA;AAE9D;AAaO,SAAS,uBAAuB,EAAE,WAA0C;AACjF,SAAwC;AAC1C;AASO,MAAM,6BAA6B;AAGnC,MAAM,8BAAqD,OAAO,OAAO;AAAA,EAC9E,KAAK;AAAA,EACL,MAAM;AAAA,EACN,SAAS;AAAA,EACT,MAAM;AACR,CAAC;AAGM,SAAS,wBAAwB;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AACF,GAI0B;AACxB,SAAO;AAAA,IACL,KAAK,GAAG,uBAAuB,GAAG,OAAO;AAAA,IACzC,MAAM,QAAQ;AAAA,IACd;AAAA,IACA,MAAM,QAAQ;AAAA,EAAA;AAElB;AAOO,SAAS,4BAA4B;AAAA,EAC1C;AAAA,EACA;AACF,GAG4B;AAC1B,MAAI,MAAM,UAAU,4BAA6B,QAAO,CAAA;AACxD,QAAM,QAAQ,IAAI,IAAI,MAAM,IAAI,CAAC,UAAU,MAAM,GAAG,CAAC;AACrD,QAAM,UAAmC,CAAA;AACzC,aAAW,SAAS,CAAC,6BAA6B,GAAG,YAAY,GAAG;AAClE,QAAI,MAAM,IAAI,MAAM,GAAG,EAAG;AAC1B,UAAM,IAAI,MAAM,GAAG;AACnB,YAAQ,KAAK,KAAK;AAAA,EACpB;AACA,SAAO;AACT;AAGO,SAAS,wBAAwB,SAAoC;AAC1E,QAAM,QAAQ,IAAI,KAAK,WAAW,MAAM,EAAE,OAAO,QAAQ,MAAM,cAAA,CAAe,EAAE,OAAO,OAAO;AAC9F,SAAO,2BAA2B,2BAA2B,eAAe,KAAK,IAC/E,QAAQ,WAAW,IAAI,WAAW,SACpC;AACF;AAOO,SAAS,6BAA6B;AAAA,EAC3C;AAAA,EACA;AACF,GAGa;AACX,QAAM,UAAoB,CAAA;AAC1B,aAAW,SAAS,QAAQ;AAC1B,UAAM,QAAQ,yBAAyB,QAAQ;AAC/C,QAAI,MAAM,KAAK,CAAC,UAAU,MAAM,QAAQ,MAAM,IAAI,KAAA,CAAM,EAAG;AAC3D,QAAI,MAAM,UAAU,6BAA6B;AAC/C,cAAQ,KAAK,MAAM,IAAI;AACvB;AAAA,IACF;AACA,2BAAuB;AAAA,MACrB;AAAA,MACA,OAAO,EAAE,KAAK,MAAM,KAAK,MAAM,MAAM,MAAM,SAAS,MAAM,QAAA;AAAA,IAAQ,CACnE;AAAA,EACH;AACA,SAAO;AACT;AAKA,IAAI,sBAAqC;AAGlC,SAAS,gCAAsC;AACpD,gBAAc,MAAA;AACd,sBAAoB,MAAA;AACpB,qBAAmB,MAAA;AACnB,kBAAgB,MAAA;AAChB,wBAAsB;AACtB,4BAA0B,SAAS,OAAO,EAAE,UAAU,CAAA,IAAK;AAC7D;AAQO,SAAS,oCAAoC,UAAwB;AAC1E,MAAI,wBAAwB,QAAQ,wBAAwB,UAAU;AACpE,kCAAA;AAAA,EACF;AACA,wBAAsB;AACxB;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"offline-status.cjs","sources":["../../../../agent-runtime/src/offline-status.ts"],"sourcesContent":["/**\n * Athena's offline language: the one set of states and words every app uses to\n * say where the person stands when the network, or Athena, is out of reach —\n * Olympus, the desktop app, the phone app, the Chrome extension and the Office\n * add-in.\n *\n * The rule the words follow: say what still works before what doesn't. Work\n * done while Athena can't be reached is kept on the device and syncs when\n * Athena is back, so every message leads with that promise. Nothing here is\n * shown while Athena answers and nothing waits; the \"back\" messages are brief.\n *\n * Pure strings and small functions, no UI library: each app draws them its own\n * way (a banner, a header chip, a tooltip, a sheet). Reachability itself is\n * each app's own (the browser's or OS's online flag AND agora answering its\n * health read); this module only names the result.\n */\n\n/** Where the app stands with Athena. */\nexport type ConnectionState =\n /** Athena answers. Nothing is shown. */\n | 'online'\n /** The device has no network. */\n | 'offline'\n /** The network is up but Athena doesn't answer. */\n | 'unreachable'\n /** Athena answers again and what waited is being sent. */\n | 'reconnecting'\n /** Just back, and everything that waited was sent. Shown briefly. */\n | 'synced';\n\n/** Where one document's edits stand, for the chip in its header. */\nexport type DocumentSyncState =\n /** In Athena. */\n | 'saved'\n /** Being sent to Athena. */\n | 'saving'\n /** Kept on this device while Athena can't be reached; syncs when it is back. */\n | 'on-device'\n /** Kept only while this tab or app stays open (no device storage); syncs when Athena is back. */\n | 'in-memory'\n /** Sending what was kept on this device. */\n | 'syncing'\n /** Some changes overlap with Athena's version: the person chooses. */\n | 'needs-review'\n /** The document can no longer take these edits (access or state changed): kept, not sent. */\n | 'view-only'\n /**\n * Athena answers but isn't taking this document's changes for now: it holds the document while it\n * repairs it, or hasn't confirmed the latest changes for longer than usual (`SavingDelayCause`\n * says which). Kept, and saved once Athena takes them. Never said while Athena can't be reached:\n * that is `on-device` or `in-memory`.\n */\n | 'delayed';\n\n/** Why a document's saving is delayed while Athena answers (`DocumentSyncState` `delayed`). */\nexport type SavingDelayCause =\n /** Athena holds the document while it repairs it, and takes no changes to it until then. */\n | 'repairing'\n /** Athena hasn't confirmed the latest changes for longer than usual. */\n | 'unconfirmed';\n\n/** How a sentence names the device the person is on. */\nexport type DeviceNoun =\n | 'this browser'\n | 'this Mac'\n | 'this computer'\n | 'this phone'\n | 'this tablet'\n | 'this device';\n\n/**\n * What the app really keeps of work done while Athena can't be reached, so the\n * words never promise more: `device` (stored on the device, survives closing),\n * `memory` (kept only while this tab or app stays open: a tenant that turns\n * device copies off, or storage the app can't open), `none` (a surface that\n * keeps no work offline at all, like the Chrome side panel).\n */\nexport type OfflineKeeping = 'device' | 'memory' | 'none';\n\n/** A title and the one line under it (a banner, a sheet, a tooltip's heading). */\nexport interface StatusCopy {\n title: string;\n detail: string;\n}\n\n/** A short label for a chip or a disabled control, and its one-line explanation. */\nexport interface LabelCopy {\n label: string;\n detail: string;\n}\n\nfunction plural(count: number, one: string, many: string): string {\n return `${count} ${count === 1 ? one : many}`;\n}\n\n/** What a tab or an app is called when work lasts only while it stays open. */\nfunction openContainer(device: DeviceNoun): string {\n return device === 'this browser' ? 'this tab' : 'the app';\n}\n\n/** The device noun at the start of a sentence (\"This browser can…\"). */\nfunction deviceAtStart(device: DeviceNoun): string {\n return `${device.charAt(0).toUpperCase()}${device.slice(1)}`;\n}\n\n/**\n * The sentence a promise ends with when the device can remove what it keeps before it syncs\n * (`evictable`: a browser that hasn't granted persistent storage, a private window): \"before then\"\n * after a sentence that says when it syncs, \"before it syncs\" after one that doesn't.\n */\nfunction removableBeforeSync({\n device,\n count,\n before = 'then',\n}: {\n device: DeviceNoun;\n count: number;\n before?: 'then' | 'syncing';\n}): string {\n const what = count === 1 ? 'it' : 'them';\n const when = before === 'then' ? 'then' : count === 1 ? 'it syncs' : 'they sync';\n return `${deviceAtStart(device)} can remove ${what} before ${when}.`;\n}\n\n/** The promise after \"You're offline\" / \"Can't reach Athena\", honest to what is kept. */\nfunction keepingPromise({\n keeping,\n device,\n when,\n evictable,\n}: {\n keeping: OfflineKeeping;\n device: DeviceNoun;\n when: string;\n evictable: boolean;\n}): string {\n switch (keeping) {\n case 'device':\n return evictable\n ? `You can keep working. Changes are kept on ${device} and sync ${when}. ${removableBeforeSync({ device, count: 2 })}`\n : `You can keep working. Changes are saved on ${device} and sync ${when}.`;\n case 'memory':\n return `You can keep working, but changes are kept only until you close ${openContainer(device)}. They sync ${when}.`;\n case 'none':\n return `You’re still signed in. This reconnects ${when}.`;\n }\n}\n\n/**\n * The app-wide status line, or `null` while Athena answers and nothing waits.\n * `waiting` counts changes not in Athena yet: while `reconnecting` they are\n * being sent; while `online` they wait for something else (a copy that sends\n * when it is next opened), and the line stays until they are gone.\n * `keeping` is what the app really keeps offline (default `device`). A surface\n * that keeps nothing (`none`) has nothing to sync, so its way back is only\n * \"Back online\", never \"Syncing…\" or \"All changes synced\".\n * `evictable`: the device may remove what it keeps before it syncs (a browser that hasn't granted\n * persistent storage, a private window); only `keeping` `device` says so (default `false`).\n */\nexport function connectionCopy({\n state,\n device,\n waiting = 0,\n keeping = 'device',\n evictable = false,\n}: {\n state: ConnectionState;\n device: DeviceNoun;\n waiting?: number;\n keeping?: OfflineKeeping;\n evictable?: boolean;\n}): StatusCopy | null {\n const atRisk = evictable && keeping === 'device';\n switch (state) {\n case 'online':\n return waiting > 0\n ? {\n title: 'Not synced yet',\n detail: `${plural(waiting, 'change', 'changes')} on ${device} ${waiting === 1 ? 'hasn’t' : 'haven’t'} synced yet.${\n atRisk ? ` ${removableBeforeSync({ device, count: waiting, before: 'syncing' })}` : ''\n }`,\n }\n : null;\n case 'offline':\n return {\n title: 'You’re offline',\n detail: keepingPromise({\n keeping,\n device,\n when: 'when you’re back online',\n evictable: atRisk,\n }),\n };\n case 'unreachable':\n return {\n title: 'Can’t reach Athena',\n detail: keepingPromise({ keeping, device, when: 'when Athena is back', evictable: atRisk }),\n };\n case 'reconnecting':\n if (keeping === 'none') return { title: 'Back online', detail: '' };\n return {\n title: 'Back online',\n detail:\n waiting > 0 ? `Syncing ${plural(waiting, 'change', 'changes')}…` : 'Syncing…',\n };\n case 'synced':\n return keeping === 'none'\n ? { title: 'Back online', detail: '' }\n : { title: 'All changes synced', detail: '' };\n }\n}\n\n/**\n * The line under \"Saving delayed\": why saving waits, and what is kept meanwhile, never promising\n * more than the app keeps.\n */\nfunction savingDelayedDetail({\n delay,\n keeping,\n device,\n}: {\n delay: SavingDelayCause;\n keeping: Exclude<OfflineKeeping, 'none'>;\n device: DeviceNoun;\n}): string {\n if (delay === 'repairing') {\n return keeping === 'memory'\n ? `You can keep working, but your changes are kept only until you close ${openContainer(device)}. They save once Athena finishes repairing this document.`\n : `You can keep working. Your changes are kept on ${device} and save once Athena finishes repairing this document.`;\n }\n return keeping === 'memory'\n ? `Athena is taking longer than usual to save your latest changes. They’re kept only until you close ${openContainer(device)}, so keep it open.`\n : `Athena is taking longer than usual to save your latest changes. They’re kept on ${device} in the meantime.`;\n}\n\n/**\n * What `on-device` says. The desktop app on a Mac speaks as Word, Excel and PowerPoint for Mac do\n * of a cloud document whose changes wait on the Mac (Office's own title-bar words): \"Upload\n * Pending\", and \"Upload Pending (Offline)\" while Athena can't be reached. Every other app says the\n * changes are saved on its device: a browser has no such words (Word for the web can't edit\n * offline), nor does the phone.\n */\nfunction onDeviceCopy({ device, reachable }: { device: DeviceNoun; reachable: boolean }): LabelCopy {\n if (device === 'this Mac') {\n return {\n label: reachable ? 'Upload Pending' : 'Upload Pending (Offline)',\n detail: 'Upload pending. Your changes sync when Athena is back.',\n };\n }\n return {\n label: `Saved on ${device}`,\n detail: `Saved on ${device}. Your changes sync when Athena is back.`,\n };\n}\n\n/**\n * The chip in a document's header, and the line it explains itself with. For `delayed`, `delay`\n * says why (default `unconfirmed`) and `keeping` whether the changes are kept on the device or only\n * while the tab or app stays open (default `device`); every other state ignores both. `reachable`\n * (default `true`) is whether Athena can be reached, which only the Mac's `on-device` words read.\n * For `on-device`, `evictable` says the device may remove the changes before they sync (default\n * `false`).\n */\nexport function documentSyncCopy({\n state,\n device,\n delay = 'unconfirmed',\n keeping = 'device',\n reachable = true,\n evictable = false,\n}: {\n state: DocumentSyncState;\n device: DeviceNoun;\n delay?: SavingDelayCause;\n keeping?: Exclude<OfflineKeeping, 'none'>;\n reachable?: boolean;\n evictable?: boolean;\n}): LabelCopy {\n switch (state) {\n case 'saved':\n return { label: 'Saved', detail: 'Saved to Athena.' };\n case 'saving':\n return { label: 'Saving…', detail: 'Saving to Athena.' };\n case 'on-device': {\n const copy = onDeviceCopy({ device, reachable });\n return evictable\n ? { ...copy, detail: `${copy.detail} ${removableBeforeSync({ device, count: 2 })}` }\n : copy;\n }\n case 'in-memory':\n return {\n label: 'Not saved yet',\n detail: `Your changes are kept only until you close ${openContainer(device)}, and save when Athena is back.`,\n };\n case 'syncing':\n return { label: 'Syncing…', detail: `Sending the changes saved on ${device}.` };\n case 'needs-review':\n return {\n label: 'Review changes',\n detail: 'Some of your changes overlap with changes made in Athena. Choose what to keep.',\n };\n case 'view-only':\n return {\n label: 'View only',\n detail: `You can’t edit this anymore. Your changes stay on ${device}.`,\n };\n case 'delayed':\n return { label: 'Saving delayed', detail: savingDelayedDetail({ delay, keeping, device }) };\n }\n}\n\n/**\n * How long a document's edits may wait unconfirmed on a connection that is up before its saving\n * reads as delayed (`delayed`, `unconfirmed`), and before its room asks Keryx why: the stall window\n * every editor shares (`ACK_STALL_MS` in `@athenaintel/asset-host/local-updates`, which Olympus's\n * `room-sync-store.test.ts` holds equal).\n */\nexport const UNCONFIRMED_EDITS_STALL_MS = 15_000;\n\n/**\n * Whether a document's saving is delayed, and why (`DocumentSyncState` `delayed`): only while Athena\n * answers and the document's room is connected; `repairing` when Keryx refuses the room's writes\n * (quarantined while it is repaired: said at once, before anything waits), `unconfirmed` once its\n * edits have stayed unconfirmed past {@link UNCONFIRMED_EDITS_STALL_MS}; `null` otherwise. Every\n * app's chip asks it after a hold and after edits kept without a connection, and ahead of syncing\n * and saving, so a room that refuses writes never spins and being offline is never a delay.\n */\nexport function savingDelayCause({\n reachable,\n connected,\n writesRefused,\n unconfirmedStalled,\n}: {\n /** Athena answers (the app's reachability, never the socket alone). */\n reachable: boolean;\n /** The document's room is connected. */\n connected: boolean;\n /** Keryx's document status says the room takes no writes for now. */\n writesRefused: boolean;\n /** Local edits have waited unconfirmed past the stall window on this connection. */\n unconfirmedStalled: boolean;\n}): SavingDelayCause | null {\n if (!reachable || !connected) return null;\n if (writesRefused) return 'repairing';\n return unconfirmedStalled ? 'unconfirmed' : null;\n}\n\n/**\n * What the person lost of a document while it was open, when the server checked its room's grant\n * again (Keryx's 4401, after a share changed): `edit`, they may still view it but no longer edit it;\n * `view`, they may no longer open it at all.\n */\nexport type AccessLoss = 'edit' | 'view';\n\n/** What a document says once the person's access changed while it was open. */\nexport interface AccessChangedCopy extends StatusCopy {\n /**\n * The label of the button that saves the person's version as a file of their own, with the\n * changes Athena never took, or `null` when nothing is offered: nothing of theirs waits, or the\n * device no longer serves the document (`view`).\n */\n saveCopy: string | null;\n}\n\n/**\n * What a document says once the person's access to it changed while it was open (its editor turns\n * read-only at once), in Word's own words (Word for Mac's message bar, `strman_a6d4`, and its\n * \"Permissions Have Changed\" notice, `strman_0a3e`). `keptChanges`: changes Athena never took wait\n * on the device, never sent; Word offers to save a copy of the file so nothing typed is lost. A\n * `view` loss offers nothing to save: the device stops serving a document the person may no longer\n * read, and their changes stay where they are kept.\n */\nexport function accessChangedCopy({\n loss,\n keptChanges,\n}: {\n loss: AccessLoss;\n keptChanges: boolean;\n}): AccessChangedCopy {\n if (loss === 'view') {\n return {\n title: 'Permissions Have Changed',\n detail:\n 'The permissions on this file were updated and you no longer have rights to view this file. If you previously made changes to this file, they may not be saved.',\n saveCopy: null,\n };\n }\n if (keptChanges) {\n return {\n title: 'Can’t save',\n detail:\n 'You no longer have the permission to edit this file. To keep your changes, save a copy of the file.',\n saveCopy: 'Save a Copy',\n };\n }\n return {\n title: 'Read Only',\n detail: 'You no longer have the permission to edit this file.',\n saveCopy: null,\n };\n}\n\n/** What a document says while it holds changes an older version of Athena made on the device. */\nexport interface OlderVersionChangesCopy extends StatusCopy {\n /** Saves this device's version as a file of the person's own, those changes included (Word's). */\n saveCopy: string;\n /** Sets this device's version aside, kept on the device to compare, and opens Athena's. */\n useAthenaVersion: string;\n /** Athena's version couldn't be opened: another window of the device has the document open. */\n openElsewhere: string;\n}\n\n/**\n * What a document says while its local copy holds changes an older version of Athena made on this\n * device, below its room's write floor (`older-version`, `@athenaintel/local-copy/room-copy`): such\n * a version deletes what newer ones store, so those changes are never uploaded. Word's way out,\n * as when it can't save a cloud document (\"You can save a copy to prevent losing your work\",\n * `strman`): Save a Copy, and Athena's version, which keeps this device's version on it to compare\n * and copy from until the person discards it. `saveCopy: false` for an editor that offers no Save\n * a Copy of the live document (the phone's page): its kept version downloads instead.\n */\nexport function olderVersionChangesCopy({\n device,\n noun,\n saveCopy = true,\n}: {\n device: DeviceNoun;\n /** What the person calls the document (\"document\", \"spreadsheet\"). */\n noun: string;\n /** Whether the editor offers Save a Copy beside Athena's version. */\n saveCopy?: boolean;\n}): OlderVersionChangesCopy {\n const made = `You changed this ${noun} on ${device} in an older version of Athena, so those changes can’t be uploaded.`;\n return {\n title: 'Changes made in an older version of Athena',\n detail: saveCopy\n ? `${made} To keep them, save a copy, or use Athena’s version: yours stays on ${device} to compare and copy from.`\n : `${made} Use Athena’s version to keep yours on ${device}, where you can compare it, copy from it or download it.`,\n saveCopy: 'Save a Copy',\n useAthenaVersion: 'Use Athena’s version',\n openElsewhere: `This ${noun} is open in another window. Close it there, then try again.`,\n };\n}\n\n/** When something that needs Athena works again (the second half of `NEEDS_CONNECTION`'s line). */\nconst AVAILABLE_AGAIN = 'It’s available again when you’re back online.';\n\n/**\n * The reason on a control that needs Athena (share, run, upload, invite…),\n * shown disabled while Athena can't be reached rather than failing when used.\n */\nexport const NEEDS_CONNECTION: LabelCopy = {\n label: 'Needs a connection',\n detail: `This needs Athena. ${AVAILABLE_AGAIN}`,\n};\n\n/** What a composer was given to attach: a photo (from the phone's library or camera) or any file. */\nexport type AttachmentKind = 'photo' | 'file';\n\n/**\n * What a composer says when a photo or file is picked, pasted or dropped while\n * Athena can't be reached. It isn't attached: only Athena can take the upload.\n * In a chat whose messages wait to be sent meanwhile (`messagesWait`: the chat\n * keeps an outbox), the message itself still goes, so that comes first. Where\n * nothing waits (the Chrome side panel, a launcher that keeps its draft), it\n * says only when attaching works again, as `NEEDS_CONNECTION` does.\n */\nexport function attachmentNeedsConnection({\n kind,\n messagesWait,\n}: {\n kind: AttachmentKind;\n messagesWait: boolean;\n}): string {\n const attaching = `Attaching ${kind === 'photo' ? 'a photo' : 'a file'} needs Athena. ${AVAILABLE_AGAIN}`;\n return messagesWait\n ? `You can still send your message: it goes when Athena is back. ${attaching}`\n : attaching;\n}\n\n/** What a sent message carries besides its text that can't wait for Athena. */\nfunction heldExtras(withQuote: boolean): string {\n return withQuote ? 'an attachment or a quote' : 'an attachment';\n}\n\n/**\n * What a composer says when a message is sent while Athena can't be reached\n * with an attachment that never reached Athena (or, `withQuote`, a quote the\n * chat can't keep waiting). Its text could wait in the chat outbox; the\n * attachment can't, so the draft stays as it is.\n */\nexport function attachedMessageNeedsConnection({\n withQuote = false,\n}: {\n withQuote?: boolean;\n} = {}): string {\n return `Your text can wait and go when Athena is back, but ${heldExtras(withQuote)} can’t. Remove ${\n withQuote ? 'it' : 'the attachment'\n } to send the text.`;\n}\n\n/**\n * What a composer says when a message with an attachment (or, `withQuote`, a\n * quote) is sent while messages written when Athena couldn't be reached still\n * wait to go: those go first, and this one can't wait behind them.\n */\nexport function attachedMessageBehindWaiting({\n withQuote = false,\n}: {\n withQuote?: boolean;\n} = {}): string {\n return `Messages you wrote while Athena couldn’t be reached go first. A message with ${heldExtras(\n withQuote\n )} can’t wait behind them, so send it once they’ve gone.`;\n}\n\n/**\n * The reason on New Presentation while Athena can't be reached, in a workspace\n * whose new presentations start from its design system's template: a\n * presentation made offline starts blank, and only Athena can copy the\n * template, so none is made until it can.\n */\nexport const NEW_PRESENTATION_NEEDS_TEMPLATE: LabelCopy = {\n label: 'Needs a connection',\n detail:\n 'New presentations in this workspace start from its design template, which needs Athena. You can make one when you’re back online.',\n};\n\n/**\n * What a download of a spreadsheet made from an Excel Macro-Enabled Workbook\n * (`.xlsm`) says when it went without the macros because they come from Athena,\n * which can't be reached, and the device hasn't kept them (they travel with the\n * workbook and never run). The file is the workbook without them; downloading\n * it again with a connection keeps them.\n */\nexport function downloadedWithoutMacros({ device }: { device: DeviceNoun }): string {\n return `Downloaded without the spreadsheet’s macros: they come from Athena, which can’t be reached, and ${device} hasn’t kept them. Download it again when you’re back online to keep them.`;\n}\n\n/**\n * Save's question for a spreadsheet whose file is an Excel Macro-Enabled\n * Workbook (`.xlsm`) while its macros come from Athena, which can't be reached,\n * and the device hasn't kept them: the `.xlsm` is never written without them,\n * so the person may save an Excel Workbook (`.xlsx`) beside it, and Save writes\n * the `.xlsm` again once Athena answers.\n */\nexport function macrosNeedConnectionToSave({\n name,\n device,\n}: {\n name: string;\n device: DeviceNoun;\n}): StatusCopy {\n return {\n title: `Athena can’t save the macros in “${name}” right now.`,\n detail: `They come from Athena, which can’t be reached, and ${device} hasn’t kept them. Save it as an Excel Workbook (.xlsx) instead. “${name}” stays as it is, macros included, and Save writes it again when you’re back online.`,\n };\n}\n\n/**\n * What saving a version kept on the device as a new spreadsheet says when the\n * spreadsheet was made from an Excel Macro-Enabled Workbook (`.xlsm`) and\n * Athena can't be reached: the new spreadsheet is made all the same (on the\n * device, and it syncs when Athena is back), but without the macros, which only\n * Athena can keep with a new spreadsheet (they travel with the workbook and\n * never run). The kept version stays on the device, so saving it again with a\n * connection keeps them.\n */\nexport function savedAsNewWithoutMacros({ device }: { device: DeviceNoun }): string {\n return `The new spreadsheet was made without the macros: only Athena can keep them in a new spreadsheet, and it can’t be reached. The kept version stays on ${device}: save it as a new spreadsheet again when you’re back online to keep them.`;\n}\n\n/**\n * What saving a copy of a Word document says when the copy was made on the\n * device while Athena can't be reached, for a document whose original Word file\n * Athena keeps (one imported from Word): the copy is made all the same, from the\n * document as the device holds it, over the original file kept with it, so it\n * keeps that file's parts but writes its body from what the editor shows.\n * Athena's own copy, made from the original file, keeps everything, so saving\n * a copy again with a connection makes that one.\n */\nexport function wordCopyMadeOnDevice({ device }: { device: DeviceNoun }): StatusCopy {\n return {\n title: `Copy made on ${device}`,\n detail: `Athena can’t be reached, so the copy holds the document as it is on ${device}. Anything in the original Word file that Athena doesn’t show may be missing from it: save a copy again when you’re back online for the complete file.`,\n };\n}\n\n/**\n * Whether an item opens without a connection on this device, for lists.\n * `canKeep` says whether opening it online would keep a copy here (the\n * deployment allows device copies and the item's type is one that is kept):\n * only then is the person told to open it once.\n */\nexport function offlineAvailabilityCopy({\n available,\n canKeep,\n device,\n}: {\n available: boolean;\n canKeep: boolean;\n device: DeviceNoun;\n}): LabelCopy {\n if (available) {\n return { label: 'Available offline', detail: `Opens without a connection on ${device}.` };\n }\n return canKeep\n ? {\n label: 'Not available offline',\n detail: `Open it once while online to keep it on ${device}.`,\n }\n : { label: 'Not available offline', detail: 'This opens only with a connection.' };\n}\n\n/**\n * The one-time explainer shown the first time the person goes offline, on a\n * surface that keeps work there (`keeping` `device`). A surface that keeps\n * nothing (`none`: the Chrome side panel, the Office task pane) shows no\n * explainer; its status line already says all that holds.\n */\nexport function firstOfflineExplainer({ device }: { device: DeviceNoun }): StatusCopy & {\n action: string;\n} {\n return {\n title: 'You can keep working offline',\n detail: `Documents you’ve opened recently keep working on ${device}. Your changes sync when you’re back online.`,\n action: 'Got it',\n };\n}\n\n/**\n * How a document's changes could be lost before they reach Athena:\n *\n * - `device`: saved on the device until they reach Athena (no connection, or a review the person\n * has not finished), but the device can remove them before then (a browser that hasn't granted\n * persistent storage, a private window);\n * - `held`: saved on the device and can't be sent (the person can only view the document now, or\n * Athena refused it), and the device can remove them;\n * - `memory`: kept only until the tab or app closes (the device keeps no copy).\n */\nexport type ChangesAtRisk = 'device' | 'held' | 'memory';\n\n/**\n * What an editor says above a document whose changes could be lost before they reach Athena, with\n * the copy it offers of them (Word's \"Upload pending\" and \"Changes not saved\"), by\n * {@link ChangesAtRisk}.\n */\nexport function changesAtRiskCopy({\n risk,\n device,\n}: {\n risk: ChangesAtRisk;\n device: DeviceNoun;\n}): StatusCopy & { download: string; downloadFailed: string } {\n const actions = {\n download: 'Download a copy',\n downloadFailed: 'Couldn’t download a copy. Try again.',\n };\n switch (risk) {\n case 'memory':\n return {\n title: 'Changes not saved',\n detail: `Your changes are kept only until you close ${openContainer(device)}. Download a copy to keep them.`,\n ...actions,\n };\n case 'held':\n return {\n title: 'Changes not saved',\n detail: `Your changes can’t be sent, and they’re saved only on ${device}, which can remove them. Download a copy to keep them.`,\n ...actions,\n };\n case 'device':\n return {\n title: 'Upload pending',\n detail: `Your changes are saved only on ${device} until they reach Athena, and ${device} can remove them before then. Download a copy to keep them.`,\n ...actions,\n };\n }\n}\n\n/**\n * The action that asks the device to keep what it holds until it syncs, where asking shows the\n * person a question of the device's own (Firefox asks whether the site may store data in\n * persistent storage): the app says why first (`changesAtRiskCopy`) and asks only on this press.\n */\nexport function keepOnDeviceAction({ device }: { device: DeviceNoun }): string {\n return `Keep them on ${device}`;\n}\n\n/** A browser whose own way of keeping a site's data longer the words point to. */\nexport type SaferStorageBrowser = 'safari-mac' | 'safari-ios';\n\n/**\n * Where changes made offline in Safari are kept longer: Safari keeps a site added to the Dock or\n * the Home Screen as an app of its own, which it is likelier to let keep its data, and the desktop\n * app keeps them in storage of its own.\n */\nexport function saferStorageHint({ browser }: { browser: SaferStorageBrowser }): string {\n return browser === 'safari-mac'\n ? 'To keep changes made offline safer in Safari, add Athena to the Dock (File ▸ Add to Dock), or use Athena Desktop.'\n : 'To keep changes made offline safer, add Athena to your Home Screen (Share ▸ Add to Home Screen).';\n}\n\n/**\n * What the app says when it finds that changes it kept on the device never reached Athena and the\n * device no longer has them (the browser removed them before they synced), naming how many\n * documents; each document's row says when its changes were made (`lostChangesItemCopy`).\n */\nexport function lostChangesCopy({\n device,\n documents,\n}: {\n device: DeviceNoun;\n documents: number;\n}): StatusCopy & { why: string; open: string; dismiss: string } {\n const which = documents === 1 ? 'a document' : plural(documents, 'document', 'documents');\n return {\n title: 'Changes not saved',\n detail: `Changes you made to ${which} on ${device} never reached Athena, and ${device} no longer has them.`,\n why: 'Browsers can remove what a site keeps when they run short of space, or when the site hasn’t been opened for a while.',\n open: 'Open',\n dismiss: 'Dismiss',\n };\n}\n\n/** One document's row under `lostChangesCopy`: the words before when its changes were made. */\nexport function lostChangesItemCopy({ device }: { device: DeviceNoun }): string {\n return `Changed on ${device}`;\n}\n\n/**\n * The summary heading of the one \"Waiting to sync\" list, from what waits on\n * the device; `null` when nothing does.\n */\nexport function waitingSummary({\n changes = 0,\n messages = 0,\n recordings = 0,\n}: {\n changes?: number;\n messages?: number;\n recordings?: number;\n}): string | null {\n const parts = [\n changes > 0 ? plural(changes, 'change', 'changes') : null,\n messages > 0 ? plural(messages, 'message', 'messages') : null,\n recordings > 0 ? plural(recordings, 'recording', 'recordings') : null,\n ].filter((part): part is string => part !== null);\n return parts.length === 0 ? null : `Waiting to sync: ${parts.join(', ')}`;\n}\n\n/**\n * Where one item in the \"Waiting to sync\" list stands: a change, a message or a\n * recording made while Athena couldn't be reached.\n */\nexport type WaitingItemState =\n /** Saved on the device; it syncs when Athena is back. */\n | 'waiting'\n /** Being sent to Athena now. */\n | 'syncing'\n /**\n * Kept only while this tab or app stays open: it couldn't be saved on the\n * device (the organization keeps nothing on devices, or storage failed).\n */\n | 'in-memory'\n /**\n * Saved on the device in something that isn't open (a document closed before\n * its edits synced, one made offline): it syncs when it is next opened with a\n * connection (opening it offline sends nothing).\n */\n | 'when-opened'\n /** Made in another workspace: it syncs once that workspace is open again, with a connection. */\n | 'other-workspace'\n /** It doesn't go on its own: the person chooses (a message that waited more than a day). */\n | 'needs-you'\n /** Athena didn't take it: the app adds why, and what the person can do about it. */\n | 'not-synced';\n\n/**\n * The state of one item in the \"Waiting to sync\" list, and the line that explains it. For an item\n * saved on the device (`waiting`, `when-opened`), `evictable` says the device may remove it before\n * it syncs (default `false`).\n */\nexport function waitingItemCopy({\n state,\n device,\n evictable = false,\n}: {\n state: WaitingItemState;\n device: DeviceNoun;\n evictable?: boolean;\n}): LabelCopy {\n const removable = evictable ? ` ${removableBeforeSync({ device, count: 1 })}` : '';\n switch (state) {\n case 'waiting':\n return {\n label: 'Waiting to sync',\n detail: `Saved on ${device}. It syncs when Athena is back.${removable}`,\n };\n case 'syncing':\n return { label: 'Syncing…', detail: `Sending what was saved on ${device}.` };\n case 'in-memory':\n return {\n label: 'Not saved yet',\n detail: `Kept only until you close ${openContainer(device)}. It syncs when Athena is back.`,\n };\n case 'when-opened':\n return {\n label: 'Not synced yet',\n detail: `Saved on ${device}. It syncs when you next open it with a connection.${removable}`,\n };\n case 'other-workspace':\n return {\n label: 'Waiting for its workspace',\n detail: 'It syncs once you’re in the workspace it was made in, with a connection.',\n };\n case 'needs-you':\n return { label: 'Waiting for you', detail: 'Open it to choose what happens to it.' };\n case 'not-synced':\n return { label: 'Couldn’t sync', detail: 'Athena didn’t take it.' };\n }\n}\n\n/** The headings of the \"Waiting to sync\" list, one per kind of item. */\nexport const WAITING_SECTION_TITLES = {\n changes: 'Changes',\n messages: 'Messages',\n recordings: 'Recordings',\n} as const;\n\n/**\n * What the person can do with an item Athena didn't take (`not-synced`) in the\n * \"Waiting to sync\" list: send it again, or delete the copy on the device. That\n * copy is the item's only one, so the app asks first (`deleteFromDeviceConfirm`)\n * and never deletes it as a side effect of anything else.\n */\nexport function notSyncedActions({ device }: { device: DeviceNoun }): {\n retry: string;\n remove: string;\n} {\n return { retry: 'Try again', remove: `Delete from ${device}` };\n}\n\n/** One of `notSyncedActions`, or showing where the item is kept on the device. */\nexport type NotSyncedAction = 'retry' | 'reveal' | 'remove';\n\n/**\n * What the person hears when the device couldn't do what they asked for an\n * item Athena didn't take (its files, not Athena, failed).\n */\nexport function notSyncedActionFailed({\n action,\n device,\n}: {\n action: NotSyncedAction;\n device: DeviceNoun;\n}): string {\n switch (action) {\n case 'retry':\n return 'Couldn’t send it again. Try again in a moment.';\n case 'reveal':\n return `Couldn’t show where it’s kept on ${device}.`;\n case 'remove':\n return `Couldn’t delete it from ${device}.`;\n }\n}\n\n/**\n * The question before deleting such an item's copy on the device, naming the\n * item: the destructive choice is never the default.\n */\nexport function deleteFromDeviceConfirm({\n name,\n device,\n}: {\n name: string;\n device: DeviceNoun;\n}): StatusCopy & { confirm: string; cancel: string } {\n return {\n title: `Delete “${name}” from ${device}?`,\n detail: 'Athena didn’t take it, so this is its only copy. Deleting it can’t be undone.',\n confirm: 'Delete',\n cancel: 'Cancel',\n };\n}\n"],"names":[],"mappings":";;AA6TO,MAAM,6BAA6B;AAgI1C,MAAM,kBAAkB;AAMjB,MAAM,mBAA8B;AAAA,EACzC,OAAO;AAAA,EACP,QAAQ,sBAAsB,eAAe;AAC/C;AAaO,SAAS,0BAA0B;AAAA,EACxC;AAAA,EACA;AACF,GAGW;AACT,QAAM,YAAY,aAA4C,QAAQ,kBAAkB,eAAe;AACvG,SAAO,eACH,iEAAiE,SAAS,KAC1E;AACN;AAGA,SAAS,WAAW,WAA4B;AAC9C,SAAO,YAAY,6BAA6B;AAClD;AAQO,SAAS,+BAA+B;AAAA,EAC7C,YAAY;AACd,IAEI,IAAY;AACd,SAAO,sDAAsD,WAAW,SAAS,CAAC,kBAChF,YAAY,OAAO,gBACrB;AACF;AAOO,SAAS,6BAA6B;AAAA,EAC3C,YAAY;AACd,IAEI,IAAY;AACd,SAAO,gFAAgF;AAAA,IACrF;AAAA,EAAA,CACD;AACH;;;;;;"}
|
|
1
|
+
{"version":3,"file":"offline-status.cjs","sources":["../../../../agent-runtime/src/offline-status.ts"],"sourcesContent":["/**\n * Athena's offline language: the one set of states and words every app uses to\n * say where the person stands when the network, or Athena, is out of reach —\n * Olympus, the desktop app, the phone app, the Chrome extension and the Office\n * add-in.\n *\n * The rule the words follow: say what still works before what doesn't. Work\n * done while Athena can't be reached is kept on the device and syncs when\n * Athena is back, so every message leads with that promise. Nothing here is\n * shown while Athena answers and nothing waits; the \"back\" messages are brief.\n *\n * Pure strings and small functions, no UI library: each app draws them its own\n * way (a banner, a header chip, a tooltip, a sheet). Reachability itself is\n * each app's own (the browser's or OS's online flag AND agora answering its\n * health read); this module only names the result.\n */\n\n/** Where the app stands with Athena. */\nexport type ConnectionState =\n /** Athena answers. Nothing is shown. */\n | 'online'\n /** The device has no network. */\n | 'offline'\n /** The network is up but Athena doesn't answer. */\n | 'unreachable'\n /** Athena answers again and what waited is being sent. */\n | 'reconnecting'\n /** Just back, and everything that waited was sent. Shown briefly. */\n | 'synced';\n\n/** Where one document's edits stand, for the chip in its header. */\nexport type DocumentSyncState =\n /** In Athena. */\n | 'saved'\n /** Being sent to Athena. */\n | 'saving'\n /** Kept on this device while Athena can't be reached; syncs when it is back. */\n | 'on-device'\n /** Kept only while this tab or app stays open (no device storage); syncs when Athena is back. */\n | 'in-memory'\n /** Sending what was kept on this device. */\n | 'syncing'\n /** Some changes overlap with Athena's version: the person chooses. */\n | 'needs-review'\n /** The document can no longer take these edits (access or state changed): kept, not sent. */\n | 'view-only'\n /**\n * Athena answers but isn't taking this document's changes for now: it holds the document while it\n * repairs it, or hasn't confirmed the latest changes for longer than usual (`SavingDelayCause`\n * says which). Kept, and saved once Athena takes them. Never said while Athena can't be reached:\n * that is `on-device` or `in-memory`.\n */\n | 'delayed';\n\n/** Why a document's saving is delayed while Athena answers (`DocumentSyncState` `delayed`). */\nexport type SavingDelayCause =\n /** Athena holds the document while it repairs it, and takes no changes to it until then. */\n | 'repairing'\n /** Athena hasn't confirmed the latest changes for longer than usual. */\n | 'unconfirmed';\n\n/** How a sentence names the device the person is on. */\nexport type DeviceNoun =\n | 'this browser'\n | 'this Mac'\n | 'this computer'\n | 'this phone'\n | 'this tablet'\n | 'this device';\n\n/**\n * What the app really keeps of work done while Athena can't be reached, so the\n * words never promise more: `device` (stored on the device, survives closing),\n * `memory` (kept only while this tab or app stays open: a tenant that turns\n * device copies off, or storage the app can't open), `none` (a surface that\n * keeps no work offline at all, like the Chrome side panel).\n */\nexport type OfflineKeeping = 'device' | 'memory' | 'none';\n\n/** A title and the one line under it (a banner, a sheet, a tooltip's heading). */\nexport interface StatusCopy {\n title: string;\n detail: string;\n}\n\n/** A short label for a chip or a disabled control, and its one-line explanation. */\nexport interface LabelCopy {\n label: string;\n detail: string;\n}\n\nfunction plural(count: number, one: string, many: string): string {\n return `${count} ${count === 1 ? one : many}`;\n}\n\n/** What a tab or an app is called when work lasts only while it stays open. */\nfunction openContainer(device: DeviceNoun): string {\n return device === 'this browser' ? 'this tab' : 'the app';\n}\n\n/** The device noun at the start of a sentence (\"This browser can…\"). */\nfunction deviceAtStart(device: DeviceNoun): string {\n return `${device.charAt(0).toUpperCase()}${device.slice(1)}`;\n}\n\n/**\n * The sentence a promise ends with when the device can remove what it keeps before it syncs\n * (`evictable`: a browser that hasn't granted persistent storage, a private window): \"before then\"\n * after a sentence that says when it syncs, \"before it syncs\" after one that doesn't.\n */\nfunction removableBeforeSync({\n device,\n count,\n before = 'then',\n}: {\n device: DeviceNoun;\n count: number;\n before?: 'then' | 'syncing';\n}): string {\n const what = count === 1 ? 'it' : 'them';\n const when = before === 'then' ? 'then' : count === 1 ? 'it syncs' : 'they sync';\n return `${deviceAtStart(device)} can remove ${what} before ${when}.`;\n}\n\n/** The promise after \"You're offline\" / \"Can't reach Athena\", honest to what is kept. */\nfunction keepingPromise({\n keeping,\n device,\n when,\n evictable,\n}: {\n keeping: OfflineKeeping;\n device: DeviceNoun;\n when: string;\n evictable: boolean;\n}): string {\n switch (keeping) {\n case 'device':\n return evictable\n ? `You can keep working. Changes are kept on ${device} and sync ${when}. ${removableBeforeSync({ device, count: 2 })}`\n : `You can keep working. Changes are saved on ${device} and sync ${when}.`;\n case 'memory':\n return `You can keep working, but changes are kept only until you close ${openContainer(device)}. They sync ${when}.`;\n case 'none':\n return `You’re still signed in. This reconnects ${when}.`;\n }\n}\n\n/**\n * The app-wide status line, or `null` while Athena answers and nothing waits.\n * `waiting` counts changes not in Athena yet: while `reconnecting` they are\n * being sent; while `online` they wait for something else (a copy that sends\n * when it is next opened), and the line stays until they are gone.\n * `keeping` is what the app really keeps offline (default `device`). A surface\n * that keeps nothing (`none`) has nothing to sync, so its way back is only\n * \"Back online\", never \"Syncing…\" or \"All changes synced\".\n * `evictable`: the device may remove what it keeps before it syncs (a browser that hasn't granted\n * persistent storage, a private window); only `keeping` `device` says so (default `false`).\n */\nexport function connectionCopy({\n state,\n device,\n waiting = 0,\n keeping = 'device',\n evictable = false,\n}: {\n state: ConnectionState;\n device: DeviceNoun;\n waiting?: number;\n keeping?: OfflineKeeping;\n evictable?: boolean;\n}): StatusCopy | null {\n const atRisk = evictable && keeping === 'device';\n switch (state) {\n case 'online':\n return waiting > 0\n ? {\n title: 'Not synced yet',\n detail: `${plural(waiting, 'change', 'changes')} on ${device} ${waiting === 1 ? 'hasn’t' : 'haven’t'} synced yet.${\n atRisk ? ` ${removableBeforeSync({ device, count: waiting, before: 'syncing' })}` : ''\n }`,\n }\n : null;\n case 'offline':\n return {\n title: 'You’re offline',\n detail: keepingPromise({\n keeping,\n device,\n when: 'when you’re back online',\n evictable: atRisk,\n }),\n };\n case 'unreachable':\n return {\n title: 'Can’t reach Athena',\n detail: keepingPromise({ keeping, device, when: 'when Athena is back', evictable: atRisk }),\n };\n case 'reconnecting':\n if (keeping === 'none') return { title: 'Back online', detail: '' };\n return {\n title: 'Back online',\n detail:\n waiting > 0 ? `Syncing ${plural(waiting, 'change', 'changes')}…` : 'Syncing…',\n };\n case 'synced':\n return keeping === 'none'\n ? { title: 'Back online', detail: '' }\n : { title: 'All changes synced', detail: '' };\n }\n}\n\n/**\n * The line under \"Saving delayed\": why saving waits, and what is kept meanwhile, never promising\n * more than the app keeps.\n */\nfunction savingDelayedDetail({\n delay,\n keeping,\n device,\n}: {\n delay: SavingDelayCause;\n keeping: Exclude<OfflineKeeping, 'none'>;\n device: DeviceNoun;\n}): string {\n if (delay === 'repairing') {\n return keeping === 'memory'\n ? `You can keep working, but your changes are kept only until you close ${openContainer(device)}. They save once Athena finishes repairing this document.`\n : `You can keep working. Your changes are kept on ${device} and save once Athena finishes repairing this document.`;\n }\n return keeping === 'memory'\n ? `Athena is taking longer than usual to save your latest changes. They’re kept only until you close ${openContainer(device)}, so keep it open.`\n : `Athena is taking longer than usual to save your latest changes. They’re kept on ${device} in the meantime.`;\n}\n\n/**\n * What `on-device` says. The desktop app on a Mac speaks as Word, Excel and PowerPoint for Mac do\n * of a cloud document whose changes wait on the Mac (Office's own title-bar words): \"Upload\n * Pending\", and \"Upload Pending (Offline)\" while Athena can't be reached. Every other app says the\n * changes are saved on its device: a browser has no such words (Word for the web can't edit\n * offline), nor does the phone.\n */\nfunction onDeviceCopy({ device, reachable }: { device: DeviceNoun; reachable: boolean }): LabelCopy {\n if (device === 'this Mac') {\n return {\n label: reachable ? 'Upload Pending' : 'Upload Pending (Offline)',\n detail: 'Upload pending. Your changes sync when Athena is back.',\n };\n }\n return {\n label: `Saved on ${device}`,\n detail: `Saved on ${device}. Your changes sync when Athena is back.`,\n };\n}\n\n/**\n * The chip in a document's header, and the line it explains itself with. For `delayed`, `delay`\n * says why (default `unconfirmed`) and `keeping` whether the changes are kept on the device or only\n * while the tab or app stays open (default `device`); every other state ignores both. `reachable`\n * (default `true`) is whether Athena can be reached, which only the Mac's `on-device` words read.\n * For `on-device`, `evictable` says the device may remove the changes before they sync (default\n * `false`).\n */\nexport function documentSyncCopy({\n state,\n device,\n delay = 'unconfirmed',\n keeping = 'device',\n reachable = true,\n evictable = false,\n}: {\n state: DocumentSyncState;\n device: DeviceNoun;\n delay?: SavingDelayCause;\n keeping?: Exclude<OfflineKeeping, 'none'>;\n reachable?: boolean;\n evictable?: boolean;\n}): LabelCopy {\n switch (state) {\n case 'saved':\n return { label: 'Saved', detail: 'Saved to Athena.' };\n case 'saving':\n return { label: 'Saving…', detail: 'Saving to Athena.' };\n case 'on-device': {\n const copy = onDeviceCopy({ device, reachable });\n return evictable\n ? { ...copy, detail: `${copy.detail} ${removableBeforeSync({ device, count: 2 })}` }\n : copy;\n }\n case 'in-memory':\n return {\n label: 'Not saved yet',\n detail: `Your changes are kept only until you close ${openContainer(device)}, and save when Athena is back.`,\n };\n case 'syncing':\n return { label: 'Syncing…', detail: `Sending the changes saved on ${device}.` };\n case 'needs-review':\n return {\n label: 'Review changes',\n detail: 'Some of your changes overlap with changes made in Athena. Choose what to keep.',\n };\n case 'view-only':\n return {\n label: 'View only',\n detail: `You can’t edit this anymore. Your changes stay on ${device}.`,\n };\n case 'delayed':\n return { label: 'Saving delayed', detail: savingDelayedDetail({ delay, keeping, device }) };\n }\n}\n\n/**\n * How long a document's edits may wait unconfirmed on a connection that is up before its saving\n * reads as delayed (`delayed`, `unconfirmed`), and before its room asks Keryx why: the stall window\n * every editor shares (`ACK_STALL_MS` in `@athenaintel/asset-host/local-updates`, which Olympus's\n * `room-sync-store.test.ts` holds equal).\n */\nexport const UNCONFIRMED_EDITS_STALL_MS = 15_000;\n\n/**\n * Whether a document's saving is delayed, and why (`DocumentSyncState` `delayed`): only while Athena\n * answers and the document's room is connected; `repairing` when Keryx refuses the room's writes\n * (quarantined while it is repaired: said at once, before anything waits), `unconfirmed` once its\n * edits have stayed unconfirmed past {@link UNCONFIRMED_EDITS_STALL_MS}; `null` otherwise. Every\n * app's chip asks it after a hold and after edits kept without a connection, and ahead of syncing\n * and saving, so a room that refuses writes never spins and being offline is never a delay.\n */\nexport function savingDelayCause({\n reachable,\n connected,\n writesRefused,\n unconfirmedStalled,\n}: {\n /** Athena answers (the app's reachability, never the socket alone). */\n reachable: boolean;\n /** The document's room is connected. */\n connected: boolean;\n /** Keryx's document status says the room takes no writes for now. */\n writesRefused: boolean;\n /** Local edits have waited unconfirmed past the stall window on this connection. */\n unconfirmedStalled: boolean;\n}): SavingDelayCause | null {\n if (!reachable || !connected) return null;\n if (writesRefused) return 'repairing';\n return unconfirmedStalled ? 'unconfirmed' : null;\n}\n\n/**\n * How long a chat message sent while Athena answers may go unaccepted before it counts as waiting\n * to sync. Athena accepts a send when it takes it, not when its turn ends: 99% of follow-up messages\n * within 3.4 s of the send, and 99% of a chat's first, which also dials, within 5.7 s (production\n * `chat_ttft`, 30 days to 2026-11-07). A send still unaccepted after this is stuck, not on its way.\n */\nexport const UNACCEPTED_SEND_STALL_MS = 8_000;\n\n/** Where a chat message a chat outbox lists stands, for {@link messageWaitsToSync}. */\nexport interface OutboxMessageStanding {\n /** Athena answers (the app's reachability, never the socket alone). */\n reachable: boolean;\n /**\n * On its way to Athena: sent, or queued to go. `false` while the outbox holds it: typed while\n * Athena couldn't be reached, behind a message that waits, asking after a day, or failed.\n */\n sending: boolean;\n /** Athena received it, before its answer reached the outbox. */\n received?: boolean;\n /** When it was sent (epoch ms); for one typed while Athena couldn't be reached, when it was typed. */\n sentAt: number;\n}\n\n/**\n * When a message on its way starts counting as waiting to sync, should Athena not have accepted it\n * by then ({@link UNACCEPTED_SEND_STALL_MS} after it was sent, while Athena answers); `null` when no\n * time passing changes whether it counts.\n */\nexport function messageStartsWaitingAt({\n reachable,\n sending,\n received = false,\n sentAt,\n}: OutboxMessageStanding): number | null {\n return reachable && sending && !received ? sentAt + UNACCEPTED_SEND_STALL_MS : null;\n}\n\n/**\n * Whether a chat message a chat outbox lists counts as waiting to sync, for the status line's\n * count and the \"Waiting to sync\" list: one the outbox holds, always; one on its way, at once while\n * Athena can't be reached, and while it answers only once it went unaccepted past\n * {@link UNACCEPTED_SEND_STALL_MS}; one Athena received, never. A send that goes as usual, however\n * long its turn runs, shows no status line.\n */\nexport function messageWaitsToSync(standing: OutboxMessageStanding & { now: number }): boolean {\n const startsAt = messageStartsWaitingAt(standing);\n if (startsAt !== null) return standing.now >= startsAt;\n return !(standing.sending && standing.received === true);\n}\n\n/**\n * What the person lost of a document while it was open, when the server checked its room's grant\n * again (Keryx's 4401, after a share changed): `edit`, they may still view it but no longer edit it;\n * `view`, they may no longer open it at all.\n */\nexport type AccessLoss = 'edit' | 'view';\n\n/** What a document says once the person's access changed while it was open. */\nexport interface AccessChangedCopy extends StatusCopy {\n /**\n * The label of the button that saves the person's version as a file of their own, with the\n * changes Athena never took, or `null` when nothing is offered: nothing of theirs waits, or the\n * device no longer serves the document (`view`).\n */\n saveCopy: string | null;\n}\n\n/**\n * What a document says once the person's access to it changed while it was open (its editor turns\n * read-only at once), in Word's own words (Word for Mac's message bar, `strman_a6d4`, and its\n * \"Permissions Have Changed\" notice, `strman_0a3e`). `keptChanges`: changes Athena never took wait\n * on the device, never sent; Word offers to save a copy of the file so nothing typed is lost. A\n * `view` loss offers nothing to save: the device stops serving a document the person may no longer\n * read, and their changes stay where they are kept.\n */\nexport function accessChangedCopy({\n loss,\n keptChanges,\n}: {\n loss: AccessLoss;\n keptChanges: boolean;\n}): AccessChangedCopy {\n if (loss === 'view') {\n return {\n title: 'Permissions Have Changed',\n detail:\n 'The permissions on this file were updated and you no longer have rights to view this file. If you previously made changes to this file, they may not be saved.',\n saveCopy: null,\n };\n }\n if (keptChanges) {\n return {\n title: 'Can’t save',\n detail:\n 'You no longer have the permission to edit this file. To keep your changes, save a copy of the file.',\n saveCopy: 'Save a Copy',\n };\n }\n return {\n title: 'Read Only',\n detail: 'You no longer have the permission to edit this file.',\n saveCopy: null,\n };\n}\n\n/** What a document says while it holds changes an older version of Athena made on the device. */\nexport interface OlderVersionChangesCopy extends StatusCopy {\n /** Saves this device's version as a file of the person's own, those changes included (Word's). */\n saveCopy: string;\n /** Sets this device's version aside, kept on the device to compare, and opens Athena's. */\n useAthenaVersion: string;\n /** Athena's version couldn't be opened: another window of the device has the document open. */\n openElsewhere: string;\n}\n\n/**\n * What a document says while its local copy holds changes an older version of Athena made on this\n * device, below its room's write floor (`older-version`, `@athenaintel/local-copy/room-copy`): such\n * a version deletes what newer ones store, so those changes are never uploaded. Word's way out,\n * as when it can't save a cloud document (\"You can save a copy to prevent losing your work\",\n * `strman`): Save a Copy, and Athena's version, which keeps this device's version on it to compare\n * and copy from until the person discards it. `saveCopy: false` for an editor that offers no Save\n * a Copy of the live document. `keepsAside: false` where the device keeps no version of it aside\n * (copies off, an embed): Athena's version then replaces the changes, which the person confirms\n * first (`olderVersionDiscardCopy`). `atRisk`: the device can lose them before the person chooses\n * (`ChangesAtRisk`), said here so the document shows one strip, never a second \"Changes not saved\".\n */\nexport function olderVersionChangesCopy({\n device,\n noun,\n saveCopy = true,\n keepsAside = true,\n atRisk = null,\n}: {\n device: DeviceNoun;\n /** What the person calls the document (\"document\", \"spreadsheet\"). */\n noun: string;\n /** Whether the editor offers Save a Copy beside Athena's version. */\n saveCopy?: boolean;\n /** Whether Athena's version keeps the device's aside, as a version to compare and copy from. */\n keepsAside?: boolean;\n /** How the device could lose the changes before the person chooses, or `null`. */\n atRisk?: ChangesAtRisk | null;\n}): OlderVersionChangesCopy {\n const made = `You changed this ${noun} on ${device} in an older version of Athena, so those changes can’t be uploaded.`;\n const keep = !keepsAside\n ? `${made} To keep them, save a copy: Athena’s version replaces them on ${device}.`\n : saveCopy\n ? `${made} To keep them, save a copy, or use Athena’s version: yours stays on ${device} to compare and copy from.`\n : `${made} Use Athena’s version to keep yours on ${device}, where you can compare it, copy from it or download it.`;\n const risk =\n atRisk === null\n ? ''\n : atRisk === 'memory'\n ? ` Until you choose, they’re kept only until you close ${openContainer(device)}.`\n : ` Until you choose, they’re saved only on ${device}, which can remove them.`;\n return {\n title: 'Changes made in an older version of Athena',\n detail: `${keep}${risk}`,\n saveCopy: 'Save a Copy',\n useAthenaVersion: 'Use Athena’s version',\n openElsewhere: `This ${noun} is open in another window. Close it there, then try again.`,\n };\n}\n\n/**\n * What the device asks before Athena's version replaces changes an older version of Athena made,\n * where it keeps no version of them aside (`olderVersionChangesCopy`'s `keepsAside: false`): they\n * are deleted then, so a copy saved first is the only way to keep them.\n */\nexport function olderVersionDiscardCopy({ device }: { device: DeviceNoun }): StatusCopy & {\n confirm: string;\n cancel: string;\n} {\n return {\n title: 'Use Athena’s version?',\n detail: `The changes made in an older version of Athena are deleted from ${device} and can’t be recovered. To keep them, save a copy first.`,\n confirm: 'Use Athena’s version',\n cancel: 'Cancel',\n };\n}\n\n/** When something that needs Athena works again (the second half of `NEEDS_CONNECTION`'s line). */\nconst AVAILABLE_AGAIN = 'It’s available again when you’re back online.';\n\n/**\n * The reason on a control that needs Athena (share, run, upload, invite…),\n * shown disabled while Athena can't be reached rather than failing when used.\n */\nexport const NEEDS_CONNECTION: LabelCopy = {\n label: 'Needs a connection',\n detail: `This needs Athena. ${AVAILABLE_AGAIN}`,\n};\n\n/** What a composer was given to attach: a photo (from the phone's library or camera) or any file. */\nexport type AttachmentKind = 'photo' | 'file';\n\n/**\n * What a composer says when a photo or file is picked, pasted or dropped while\n * Athena can't be reached. It isn't attached: only Athena can take the upload.\n * In a chat whose messages wait to be sent meanwhile (`messagesWait`: the chat\n * keeps an outbox), the message itself still goes, so that comes first. Where\n * nothing waits (the Chrome side panel, a launcher that keeps its draft), it\n * says only when attaching works again, as `NEEDS_CONNECTION` does.\n */\nexport function attachmentNeedsConnection({\n kind,\n messagesWait,\n}: {\n kind: AttachmentKind;\n messagesWait: boolean;\n}): string {\n const attaching = `Attaching ${kind === 'photo' ? 'a photo' : 'a file'} needs Athena. ${AVAILABLE_AGAIN}`;\n return messagesWait\n ? `You can still send your message: it goes when Athena is back. ${attaching}`\n : attaching;\n}\n\n/** What a sent message carries besides its text that can't wait for Athena. */\nfunction heldExtras(withQuote: boolean): string {\n return withQuote ? 'an attachment or a quote' : 'an attachment';\n}\n\n/**\n * What a composer says when a message is sent while Athena can't be reached\n * with an attachment that never reached Athena (or, `withQuote`, a quote the\n * chat can't keep waiting). Its text could wait in the chat outbox; the\n * attachment can't, so the draft stays as it is.\n */\nexport function attachedMessageNeedsConnection({\n withQuote = false,\n}: {\n withQuote?: boolean;\n} = {}): string {\n return `Your text can wait and go when Athena is back, but ${heldExtras(withQuote)} can’t. Remove ${\n withQuote ? 'it' : 'the attachment'\n } to send the text.`;\n}\n\n/**\n * What a composer says when a message with an attachment (or, `withQuote`, a\n * quote) is sent while messages written when Athena couldn't be reached still\n * wait to go: those go first, and this one can't wait behind them.\n */\nexport function attachedMessageBehindWaiting({\n withQuote = false,\n}: {\n withQuote?: boolean;\n} = {}): string {\n return `Messages you wrote while Athena couldn’t be reached go first. A message with ${heldExtras(\n withQuote\n )} can’t wait behind them, so send it once they’ve gone.`;\n}\n\n/**\n * The reason on New Presentation while Athena can't be reached, in a workspace\n * whose new presentations start from its design system's template: a\n * presentation made offline starts blank, and only Athena can copy the\n * template, so none is made until it can.\n */\nexport const NEW_PRESENTATION_NEEDS_TEMPLATE: LabelCopy = {\n label: 'Needs a connection',\n detail:\n 'New presentations in this workspace start from its design template, which needs Athena. You can make one when you’re back online.',\n};\n\n/**\n * What a download of a spreadsheet made from an Excel Macro-Enabled Workbook\n * (`.xlsm`) says when it went without the macros because they come from Athena,\n * which can't be reached, and the device hasn't kept them (they travel with the\n * workbook and never run). The file is the workbook without them; downloading\n * it again with a connection keeps them.\n */\nexport function downloadedWithoutMacros({ device }: { device: DeviceNoun }): string {\n return `Downloaded without the spreadsheet’s macros: they come from Athena, which can’t be reached, and ${device} hasn’t kept them. Download it again when you’re back online to keep them.`;\n}\n\n/**\n * Save's question for a spreadsheet whose file is an Excel Macro-Enabled\n * Workbook (`.xlsm`) while its macros come from Athena, which can't be reached,\n * and the device hasn't kept them: the `.xlsm` is never written without them,\n * so the person may save an Excel Workbook (`.xlsx`) beside it, and Save writes\n * the `.xlsm` again once Athena answers.\n */\nexport function macrosNeedConnectionToSave({\n name,\n device,\n}: {\n name: string;\n device: DeviceNoun;\n}): StatusCopy {\n return {\n title: `Athena can’t save the macros in “${name}” right now.`,\n detail: `They come from Athena, which can’t be reached, and ${device} hasn’t kept them. Save it as an Excel Workbook (.xlsx) instead. “${name}” stays as it is, macros included, and Save writes it again when you’re back online.`,\n };\n}\n\n/**\n * What saving a version kept on the device as a new spreadsheet says when the\n * spreadsheet was made from an Excel Macro-Enabled Workbook (`.xlsm`) and\n * Athena can't be reached: the new spreadsheet is made all the same (on the\n * device, and it syncs when Athena is back), but without the macros, which only\n * Athena can keep with a new spreadsheet (they travel with the workbook and\n * never run). The kept version stays on the device, so saving it again with a\n * connection keeps them.\n */\nexport function savedAsNewWithoutMacros({ device }: { device: DeviceNoun }): string {\n return `The new spreadsheet was made without the macros: only Athena can keep them in a new spreadsheet, and it can’t be reached. The kept version stays on ${device}: save it as a new spreadsheet again when you’re back online to keep them.`;\n}\n\n/**\n * What saving a copy of a Word document says when the copy was made on the\n * device while Athena can't be reached, for a document whose original Word file\n * Athena keeps (one imported from Word): the copy is made all the same, from the\n * document as the device holds it, over the original file kept with it, so it\n * keeps that file's parts but writes its body from what the editor shows.\n * Athena's own copy, made from the original file, keeps everything, so saving\n * a copy again with a connection makes that one.\n */\nexport function wordCopyMadeOnDevice({ device }: { device: DeviceNoun }): StatusCopy {\n return {\n title: `Copy made on ${device}`,\n detail: `Athena can’t be reached, so the copy holds the document as it is on ${device}. Anything in the original Word file that Athena doesn’t show may be missing from it: save a copy again when you’re back online for the complete file.`,\n };\n}\n\n/**\n * Whether an item opens without a connection on this device, for lists.\n * `canKeep` says whether opening it online would keep a copy here (the\n * deployment allows device copies and the item's type is one that is kept):\n * only then is the person told to open it once.\n */\nexport function offlineAvailabilityCopy({\n available,\n canKeep,\n device,\n}: {\n available: boolean;\n canKeep: boolean;\n device: DeviceNoun;\n}): LabelCopy {\n if (available) {\n return { label: 'Available offline', detail: `Opens without a connection on ${device}.` };\n }\n return canKeep\n ? {\n label: 'Not available offline',\n detail: `Open it once while online to keep it on ${device}.`,\n }\n : { label: 'Not available offline', detail: 'This opens only with a connection.' };\n}\n\n/**\n * The choice to always keep an item on the device, as OneDrive's \"Always Keep\n * on This Device\" (for the item's menu and its toggle in a list). Kept, it\n * stays however long it goes unopened; otherwise the device keeps what was\n * opened in the last `keptDays` days while there is room, and an item turned\n * off counts its days from then. `menuLabel` is the label in a desktop menu's\n * title case (\"Always Keep on This Mac\").\n */\nexport function alwaysKeepCopy({\n kept,\n device,\n keptDays,\n}: {\n kept: boolean;\n device: DeviceNoun;\n keptDays: number;\n}): LabelCopy & { menuLabel: string } {\n const titled = device.replace(/(^|\\s)\\S/g, (letter) => letter.toUpperCase());\n return {\n label: `Always keep on ${device}`,\n menuLabel: `Always Keep on ${titled}`,\n detail: kept\n ? `Kept on ${device} however long it goes unopened, so it always opens without a connection. Turned off, it stays while you open it at least every ${keptDays} days and there’s room, counting from then.`\n : `Kept on ${device} while you open it at least every ${keptDays} days and there’s room. Turn this on to keep it however long it goes unopened.`,\n };\n}\n\n/**\n * What a toast says when always keeping an item on the device could not be\n * turned on or off (`alwaysKeepCopy`): the item was no longer kept there\n * (`gone`: nothing to keep until it is opened once online), or the change\n * failed and can be tried again.\n */\nexport function alwaysKeepFailedCopy({\n kept,\n gone,\n device,\n}: {\n /** What the person asked for: on (`true`) or off. */\n kept: boolean;\n gone: boolean;\n device: DeviceNoun;\n}): string {\n if (gone) {\n return `This isn’t kept on ${device} any more. Open it once while online to keep it here.`;\n }\n return `Always keep on ${device} couldn’t be turned ${kept ? 'on' : 'off'}. Try again.`;\n}\n\n/**\n * A history Athena keeps in full (a person's dictations), shown while Athena\n * can't be reached: the list holds only what is kept on the device, and the\n * rest comes back once online. `items` names what the list holds, plural.\n */\nexport function historyOnDeviceCopy({\n items,\n device,\n}: {\n items: string;\n device: DeviceNoun;\n}): string {\n return `Showing the ${items} kept on ${device}. Your full history shows when you’re back online.`;\n}\n\n/**\n * The one-time explainer shown the first time the person goes offline, on a\n * surface that keeps work there (`keeping` `device`). A surface that keeps\n * nothing (`none`: the Chrome side panel, the Office task pane) shows no\n * explainer; its status line already says all that holds.\n */\nexport function firstOfflineExplainer({ device }: { device: DeviceNoun }): StatusCopy & {\n action: string;\n} {\n return {\n title: 'You can keep working offline',\n detail: `Documents you’ve opened recently keep working on ${device}. Your changes sync when you’re back online.`,\n action: 'Got it',\n };\n}\n\n/**\n * How a document's changes could be lost before they reach Athena:\n *\n * - `device`: saved on the device until they reach Athena (no connection, or a review the person\n * has not finished), but the device can remove them before then (a browser that hasn't granted\n * persistent storage, a private window);\n * - `held`: saved on the device and can't be sent (the person can only view the document now, or\n * Athena refused it), and the device can remove them;\n * - `memory`: kept only until the tab or app closes (the device keeps no copy).\n */\nexport type ChangesAtRisk = 'device' | 'held' | 'memory';\n\n/**\n * What an editor says above a document whose changes could be lost before they reach Athena, with\n * the copy it offers of them (Word's \"Upload pending\" and \"Changes not saved\"), by\n * {@link ChangesAtRisk}.\n */\nexport function changesAtRiskCopy({\n risk,\n device,\n}: {\n risk: ChangesAtRisk;\n device: DeviceNoun;\n}): StatusCopy & { download: string; downloadFailed: string } {\n const actions = {\n download: 'Download a copy',\n downloadFailed: 'Couldn’t download a copy. Try again.',\n };\n switch (risk) {\n case 'memory':\n return {\n title: 'Changes not saved',\n detail: `Your changes are kept only until you close ${openContainer(device)}. Download a copy to keep them.`,\n ...actions,\n };\n case 'held':\n return {\n title: 'Changes not saved',\n detail: `Your changes can’t be sent, and they’re saved only on ${device}, which can remove them. Download a copy to keep them.`,\n ...actions,\n };\n case 'device':\n return {\n title: 'Upload pending',\n detail: `Your changes are saved only on ${device} until they reach Athena, and ${device} can remove them before then. Download a copy to keep them.`,\n ...actions,\n };\n }\n}\n\n/**\n * The action that asks the device to keep what it holds until it syncs, where asking shows the\n * person a question of the device's own (Firefox asks whether the site may store data in\n * persistent storage): the app says why first (`changesAtRiskCopy`) and asks only on this press.\n */\nexport function keepOnDeviceAction({ device }: { device: DeviceNoun }): string {\n return `Keep them on ${device}`;\n}\n\n/** A browser whose own way of keeping a site's data longer the words point to. */\nexport type SaferStorageBrowser = 'safari-mac' | 'safari-ios';\n\n/**\n * Where changes made offline in Safari are kept longer: Safari keeps a site added to the Dock or\n * the Home Screen as an app of its own, which it is likelier to let keep its data, and the desktop\n * app keeps them in storage of its own.\n */\nexport function saferStorageHint({ browser }: { browser: SaferStorageBrowser }): string {\n return browser === 'safari-mac'\n ? 'To keep changes made offline safer in Safari, add Athena to the Dock (File ▸ Add to Dock), or use Athena Desktop.'\n : 'To keep changes made offline safer, add Athena to your Home Screen (Share ▸ Add to Home Screen).';\n}\n\n/**\n * What the app says when it finds that changes it kept on the device never reached Athena and the\n * device no longer has them (the browser removed them before they synced), naming how many\n * documents; each document's row says when its changes were made (`lostChangesItemCopy`).\n */\nexport function lostChangesCopy({\n device,\n documents,\n}: {\n device: DeviceNoun;\n documents: number;\n}): StatusCopy & { why: string; open: string; dismiss: string } {\n const which = documents === 1 ? 'a document' : plural(documents, 'document', 'documents');\n return {\n title: 'Changes not saved',\n detail: `Changes you made to ${which} on ${device} never reached Athena, and ${device} no longer has them.`,\n why: 'Browsers can remove what a site keeps when they run short of space, or when the site hasn’t been opened for a while.',\n open: 'Open',\n dismiss: 'Dismiss',\n };\n}\n\n/** One document's row under `lostChangesCopy`: the words before when its changes were made. */\nexport function lostChangesItemCopy({ device }: { device: DeviceNoun }): string {\n return `Changed on ${device}`;\n}\n\n/**\n * The summary heading of the one \"Waiting to sync\" list, from what waits on\n * the device; `null` when nothing does.\n */\nexport function waitingSummary({\n changes = 0,\n messages = 0,\n recordings = 0,\n}: {\n changes?: number;\n messages?: number;\n recordings?: number;\n}): string | null {\n const parts = [\n changes > 0 ? plural(changes, 'change', 'changes') : null,\n messages > 0 ? plural(messages, 'message', 'messages') : null,\n recordings > 0 ? plural(recordings, 'recording', 'recordings') : null,\n ].filter((part): part is string => part !== null);\n return parts.length === 0 ? null : `Waiting to sync: ${parts.join(', ')}`;\n}\n\n/**\n * Where one item in the \"Waiting to sync\" list stands: a change, a message or a\n * recording made while Athena couldn't be reached.\n */\nexport type WaitingItemState =\n /** Saved on the device; it syncs when Athena is back. */\n | 'waiting'\n /** Being sent to Athena now. */\n | 'syncing'\n /**\n * Kept only while this tab or app stays open: it couldn't be saved on the\n * device (the organization keeps nothing on devices, or storage failed).\n */\n | 'in-memory'\n /**\n * Saved on the device in something that isn't open (a document closed before\n * its edits synced, one made offline): it syncs when it is next opened with a\n * connection (opening it offline sends nothing).\n */\n | 'when-opened'\n /** Made in another workspace: it syncs once that workspace is open again, with a connection. */\n | 'other-workspace'\n /** It doesn't go on its own: the person chooses (a message that waited more than a day). */\n | 'needs-you'\n /** Athena didn't take it: the app adds why, and what the person can do about it. */\n | 'not-synced';\n\n/**\n * The state of one item in the \"Waiting to sync\" list, and the line that explains it. For an item\n * saved on the device (`waiting`, `when-opened`), `evictable` says the device may remove it before\n * it syncs (default `false`).\n */\nexport function waitingItemCopy({\n state,\n device,\n evictable = false,\n}: {\n state: WaitingItemState;\n device: DeviceNoun;\n evictable?: boolean;\n}): LabelCopy {\n const removable = evictable ? ` ${removableBeforeSync({ device, count: 1 })}` : '';\n switch (state) {\n case 'waiting':\n return {\n label: 'Waiting to sync',\n detail: `Saved on ${device}. It syncs when Athena is back.${removable}`,\n };\n case 'syncing':\n return { label: 'Syncing…', detail: `Sending what was saved on ${device}.` };\n case 'in-memory':\n return {\n label: 'Not saved yet',\n detail: `Kept only until you close ${openContainer(device)}. It syncs when Athena is back.`,\n };\n case 'when-opened':\n return {\n label: 'Not synced yet',\n detail: `Saved on ${device}. It syncs when you next open it with a connection.${removable}`,\n };\n case 'other-workspace':\n return {\n label: 'Waiting for its workspace',\n detail: 'It syncs once you’re in the workspace it was made in, with a connection.',\n };\n case 'needs-you':\n return { label: 'Waiting for you', detail: 'Open it to choose what happens to it.' };\n case 'not-synced':\n return { label: 'Couldn’t sync', detail: 'Athena didn’t take it.' };\n }\n}\n\n/** The headings of the \"Waiting to sync\" list, one per kind of item. */\nexport const WAITING_SECTION_TITLES = {\n changes: 'Changes',\n messages: 'Messages',\n recordings: 'Recordings',\n} as const;\n\n/**\n * What the person can do with an item Athena didn't take (`not-synced`) in the\n * \"Waiting to sync\" list: send it again, or delete the copy on the device. That\n * copy is the item's only one, so the app asks first (`deleteFromDeviceConfirm`)\n * and never deletes it as a side effect of anything else.\n */\nexport function notSyncedActions({ device }: { device: DeviceNoun }): {\n retry: string;\n remove: string;\n} {\n return { retry: 'Try again', remove: `Delete from ${device}` };\n}\n\n/** One of `notSyncedActions`, or showing where the item is kept on the device. */\nexport type NotSyncedAction = 'retry' | 'reveal' | 'remove';\n\n/**\n * What the person hears when the device couldn't do what they asked for an\n * item Athena didn't take (its files, not Athena, failed).\n */\nexport function notSyncedActionFailed({\n action,\n device,\n}: {\n action: NotSyncedAction;\n device: DeviceNoun;\n}): string {\n switch (action) {\n case 'retry':\n return 'Couldn’t send it again. Try again in a moment.';\n case 'reveal':\n return `Couldn’t show where it’s kept on ${device}.`;\n case 'remove':\n return `Couldn’t delete it from ${device}.`;\n }\n}\n\n/**\n * The question before deleting such an item's copy on the device, naming the\n * item: the destructive choice is never the default.\n */\nexport function deleteFromDeviceConfirm({\n name,\n device,\n}: {\n name: string;\n device: DeviceNoun;\n}): StatusCopy & { confirm: string; cancel: string } {\n return {\n title: `Delete “${name}” from ${device}?`,\n detail: 'Athena didn’t take it, so this is its only copy. Deleting it can’t be undone.',\n confirm: 'Delete',\n cancel: 'Cancel',\n };\n}\n"],"names":[],"mappings":";;AA6TO,MAAM,6BAA6B;AAqN1C,MAAM,kBAAkB;AAMjB,MAAM,mBAA8B;AAAA,EACzC,OAAO;AAAA,EACP,QAAQ,sBAAsB,eAAe;AAC/C;AAaO,SAAS,0BAA0B;AAAA,EACxC;AAAA,EACA;AACF,GAGW;AACT,QAAM,YAAY,aAA4C,QAAQ,kBAAkB,eAAe;AACvG,SAAO,eACH,iEAAiE,SAAS,KAC1E;AACN;AAGA,SAAS,WAAW,WAA4B;AAC9C,SAAO,YAAY,6BAA6B;AAClD;AAQO,SAAS,+BAA+B;AAAA,EAC7C,YAAY;AACd,IAEI,IAAY;AACd,SAAO,sDAAsD,WAAW,SAAS,CAAC,kBAChF,YAAY,OAAO,gBACrB;AACF;AAOO,SAAS,6BAA6B;AAAA,EAC3C,YAAY;AACd,IAEI,IAAY;AACd,SAAO,gFAAgF;AAAA,IACrF;AAAA,EAAA,CACD;AACH;;;;;;"}
|