@athenaintel/react 0.41.2 → 0.42.1
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 +108 -9
- package/dist/agent-runtime/src/asset-attachment.d.ts +98 -0
- package/dist/agent-runtime/src/athena-asset-drag.d.ts +32 -0
- package/dist/agent-runtime/src/auth-denial.d.ts +29 -0
- package/dist/agent-runtime/src/chat-outbox-attachments.cjs +41 -0
- package/dist/agent-runtime/src/chat-outbox-attachments.cjs.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-attachments.d.ts +38 -0
- package/dist/agent-runtime/src/chat-outbox-attachments.js +41 -0
- package/dist/agent-runtime/src/chat-outbox-attachments.js.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-signals.cjs +63 -0
- package/dist/agent-runtime/src/chat-outbox-signals.cjs.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-signals.d.ts +12 -0
- package/dist/agent-runtime/src/chat-outbox-signals.js +63 -0
- package/dist/agent-runtime/src/chat-outbox-signals.js.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-store.cjs +509 -0
- package/dist/agent-runtime/src/chat-outbox-store.cjs.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-store.d.ts +203 -0
- package/dist/agent-runtime/src/chat-outbox-store.js +509 -0
- package/dist/agent-runtime/src/chat-outbox-store.js.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-thread.cjs +136 -0
- package/dist/agent-runtime/src/chat-outbox-thread.cjs.map +1 -0
- package/dist/agent-runtime/src/chat-outbox-thread.d.ts +118 -0
- package/dist/agent-runtime/src/chat-outbox-thread.js +136 -0
- package/dist/agent-runtime/src/chat-outbox-thread.js.map +1 -0
- package/dist/agent-runtime/src/chat-outbox.cjs +696 -0
- package/dist/agent-runtime/src/chat-outbox.cjs.map +1 -0
- package/dist/agent-runtime/src/chat-outbox.d.ts +285 -0
- package/dist/agent-runtime/src/chat-outbox.js +696 -0
- package/dist/agent-runtime/src/chat-outbox.js.map +1 -0
- package/dist/agent-runtime/src/chat-socket-reachability.d.ts +45 -0
- package/dist/agent-runtime/src/client-tool-bridge.d.ts +152 -0
- package/dist/agent-runtime/src/client-tools.d.ts +133 -0
- package/dist/agent-runtime/src/composer-markdown.cjs +10 -0
- package/dist/agent-runtime/src/composer-markdown.cjs.map +1 -1
- package/dist/agent-runtime/src/composer-markdown.d.ts +108 -0
- package/dist/agent-runtime/src/composer-markdown.js +10 -0
- package/dist/agent-runtime/src/composer-markdown.js.map +1 -1
- package/dist/agent-runtime/src/config-mutations.d.ts +51 -0
- package/dist/agent-runtime/src/conversation-index.d.ts +110 -0
- package/dist/agent-runtime/src/conversation-list.d.ts +343 -0
- package/dist/agent-runtime/src/deep-agent-transport-recipe.cjs +3 -2
- package/dist/agent-runtime/src/deep-agent-transport-recipe.cjs.map +1 -1
- package/dist/agent-runtime/src/deep-agent-transport-recipe.d.ts +166 -0
- package/dist/agent-runtime/src/deep-agent-transport-recipe.js +3 -2
- package/dist/agent-runtime/src/deep-agent-transport-recipe.js.map +1 -1
- package/dist/agent-runtime/src/desktop-handoff.d.ts +139 -0
- package/dist/agent-runtime/src/durable-thread-snapshot-cache.cjs +158 -0
- package/dist/agent-runtime/src/durable-thread-snapshot-cache.cjs.map +1 -0
- package/dist/agent-runtime/src/durable-thread-snapshot-cache.d.ts +60 -0
- package/dist/agent-runtime/src/durable-thread-snapshot-cache.js +158 -0
- package/dist/agent-runtime/src/durable-thread-snapshot-cache.js.map +1 -0
- package/dist/agent-runtime/src/edit-command.d.ts +156 -0
- package/dist/agent-runtime/src/errors.d.ts +174 -0
- package/dist/agent-runtime/src/execute-output.d.ts +31 -0
- package/dist/agent-runtime/src/generated/runconfig-contract.cjs +16 -2
- package/dist/agent-runtime/src/generated/runconfig-contract.cjs.map +1 -1
- package/dist/agent-runtime/src/generated/runconfig-contract.d.ts +202 -0
- package/dist/agent-runtime/src/generated/runconfig-contract.js +16 -2
- package/dist/agent-runtime/src/generated/runconfig-contract.js.map +1 -1
- package/dist/agent-runtime/src/github-wake-event.d.ts +77 -0
- package/dist/agent-runtime/src/index.d.ts +74 -0
- package/dist/agent-runtime/src/interrupts.cjs +17 -0
- package/dist/agent-runtime/src/interrupts.cjs.map +1 -1
- package/dist/agent-runtime/src/interrupts.d.ts +348 -0
- package/dist/agent-runtime/src/interrupts.js +17 -0
- package/dist/agent-runtime/src/interrupts.js.map +1 -1
- package/dist/agent-runtime/src/lane-follow.d.ts +121 -0
- package/dist/agent-runtime/src/lane-history.cjs +209 -0
- package/dist/agent-runtime/src/lane-history.cjs.map +1 -0
- package/dist/agent-runtime/src/lane-history.d.ts +175 -0
- package/dist/agent-runtime/src/lane-history.js +209 -0
- package/dist/agent-runtime/src/lane-history.js.map +1 -0
- package/dist/agent-runtime/src/lane-images.d.ts +184 -0
- package/dist/agent-runtime/src/message-author.d.ts +43 -0
- package/dist/agent-runtime/src/message-text.cjs +15 -0
- package/dist/agent-runtime/src/message-text.cjs.map +1 -0
- package/dist/agent-runtime/src/message-text.d.ts +47 -0
- package/dist/agent-runtime/src/message-text.js +15 -0
- package/dist/agent-runtime/src/message-text.js.map +1 -0
- package/dist/agent-runtime/src/message-window.cjs +15 -1
- package/dist/agent-runtime/src/message-window.cjs.map +1 -1
- package/dist/agent-runtime/src/message-window.d.ts +159 -0
- package/dist/agent-runtime/src/message-window.js +16 -2
- package/dist/agent-runtime/src/message-window.js.map +1 -1
- package/dist/agent-runtime/src/messages.cjs +88 -4
- package/dist/agent-runtime/src/messages.cjs.map +1 -1
- package/dist/agent-runtime/src/messages.d.ts +603 -0
- package/dist/agent-runtime/src/messages.js +88 -4
- package/dist/agent-runtime/src/messages.js.map +1 -1
- package/dist/agent-runtime/src/model-context.d.ts +22 -0
- package/dist/agent-runtime/src/offline-status.d.ts +157 -0
- package/dist/agent-runtime/src/optimistic-content.d.ts +21 -0
- package/dist/agent-runtime/src/protocol.cjs +12 -4
- package/dist/agent-runtime/src/protocol.cjs.map +1 -1
- package/dist/agent-runtime/src/protocol.d.ts +119 -0
- package/dist/agent-runtime/src/protocol.js +13 -5
- package/dist/agent-runtime/src/protocol.js.map +1 -1
- package/dist/agent-runtime/src/ptc-subcalls.d.ts +51 -0
- package/dist/agent-runtime/src/queue.d.ts +138 -0
- package/dist/agent-runtime/src/quota-safe-local-storage-session.d.ts +154 -0
- package/dist/agent-runtime/src/running-tool-placeholder.cjs +11 -0
- package/dist/agent-runtime/src/running-tool-placeholder.cjs.map +1 -0
- package/dist/agent-runtime/src/running-tool-placeholder.d.ts +25 -0
- package/dist/agent-runtime/src/running-tool-placeholder.js +11 -0
- package/dist/agent-runtime/src/running-tool-placeholder.js.map +1 -0
- package/dist/agent-runtime/src/runtime-messages.d.ts +104 -0
- package/dist/agent-runtime/src/screen-point.d.ts +151 -0
- package/dist/agent-runtime/src/sealed-idb.cjs +112 -0
- package/dist/agent-runtime/src/sealed-idb.cjs.map +1 -0
- package/dist/agent-runtime/src/sealed-idb.d.ts +106 -0
- package/dist/agent-runtime/src/sealed-idb.js +112 -0
- package/dist/agent-runtime/src/sealed-idb.js.map +1 -0
- package/dist/agent-runtime/src/send-recovery.d.ts +40 -0
- package/dist/agent-runtime/src/statewire-attach-observer.d.ts +194 -0
- package/dist/agent-runtime/src/statewire-diagnostics.d.ts +74 -0
- package/dist/agent-runtime/src/statewire-state.d.ts +29 -0
- package/dist/agent-runtime/src/statewire-suspended.cjs.map +1 -1
- package/dist/agent-runtime/src/statewire-suspended.d.ts +27 -0
- package/dist/agent-runtime/src/statewire-suspended.js.map +1 -1
- package/dist/agent-runtime/src/statewire-transport.d.ts +40 -0
- package/dist/agent-runtime/src/streaming-markdown.d.ts +46 -0
- package/dist/agent-runtime/src/subagent-transcripts.cjs +209 -0
- package/dist/agent-runtime/src/subagent-transcripts.cjs.map +1 -0
- package/dist/agent-runtime/src/subagent-transcripts.d.ts +71 -0
- package/dist/agent-runtime/src/subagent-transcripts.js +209 -0
- package/dist/agent-runtime/src/subagent-transcripts.js.map +1 -0
- package/dist/agent-runtime/src/subagents.cjs +253 -0
- package/dist/agent-runtime/src/subagents.cjs.map +1 -0
- package/dist/agent-runtime/src/subagents.d.ts +311 -0
- package/dist/agent-runtime/src/subagents.js +253 -0
- package/dist/agent-runtime/src/subagents.js.map +1 -0
- package/dist/agent-runtime/src/subscription-wake-event.d.ts +111 -0
- package/dist/agent-runtime/src/thread-extras.d.ts +43 -0
- package/dist/agent-runtime/src/thread-handoff.d.ts +364 -0
- package/dist/agent-runtime/src/thread-prewarm-controller.d.ts +76 -0
- package/dist/agent-runtime/src/thread-prewarm.d.ts +118 -0
- package/dist/agent-runtime/src/thread-snapshot-cache.d.ts +99 -0
- package/dist/agent-runtime/src/thread-snapshot-mirror.cjs +329 -0
- package/dist/agent-runtime/src/thread-snapshot-mirror.cjs.map +1 -0
- package/dist/agent-runtime/src/thread-snapshot-mirror.d.ts +101 -0
- package/dist/agent-runtime/src/thread-snapshot-mirror.js +329 -0
- package/dist/agent-runtime/src/thread-snapshot-mirror.js.map +1 -0
- package/dist/agent-runtime/src/thread-status.d.ts +53 -0
- package/dist/agent-runtime/src/tool-metadata.d.ts +146 -0
- package/dist/agent-runtime/src/tool-names.cjs +67 -0
- package/dist/agent-runtime/src/tool-names.cjs.map +1 -1
- package/dist/agent-runtime/src/tool-names.d.ts +60 -0
- package/dist/agent-runtime/src/tool-names.js +68 -1
- package/dist/agent-runtime/src/tool-names.js.map +1 -1
- package/dist/agent-runtime/src/tool-outputs.d.ts +35 -0
- package/dist/agent-runtime/src/tool-result.cjs +1 -0
- package/dist/agent-runtime/src/tool-result.cjs.map +1 -1
- package/dist/agent-runtime/src/tool-result.d.ts +126 -0
- package/dist/agent-runtime/src/tool-result.js +1 -0
- package/dist/agent-runtime/src/tool-result.js.map +1 -1
- package/dist/agent-runtime/src/types.d.ts +159 -0
- package/dist/agent-runtime/src/use-conversation-list.d.ts +76 -0
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.cjs +136 -0
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.cjs.map +1 -0
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.d.ts +64 -0
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.js +136 -0
- package/dist/agent-runtime/src/use-deep-agent-chat-outbox.js.map +1 -0
- package/dist/agent-runtime/src/use-deep-agent-config.d.ts +169 -0
- package/dist/agent-runtime/src/use-deep-agent-edit-submit.cjs +13 -0
- package/dist/agent-runtime/src/use-deep-agent-edit-submit.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-edit-submit.d.ts +22 -0
- package/dist/agent-runtime/src/use-deep-agent-edit-submit.js +13 -0
- package/dist/agent-runtime/src/use-deep-agent-edit-submit.js.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-runtime.cjs +20 -2
- package/dist/agent-runtime/src/use-deep-agent-runtime.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-runtime.d.ts +168 -0
- package/dist/agent-runtime/src/use-deep-agent-runtime.js +20 -2
- package/dist/agent-runtime/src/use-deep-agent-runtime.js.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-thread.cjs +12 -4
- package/dist/agent-runtime/src/use-deep-agent-thread.cjs.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-thread.d.ts +320 -0
- package/dist/agent-runtime/src/use-deep-agent-thread.js +12 -4
- package/dist/agent-runtime/src/use-deep-agent-thread.js.map +1 -1
- package/dist/agent-runtime/src/use-deep-agent-voice.cjs +999 -0
- package/dist/agent-runtime/src/use-deep-agent-voice.cjs.map +1 -0
- package/dist/agent-runtime/src/use-deep-agent-voice.d.ts +409 -0
- package/dist/agent-runtime/src/use-deep-agent-voice.js +999 -0
- package/dist/agent-runtime/src/use-deep-agent-voice.js.map +1 -0
- package/dist/agent-runtime/src/use-deep-agent-window-sync.d.ts +102 -0
- package/dist/agent-runtime/src/use-historical-edit-attachments.d.ts +2 -0
- package/dist/agent-runtime/src/use-thread-handoff-flow.d.ts +84 -0
- package/dist/agent-runtime/src/voice-presentation.d.ts +80 -0
- package/dist/agent-runtime/src/voice-turn-grouping.d.ts +28 -0
- package/dist/agent-runtime/src/voice-wire-types.d.ts +15 -0
- package/dist/agent-runtime/src/withdrawn-turns.d.ts +97 -0
- package/dist/chat/AthenaChat.cjs +77 -6
- package/dist/chat/AthenaChat.cjs.map +1 -1
- package/dist/chat/AthenaChat.js +78 -7
- package/dist/chat/AthenaChat.js.map +1 -1
- package/dist/chat/StatewireApprovalCard.d.ts +1 -1
- package/dist/chat/StatewireClientToolBridge.d.ts +1 -1
- package/dist/chat/StatewireQueuedMessages.cjs +11 -4
- package/dist/chat/StatewireQueuedMessages.cjs.map +1 -1
- package/dist/chat/StatewireQueuedMessages.d.ts +1 -1
- package/dist/chat/StatewireQueuedMessages.js +11 -4
- package/dist/chat/StatewireQueuedMessages.js.map +1 -1
- package/dist/chat/chat-outbox-rows.cjs +223 -0
- package/dist/chat/chat-outbox-rows.cjs.map +1 -0
- package/dist/chat/chat-outbox-rows.d.ts +29 -0
- package/dist/chat/chat-outbox-rows.js +223 -0
- package/dist/chat/chat-outbox-rows.js.map +1 -0
- package/dist/chat/statewire-approval.d.ts +1 -1
- package/dist/chat/statewire-client-tools.d.ts +1 -1
- package/dist/chat/super-grouping/SuperGroupingCard.cjs +3 -1
- package/dist/chat/super-grouping/SuperGroupingCard.cjs.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingCard.d.ts +7 -1
- package/dist/chat/super-grouping/SuperGroupingCard.js +3 -1
- package/dist/chat/super-grouping/SuperGroupingCard.js.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingTranscript.cjs +7 -2
- package/dist/chat/super-grouping/SuperGroupingTranscript.cjs.map +1 -1
- package/dist/chat/super-grouping/SuperGroupingTranscript.d.ts +2 -2
- package/dist/chat/super-grouping/SuperGroupingTranscript.js +7 -2
- package/dist/chat/super-grouping/SuperGroupingTranscript.js.map +1 -1
- package/dist/chat/super-grouping/activity-timeline.cjs +19 -11
- package/dist/chat/super-grouping/activity-timeline.cjs.map +1 -1
- package/dist/chat/super-grouping/activity-timeline.d.ts +25 -9
- package/dist/chat/super-grouping/activity-timeline.js +19 -11
- package/dist/chat/super-grouping/activity-timeline.js.map +1 -1
- package/dist/chat/use-statewire-approval-request.cjs +36 -0
- package/dist/chat/use-statewire-approval-request.cjs.map +1 -1
- package/dist/chat/use-statewire-approval-request.d.ts +49 -1
- package/dist/chat/use-statewire-approval-request.js +39 -3
- package/dist/chat/use-statewire-approval-request.js.map +1 -1
- package/dist/chat-ui/composer/tiptap-composer.cjs +102 -3
- package/dist/chat-ui/composer/tiptap-composer.cjs.map +1 -1
- package/dist/chat-ui/composer/tiptap-composer.d.ts +32 -1
- package/dist/chat-ui/composer/tiptap-composer.js +103 -4
- package/dist/chat-ui/composer/tiptap-composer.js.map +1 -1
- package/dist/chat-ui/header/conversation-history-panel.d.ts +1 -1
- package/dist/chat-ui/index.d.ts +1 -1
- package/dist/chat-ui/messages/message-components.cjs +15 -0
- package/dist/chat-ui/messages/message-components.cjs.map +1 -1
- package/dist/chat-ui/messages/message-components.js +15 -0
- package/dist/chat-ui/messages/message-components.js.map +1 -1
- package/dist/chat-ui/messages/runtime-message.d.ts +1 -1
- package/dist/chat-ui/messages/statewire-continue-run.d.ts +1 -1
- package/dist/chat-ui/messages/user-edit-composer.cjs +15 -2
- package/dist/chat-ui/messages/user-edit-composer.cjs.map +1 -1
- package/dist/chat-ui/messages/user-edit-composer.d.ts +4 -2
- package/dist/chat-ui/messages/user-edit-composer.js +15 -2
- package/dist/chat-ui/messages/user-edit-composer.js.map +1 -1
- package/dist/chat-ui/messages/wake-marker.d.ts +1 -1
- package/dist/chat-ui/rich-text/chat-text-schema.cjs +1 -0
- package/dist/chat-ui/rich-text/chat-text-schema.cjs.map +1 -1
- package/dist/chat-ui/rich-text/chat-text-schema.d.ts +3 -0
- package/dist/chat-ui/rich-text/chat-text-schema.js +1 -0
- package/dist/chat-ui/rich-text/chat-text-schema.js.map +1 -1
- package/dist/chat-ui/statewire.cjs +1 -0
- package/dist/chat-ui/statewire.cjs.map +1 -1
- package/dist/chat-ui/statewire.d.ts +2 -2
- package/dist/chat-ui/statewire.js +2 -1
- package/dist/chat-ui/thread/statewire-history-edge.d.ts +1 -1
- package/dist/composer/AttachmentContext.cjs +8 -4
- package/dist/composer/AttachmentContext.cjs.map +1 -1
- package/dist/composer/AttachmentContext.d.ts +7 -0
- package/dist/composer/AttachmentContext.js +8 -4
- package/dist/composer/AttachmentContext.js.map +1 -1
- package/dist/composer/build-composed-message.cjs +34 -0
- package/dist/composer/build-composed-message.cjs.map +1 -1
- package/dist/composer/build-composed-message.d.ts +20 -0
- package/dist/composer/build-composed-message.js +35 -1
- package/dist/composer/build-composed-message.js.map +1 -1
- package/dist/composer/composer-handoff.cjs +39 -2
- package/dist/composer/composer-handoff.cjs.map +1 -1
- package/dist/composer/composer-handoff.d.ts +28 -3
- package/dist/composer/composer-handoff.js +39 -2
- package/dist/composer/composer-handoff.js.map +1 -1
- package/dist/composer/useAttachFiles.cjs +15 -2
- package/dist/composer/useAttachFiles.cjs.map +1 -1
- package/dist/composer/useAttachFiles.d.ts +11 -0
- package/dist/composer/useAttachFiles.js +15 -2
- package/dist/composer/useAttachFiles.js.map +1 -1
- package/dist/composer/useSendMessage.cjs.map +1 -1
- package/dist/composer/useSendMessage.d.ts +4 -3
- package/dist/composer/useSendMessage.js.map +1 -1
- package/dist/diagnostics/athena-diagnostics.cjs.map +1 -1
- package/dist/diagnostics/athena-diagnostics.d.ts +3 -1
- package/dist/diagnostics/athena-diagnostics.js.map +1 -1
- package/dist/index.cjs +18 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +15 -6
- package/dist/index.js +19 -1
- package/dist/index.js.map +1 -1
- package/dist/offline/chat-outbox.cjs +57 -0
- package/dist/offline/chat-outbox.cjs.map +1 -0
- package/dist/offline/chat-outbox.d.ts +80 -0
- package/dist/offline/chat-outbox.js +57 -0
- package/dist/offline/chat-outbox.js.map +1 -0
- package/dist/offline/offline-history.cjs +77 -0
- package/dist/offline/offline-history.cjs.map +1 -0
- package/dist/offline/offline-history.d.ts +60 -0
- package/dist/offline/offline-history.js +77 -0
- package/dist/offline/offline-history.js.map +1 -0
- package/dist/provider/AthenaProvider.cjs +206 -9
- package/dist/provider/AthenaProvider.cjs.map +1 -1
- package/dist/provider/AthenaProvider.d.ts +22 -1
- package/dist/provider/AthenaProvider.js +207 -10
- package/dist/provider/AthenaProvider.js.map +1 -1
- package/dist/provider/statewire-window-context.d.ts +1 -1
- package/dist/react/package.json.cjs +1 -1
- package/dist/react/package.json.js +1 -1
- package/dist/references/src/anchors/file-line-range.d.ts +58 -0
- package/dist/references/src/anchors/format.d.ts +21 -0
- package/dist/references/src/anchors/message-anchors.d.ts +71 -0
- package/dist/references/src/anchors/parse.d.ts +8 -0
- package/dist/references/src/anchors/registry-contract.d.ts +24 -0
- package/dist/references/src/anchors/registry.d.ts +19 -0
- package/dist/references/src/anchors/schemas.d.ts +194 -0
- package/dist/references/src/anchors/serialize.d.ts +8 -0
- package/dist/references/src/anchors/time.d.ts +78 -0
- package/dist/references/src/anchors/types.d.ts +474 -0
- package/dist/references/src/asset-bounds.d.ts +27 -0
- package/dist/references/src/asset-links.d.ts +23 -0
- package/dist/references/src/asset-reference.d.ts +16 -0
- package/dist/references/src/formats/format-catalog.d.ts +79 -0
- package/dist/references/src/formats/markdown/parse-reference-markdown.d.ts +28 -0
- package/dist/references/src/formats/markdown/reference-display-name.d.ts +6 -0
- package/dist/references/src/formats/object/asset-object.d.ts +9 -0
- package/dist/references/src/formats/object/callable-object.d.ts +6 -0
- package/dist/references/src/formats/object/decode-reference-object-payload.d.ts +3 -0
- package/dist/references/src/formats/object/external-url-object.d.ts +9 -0
- package/dist/references/src/formats/object/group-object.d.ts +9 -0
- package/dist/references/src/formats/object/navigation-object.d.ts +9 -0
- package/dist/references/src/formats/object/parse-reference-object.d.ts +11 -0
- package/dist/references/src/formats/object/person-object.d.ts +9 -0
- package/dist/references/src/formats/uri/asset-mention-uri.d.ts +9 -0
- package/dist/references/src/formats/uri/asset-spaces-url.d.ts +9 -0
- package/dist/references/src/formats/uri/callable-mention-uris.d.ts +9 -0
- package/dist/references/src/formats/uri/detect-uri-wire.d.ts +9 -0
- package/dist/references/src/formats/uri/group-mention-uri.d.ts +12 -0
- package/dist/references/src/formats/uri/navigation-spaces-url.d.ts +14 -0
- package/dist/references/src/formats/uri/parse-reference-uri.d.ts +20 -0
- package/dist/references/src/formats/uri/person-mention-uri.d.ts +9 -0
- package/dist/references/src/formats/uri/template-placeholder.d.ts +12 -0
- package/dist/references/src/index.d.ts +47 -0
- package/dist/references/src/legacy/index.d.ts +14 -0
- package/dist/references/src/legacy/pre-reference-asset-url.d.ts +57 -0
- package/dist/references/src/legacy/pre-reference-citation-bridge.d.ts +22 -0
- package/dist/references/src/legacy/pre-reference-citation.d.ts +138 -0
- package/dist/references/src/legacy/pre-reference-external-url.d.ts +31 -0
- package/dist/references/src/legacy/pre-reference-format.d.ts +8 -0
- package/dist/references/src/legacy/pre-reference-mention.d.ts +27 -0
- package/dist/references/src/legacy/pre-reference-object.d.ts +8 -0
- package/dist/references/src/legacy/pre-reference-uri.d.ts +12 -0
- package/dist/references/src/legacy.d.ts +2 -0
- package/dist/references/src/mention-href-patterns.d.ts +19 -0
- package/dist/references/src/mention-node/index.d.ts +5 -0
- package/dist/references/src/mention-node/mention-node.d.ts +31 -0
- package/dist/references/src/mention-node/resolve-node-attrs.d.ts +27 -0
- package/dist/references/src/parse-reference.d.ts +23 -0
- package/dist/references/src/schemas.d.ts +463 -0
- package/dist/references/src/serialize-reference.d.ts +50 -0
- package/dist/references/src/sheet-name.d.ts +10 -0
- package/dist/references/src/tool-option-schemas.d.ts +597 -0
- package/dist/references/src/types.d.ts +125 -0
- package/dist/references/src/version-ref.d.ts +30 -0
- package/dist/runtime/statewire-lifecycle.d.ts +1 -1
- package/dist/runtime/statewire-model-lane.d.ts +1 -1
- package/dist/runtime/statewire-server-lane-context.d.ts +1 -1
- package/dist/runtime/statewire-session-key.cjs +7 -0
- package/dist/runtime/statewire-session-key.cjs.map +1 -1
- package/dist/runtime/statewire-session-key.d.ts +16 -0
- package/dist/runtime/statewire-session-key.js +8 -1
- package/dist/runtime/statewire-session-key.js.map +1 -1
- package/dist/runtime/statewire-session-lane.cjs +48 -0
- package/dist/runtime/statewire-session-lane.cjs.map +1 -0
- package/dist/runtime/statewire-session-lane.d.ts +29 -0
- package/dist/runtime/statewire-session-lane.js +48 -0
- package/dist/runtime/statewire-session-lane.js.map +1 -0
- package/dist/runtime/statewire-thread-config-lane.d.ts +1 -1
- package/dist/runtime/useAthenaStatewireRuntime.cjs +16 -5
- package/dist/runtime/useAthenaStatewireRuntime.cjs.map +1 -1
- package/dist/runtime/useAthenaStatewireRuntime.d.ts +15 -1
- package/dist/runtime/useAthenaStatewireRuntime.js +17 -6
- package/dist/runtime/useAthenaStatewireRuntime.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/threads/api.d.ts +1 -1
- package/dist/threads/conversation-list-fetcher.d.ts +1 -1
- package/dist/threads/index-triggered-refresh.cjs +164 -0
- package/dist/threads/index-triggered-refresh.cjs.map +1 -0
- package/dist/threads/index-triggered-refresh.d.ts +70 -0
- package/dist/threads/index-triggered-refresh.js +164 -0
- package/dist/threads/index-triggered-refresh.js.map +1 -0
- package/dist/threads/offline-session-list.cjs +75 -0
- package/dist/threads/offline-session-list.cjs.map +1 -0
- package/dist/threads/offline-session-list.d.ts +27 -0
- package/dist/threads/offline-session-list.js +75 -0
- package/dist/threads/offline-session-list.js.map +1 -0
- package/dist/threads/pull-request-display.d.ts +1 -1
- package/dist/threads/session-list-model.d.ts +1 -1
- package/dist/threads/session-list-tab-share.cjs +150 -0
- package/dist/threads/session-list-tab-share.cjs.map +1 -0
- package/dist/threads/session-list-tab-share.d.ts +73 -0
- package/dist/threads/session-list-tab-share.js +150 -0
- package/dist/threads/session-list-tab-share.js.map +1 -0
- package/dist/threads/session-row-parts.d.ts +1 -1
- package/dist/threads/sessions-query.d.ts +1 -1
- package/dist/threads/statewire-thread-list.cjs +105 -20
- package/dist/threads/statewire-thread-list.cjs.map +1 -1
- package/dist/threads/statewire-thread-list.d.ts +31 -3
- package/dist/threads/statewire-thread-list.js +107 -22
- package/dist/threads/statewire-thread-list.js.map +1 -1
- package/dist/threads/thread-prefetcher.d.ts +1 -1
- package/dist/threads/use-athena-session-attention.d.ts +1 -1
- package/dist/threads/use-athena-sessions.cjs +32 -22
- package/dist/threads/use-athena-sessions.cjs.map +1 -1
- package/dist/threads/use-athena-sessions.js +33 -23
- package/dist/threads/use-athena-sessions.js.map +1 -1
- package/dist/threads/use-rest-conversation-history.d.ts +1 -1
- package/dist/threads/use-statewire-conversation-history.d.ts +5 -5
- package/dist/tiptap-markdown-table/src/markdown-table-serializer.d.ts +56 -0
- package/dist/tools/NestedPtcMessages.cjs +14 -9
- package/dist/tools/NestedPtcMessages.cjs.map +1 -1
- package/dist/tools/NestedPtcMessages.d.ts +9 -0
- package/dist/tools/NestedPtcMessages.js +6 -1
- package/dist/tools/NestedPtcMessages.js.map +1 -1
- package/dist/tools/index.d.ts +1 -1
- package/dist/tools/primitives.d.ts +1 -1
- package/dist/tools/subagent-task-tool-ui.cjs +494 -0
- package/dist/tools/subagent-task-tool-ui.cjs.map +1 -0
- package/dist/tools/subagent-task-tool-ui.d.ts +109 -0
- package/dist/tools/subagent-task-tool-ui.js +494 -0
- package/dist/tools/subagent-task-tool-ui.js.map +1 -0
- package/dist/tools/tool-fallback.d.ts +1 -1
- package/dist/tools/tool-icons.d.ts +1 -1
- package/dist/tools/tool-summary.d.ts +1 -1
- package/dist/tools/tool-uis.cjs +4 -0
- package/dist/tools/tool-uis.cjs.map +1 -1
- package/dist/tools/tool-uis.js +4 -0
- package/dist/tools/tool-uis.js.map +1 -1
- package/dist/voice/chat.cjs +6 -0
- package/dist/voice/chat.cjs.map +1 -0
- package/dist/voice/chat.d.ts +2 -0
- package/dist/voice/chat.js +6 -0
- package/dist/voice/chat.js.map +1 -0
- package/dist/voice/livekit-join.cjs +119 -0
- package/dist/voice/livekit-join.cjs.map +1 -0
- package/dist/voice/livekit-join.d.ts +8 -0
- package/dist/voice/livekit-join.js +119 -0
- package/dist/voice/livekit-join.js.map +1 -0
- package/dist/voice/livekit.cjs +32 -0
- package/dist/voice/livekit.cjs.map +1 -0
- package/dist/voice/livekit.d.ts +80 -0
- package/dist/voice/livekit.js +32 -0
- package/dist/voice/livekit.js.map +1 -0
- package/package.json +20 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deep-agent-transport-recipe.js","sources":["../../../../agent-runtime/src/deep-agent-transport-recipe.ts"],"sourcesContent":["import type { ResourceElement } from \"@assistant-ui/tap\";\nimport type { Statewire, StatewireClient } from \"statewire\";\nimport {\n type DeepAgentMessageWindowDeclaration,\n withDeclaredMessageWindow,\n} from \"./message-window\";\nimport { withDeclaredProtocolVersion } from \"./protocol\";\nimport {\n attachRetryGate,\n type AttachRetryGate,\n createAttachInstrumentation,\n type DeepAgentAttachTimingEvent,\n type DeepAgentWakeRefusal,\n parseRetryAfterHeaderMs,\n} from \"./statewire-attach-observer\";\nimport {\n resolveStatewireTransportKind,\n statewireTransport,\n type StatewireTransportOptions,\n} from \"./statewire-transport\";\n\n/** Auth-header resolver for the transport; `staleAuth` is true right after an\n * auth rejection, so resolvers that can force-renew should honor it. */\nexport type DeepAgentHeadersResolver = (ctx: {\n staleAuth: boolean;\n}) => Record<string, string> | Promise<Record<string, string>>;\n\n/** The statewire attach URL for a thread: the host's `…/v2/threads` mount plus the id. */\nexport function deepAgentThreadUrl({\n baseUrl,\n threadId,\n}: {\n baseUrl: string;\n threadId: string;\n}): string {\n return `${baseUrl.replace(/\\/+$/, \"\")}/${encodeURIComponent(threadId)}`;\n}\n\nexport interface DeepAgentAttachTransportOptions {\n /** Base URL of the deep-agent statewire host (the `…/v2/threads` mount). */\n baseUrl: string;\n threadId: string;\n headers: DeepAgentHeadersResolver;\n /** SSE when true, WebSocket otherwise (`resolveStatewireTransportKind`). */\n sse?: boolean;\n /** A never-started chat: the transport makes no network calls until the first command send. */\n isNew?: boolean;\n /** Host session store (mobile); browser hosts mount `storage.session` on the thread instead. */\n sessionStore?: StatewireClient.SessionStorage | undefined;\n /** Observes every headers resolve (the diagnostics recorder's stale-auth seam). */\n onAuthResolve?: ((ctx: { staleAuth: boolean }) => void) | undefined;\n /** Attach timing + retry hints (see `statewire-attach-observer`). */\n onAttachTiming?: ((event: DeepAgentAttachTimingEvent) => void) | undefined;\n /** Dial floors from server retry hints; the process-wide gate by default. */\n retryGate?: AttachRetryGate;\n /**\n * The head window declared on the attach (`x-athena-deep-agent-window`,\n * see `message-window.ts`): the hello of a client the host does not\n * remember carries the newest `size` messages. Part of the recipe so a\n * pooled dial asks for the same shape as the thread's own attach — a pooled\n * hello then seeds the very state the attach will reconcile. Omitted, the\n * shared default is declared.\n */\n messageWindow?: DeepAgentMessageWindowDeclaration | undefined;\n}\n\n/**\n * The ONE recipe for a deep-agent thread transport — shared by the mounted\n * thread (`useDeepAgentThread`) and the prewarm pool, so a pre-dialed\n * connection is byte-for-byte the connection the thread would have opened\n * itself: same URL, same auth + wire-contract headers, same session lane, same\n * instrumentation.\n *\n * Every attach declares this build's wire-contract version alongside the\n * host's auth headers (first WS frame / SSE request headers) — the server\n * half of version negotiation reads it in `authorize`. The headers resolve\n * also waits out any server `Retry-After` floor for the thread: both statewire\n * attach paths resolve headers before they dial, so this is the seam where a\n * hint can hold the next dial without touching the library's backoff.\n */\nexport function createDeepAgentAttachTransport<TState = unknown>({\n baseUrl,\n threadId,\n headers,\n sse = false,\n isNew = false,\n sessionStore,\n onAuthResolve,\n onAttachTiming,\n retryGate = attachRetryGate,\n messageWindow,\n}: DeepAgentAttachTransportOptions): ResourceElement<\n Statewire<TState | undefined>\n> {\n const url = deepAgentThreadUrl({ baseUrl, threadId });\n // The instrumentation wraps the transport actually built: SSE needs the\n // fetch wrapper that reads a refused attach's `Retry-After`.\n const useSse = resolveStatewireTransportKind({ sse }) === \"sse\";\n const instrumentation = createAttachInstrumentation({\n url,\n sse: useSse,\n onEvent: onAttachTiming,\n retryGate,\n });\n const options: StatewireTransportOptions = {\n url,\n ...(isNew && { isNew: true }),\n headers: async (ctx: { staleAuth: boolean }) => {\n await retryGate.waitForDial(url);\n onAuthResolve?.(ctx);\n return withDeclaredMessageWindow(\n withDeclaredProtocolVersion(await headers(ctx)),\n messageWindow,\n );\n },\n ...(sessionStore && { sessionStore }),\n // Structural types: this package compiles without the DOM lib, while\n // statewire's option types name the browser `WebSocket`/`fetch`.\n ...(instrumentation.webSocket && {\n webSocket:\n instrumentation.webSocket as unknown as StatewireTransportOptions[\"webSocket\"],\n }),\n ...(instrumentation.fetch && {\n fetch:\n instrumentation.fetch as unknown as StatewireTransportOptions[\"fetch\"],\n }),\n };\n return statewireTransport<TState>(options, { sse: useSse });\n}\n\n/** What `POST …/prewarm` answered. */\nexport interface DeepAgentWakeResult {\n status: number;\n /** The host activated the thread and its history is resident. */\n warm: boolean;\n /**\n * `'warm'` when the history was already memoized, `'fresh_load'` when this\n * call loaded it; `null` when the host did not say (a refusal, or a host\n * without the route).\n */\n history: \"fresh_load\" | \"warm\" | null;\n /**\n * The dial floor recorded for the thread off a 503/429 `Retry-After` — the\n * header's value, except a 503 `\"worker\"` refusal, capped at\n * {@link WAKE_WORKER_REFUSAL_FLOOR_MS}.\n */\n retryAfterMs: number | null;\n /** Who refused a 503/429 (see {@link DeepAgentWakeRefusal}); `null` for any other answer. */\n refusal: DeepAgentWakeRefusal;\n durationMs: number;\n}\n\n/**\n * Dial floor for a 503 the pinned worker produced about one instance's\n * lifecycle. Pinned answers every retriable 503 with a blanket\n * `Retry-After: 1`, but what those name — an instance record mid-teardown\n * (\"instance closing; retry\": fence release + placement release, ≈100 ms), a\n * full activation queue — clears far sooner than that, and the thread's own\n * attach is the request that carries the next activation. Holding it a full\n * second traded a ≈100 ms gap for a ≈1 s stall on every refused wake. A 429\n * is rate limiting and keeps its hint whatever the body says.\n */\nexport const WAKE_WORKER_REFUSAL_FLOOR_MS = 250;\n\n/**\n * The pinboard's own placement-refusal vocabulary — the `error` strings of\n * `@assistant-ui/pinboard` (`src/refusals.ts` plus the two inline refusals in\n * `src/server.ts`). Mirrors `PINBOARD_PLACEMENT_REFUSAL_ERRORS` in\n * `iris/scaler/src/v2AccessLog.ts`, whose test pins it to the installed\n * library; keep the two lists identical. A body with any other `error`\n * string is `\"unknown\"`, never `\"placement\"`.\n */\nexport const PINBOARD_PLACEMENT_REFUSAL_ERRORS: ReadonlySet<string> = new Set([\n \"no live backends for namespace\",\n \"registry cold start, retry\",\n \"not the serving fleet\",\n \"no live workers for hostname\",\n \"hostname binding displaced, retry\",\n \"hostname bindings inconsistent, retry\",\n \"takeover in progress, retry\",\n \"placement held by another hostname\",\n \"worker inflight cap exceeded, retry\",\n \"worker refused activation, retry\",\n]);\n\n/**\n * Pinned's instance-lifecycle refusals (`pinned/hosting/directory.py`,\n * `pinned/hosting/_records.py`): each names one instance on the worker the\n * thread is already placed on and clears in the time a teardown or an\n * activation slot takes. Anything else the worker answers 503 with — \"Thread\n * history load failed\", \"The regional conversation store is temporarily\n * unavailable\", a lease that expired — is not about one instance and keeps\n * the full hint.\n */\nexport const PINNED_TRANSIENT_WORKER_REFUSALS: ReadonlySet<string> = new Set([\n \"instance closing; retry\",\n \"instance aborted\",\n \"activation queue full; retry\",\n \"host draining; retry\",\n \"instance capacity reached; retry\",\n \"instance past its wind-down deadline; retry\",\n]);\n\n/**\n * Classify a 503/429 body (see {@link DeepAgentWakeRefusal}): a known pinboard\n * `error` is `\"placement\"`, a known pinned `detail` is `\"worker\"`, everything\n * else — including unfamiliar strings in either field — is `\"unknown\"`.\n */\nexport function classifyWakeRefusal(\n body: unknown,\n): Exclude<DeepAgentWakeRefusal, null> {\n if (typeof body === \"object\" && body !== null) {\n const record = body as Record<string, unknown>;\n if (\n typeof record.error === \"string\" &&\n PINBOARD_PLACEMENT_REFUSAL_ERRORS.has(record.error)\n ) {\n return \"placement\";\n }\n if (\n typeof record.detail === \"string\" &&\n PINNED_TRANSIENT_WORKER_REFUSALS.has(record.detail)\n ) {\n return \"worker\";\n }\n }\n return \"unknown\";\n}\n\n/** Structural `fetch` for the wake call — this package compiles without the DOM lib. */\nexport type DeepAgentWakeFetch = (\n input: string,\n init?: {\n method?: string;\n headers?: Record<string, string>;\n keepalive?: boolean;\n },\n) => Promise<{\n ok: boolean;\n status: number;\n headers: { get(name: string): string | null };\n json(): Promise<unknown>;\n}>;\n\nexport interface DeepAgentWakeOptions {\n /** Base URL of the deep-agent statewire host (the `…/v2/threads` mount). */\n baseUrl: string;\n threadId: string;\n headers: DeepAgentHeadersResolver;\n fetch?: DeepAgentWakeFetch | undefined;\n /** Dial floors from server retry hints; the process-wide gate by default. */\n retryGate?: AttachRetryGate;\n onAttachTiming?: ((event: DeepAgentAttachTimingEvent) => void) | undefined;\n now?: () => number;\n}\n\n/**\n * Wake a thread's server instance ahead of its attach. `POST …/prewarm` runs\n * the host's `authorize` and history load — the fence adopt, graph compile and\n * checkpoint read that make a cold attach's hello take ≈1 s — and answers with\n * no thread content, only whether the history was already resident. Fire it\n * on hover intent, before a pooled attach or the click's own dial, so the\n * activation overlaps the handshake and the attach that follows finds the\n * instance warm.\n *\n * Fire-and-forget by contract: every failure resolves `null`, and a host\n * without the route (404) is reported like any other non-OK answer. A 503/429\n * `Retry-After` is recorded as a dial floor for the thread, so the attach that\n * follows waits it out instead of bouncing — in full, except a 503 that names\n * one of pinned's instance-lifecycle refusals (one instance mid-teardown on\n * the worker the thread already has; see {@link DeepAgentWakeRefusal}), whose\n * floor is capped at {@link WAKE_WORKER_REFUSAL_FLOOR_MS}.\n */\nexport async function wakeDeepAgentThread({\n baseUrl,\n threadId,\n headers,\n fetch: fetchOverride,\n retryGate = attachRetryGate,\n onAttachTiming,\n now = () => Date.now(),\n}: DeepAgentWakeOptions): Promise<DeepAgentWakeResult | null> {\n const fetchImpl =\n fetchOverride ?? (globalThis as { fetch?: DeepAgentWakeFetch }).fetch;\n if (typeof fetchImpl !== \"function\") return null;\n const threadUrl = deepAgentThreadUrl({ baseUrl, threadId });\n const emit = (event: DeepAgentAttachTimingEvent): void => {\n try {\n onAttachTiming?.(event);\n } catch {\n // Observers are best-effort.\n }\n };\n const startedAt = now();\n try {\n const resolved = withDeclaredProtocolVersion(\n await headers({ staleAuth: false }),\n );\n const response = await fetchImpl(`${threadUrl}/prewarm`, {\n method: \"POST\",\n headers: resolved,\n keepalive: true,\n });\n const durationMs = now() - startedAt;\n let retryAfterMs: number | null = null;\n let refusal: DeepAgentWakeRefusal = null;\n if (response.status === 503 || response.status === 429) {\n let body: unknown = null;\n try {\n body = await response.json();\n } catch {\n // A refusal without a readable body is classified by nothing.\n }\n refusal = classifyWakeRefusal(body);\n const hinted = parseRetryAfterHeaderMs(\n response.headers.get(\"retry-after\"),\n now,\n );\n if (hinted !== null) {\n retryAfterMs =\n response.status === 503 && refusal === \"worker\"\n ? Math.min(hinted, WAKE_WORKER_REFUSAL_FLOOR_MS)\n : hinted;\n if (retryAfterMs > 0) {\n retryGate.noteRetryAfter(threadUrl, retryAfterMs);\n emit({\n type: \"retry-after\",\n url: threadUrl,\n delayMs: retryAfterMs,\n source: \"http-header\",\n });\n }\n }\n }\n let warm = false;\n let history: DeepAgentWakeResult[\"history\"] = null;\n if (response.ok) {\n try {\n const body = (await response.json()) as {\n warm?: unknown;\n history?: unknown;\n } | null;\n warm = body?.warm === true;\n history =\n body?.history === \"warm\" || body?.history === \"fresh_load\"\n ? body.history\n : null;\n } catch {\n // A 200 without a JSON body still means the instance is up.\n warm = true;\n }\n }\n emit({\n type: \"wake\",\n url: threadUrl,\n status: response.status,\n durationMs,\n history,\n refusal,\n });\n return {\n status: response.status,\n warm,\n history,\n retryAfterMs,\n refusal,\n durationMs,\n };\n } catch {\n return null;\n }\n}\n"],"names":[],"mappings":";;;;AA4BO,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AACF,GAGW;AACT,SAAO,GAAG,QAAQ,QAAQ,QAAQ,EAAE,CAAC,IAAI,mBAAmB,QAAQ,CAAC;AACvE;AA4CO,SAAS,+BAAiD;AAAA,EAC/D;AAAA,EACA;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ;AACF,GAEE;AACA,QAAM,MAAM,mBAAmB,EAAE,SAAS,UAAU;AAGpD,QAAM,SAAS,8BAA8B,EAAE,IAAA,CAAK,MAAM;AAC1D,QAAM,kBAAkB,4BAA4B;AAAA,IAClD;AAAA,IACA,KAAK;AAAA,IACL,SAAS;AAAA,IACT;AAAA,EAAA,CACD;AACD,QAAM,UAAqC;AAAA,IACzC;AAAA,IACA,GAAI,SAAS,EAAE,OAAO,KAAA;AAAA,IACtB,SAAS,OAAO,QAAgC;AAC9C,YAAM,UAAU,YAAY,GAAG;AAC/B,qDAAgB;AAChB,aAAO;AAAA,QACL,4BAA4B,MAAM,QAAQ,GAAG,CAAC;AAAA,QAC9C;AAAA,MAAA;AAAA,IAEJ;AAAA,IACA,GAAI,gBAAgB,EAAE,aAAA;AAAA;AAAA;AAAA,IAGtB,GAAI,gBAAgB,aAAa;AAAA,MAC/B,WACE,gBAAgB;AAAA,IAAA;AAAA,IAEpB,GAAI,gBAAgB,SAAS;AAAA,MAC3B,OACE,gBAAgB;AAAA,IAAA;AAAA,EACpB;AAEF,SAAO,mBAA2B,SAAS,EAAE,KAAK,QAAQ;AAC5D;"}
|
|
1
|
+
{"version":3,"file":"deep-agent-transport-recipe.js","sources":["../../../../agent-runtime/src/deep-agent-transport-recipe.ts"],"sourcesContent":["import type { ResourceElement } from \"@assistant-ui/tap\";\nimport type { Statewire, StatewireClient } from \"statewire\";\nimport {\n type DeepAgentMessageWindowDeclaration,\n withDeclaredMessageWindow,\n} from \"./message-window\";\nimport { withDeclaredProtocolVersion } from \"./protocol\";\nimport {\n attachRetryGate,\n type AttachRetryGate,\n createAttachInstrumentation,\n type DeepAgentAttachTimingEvent,\n type DeepAgentWakeRefusal,\n parseRetryAfterHeaderMs,\n} from \"./statewire-attach-observer\";\nimport {\n resolveStatewireTransportKind,\n statewireTransport,\n type StatewireTransportOptions,\n} from \"./statewire-transport\";\n\n/** Auth-header resolver for the transport; `staleAuth` is true right after an\n * auth rejection, so resolvers that can force-renew should honor it. */\nexport type DeepAgentHeadersResolver = (ctx: {\n staleAuth: boolean;\n}) => Record<string, string> | Promise<Record<string, string>>;\n\n/** The statewire attach URL for a thread: the host's `…/v2/threads` mount plus the id. */\nexport function deepAgentThreadUrl({\n baseUrl,\n threadId,\n}: {\n baseUrl: string;\n threadId: string;\n}): string {\n return `${baseUrl.replace(/\\/+$/, \"\")}/${encodeURIComponent(threadId)}`;\n}\n\nexport interface DeepAgentAttachTransportOptions {\n /** Base URL of the deep-agent statewire host (the `…/v2/threads` mount). */\n baseUrl: string;\n threadId: string;\n headers: DeepAgentHeadersResolver;\n /** SSE when true, WebSocket otherwise (`resolveStatewireTransportKind`). */\n sse?: boolean;\n /** A never-started chat: the transport makes no network calls until the first command send. */\n isNew?: boolean;\n /** Host session store (mobile); browser hosts mount `storage.session` on the thread instead. */\n sessionStore?: StatewireClient.SessionStorage | undefined;\n /** Observes every headers resolve (the diagnostics recorder's stale-auth seam). */\n onAuthResolve?: ((ctx: { staleAuth: boolean }) => void) | undefined;\n /** Attach timing + retry hints (see `statewire-attach-observer`). */\n onAttachTiming?: ((event: DeepAgentAttachTimingEvent) => void) | undefined;\n /** Dial floors from server retry hints; the process-wide gate by default. */\n retryGate?: AttachRetryGate;\n /**\n * The head window declared on the attach (`x-athena-deep-agent-window`,\n * see `message-window.ts`): the hello of a client the host does not\n * remember carries the newest `size` messages. Part of the recipe so a\n * pooled dial asks for the same shape as the thread's own attach — a pooled\n * hello then seeds the very state the attach will reconcile. Omitted, the\n * shared default is declared.\n */\n messageWindow?: DeepAgentMessageWindowDeclaration | undefined;\n /**\n * The surface pages cut lanes (see `DeepAgentProtocolDeclaration`), so its\n * attach declares the lane-cut contract version. Part of the recipe so a\n * pooled dial declares what the thread's own attach would; omitted, the\n * default version is declared.\n */\n laneHistory?: boolean | undefined;\n}\n\n/**\n * The ONE recipe for a deep-agent thread transport — shared by the mounted\n * thread (`useDeepAgentThread`) and the prewarm pool, so a pre-dialed\n * connection is byte-for-byte the connection the thread would have opened\n * itself: same URL, same auth + wire-contract headers, same session lane, same\n * instrumentation.\n *\n * Every attach declares the surface's wire-contract version alongside the\n * host's auth headers (first WS frame / SSE request headers) — the server\n * half of version negotiation reads it in `authorize`. The headers resolve\n * also waits out any server `Retry-After` floor for the thread: both statewire\n * attach paths resolve headers before they dial, so this is the seam where a\n * hint can hold the next dial without touching the library's backoff.\n */\nexport function createDeepAgentAttachTransport<TState = unknown>({\n baseUrl,\n threadId,\n headers,\n sse = false,\n isNew = false,\n sessionStore,\n onAuthResolve,\n onAttachTiming,\n retryGate = attachRetryGate,\n messageWindow,\n laneHistory = false,\n}: DeepAgentAttachTransportOptions): ResourceElement<\n Statewire<TState | undefined>\n> {\n const url = deepAgentThreadUrl({ baseUrl, threadId });\n // The instrumentation wraps the transport actually built: SSE needs the\n // fetch wrapper that reads a refused attach's `Retry-After`.\n const useSse = resolveStatewireTransportKind({ sse }) === \"sse\";\n const instrumentation = createAttachInstrumentation({\n url,\n sse: useSse,\n onEvent: onAttachTiming,\n retryGate,\n });\n const options: StatewireTransportOptions = {\n url,\n ...(isNew && { isNew: true }),\n headers: async (ctx: { staleAuth: boolean }) => {\n await retryGate.waitForDial(url);\n onAuthResolve?.(ctx);\n return withDeclaredMessageWindow(\n withDeclaredProtocolVersion(await headers(ctx), { laneHistory }),\n messageWindow,\n );\n },\n ...(sessionStore && { sessionStore }),\n // Structural types: this package compiles without the DOM lib, while\n // statewire's option types name the browser `WebSocket`/`fetch`.\n ...(instrumentation.webSocket && {\n webSocket:\n instrumentation.webSocket as unknown as StatewireTransportOptions[\"webSocket\"],\n }),\n ...(instrumentation.fetch && {\n fetch:\n instrumentation.fetch as unknown as StatewireTransportOptions[\"fetch\"],\n }),\n };\n return statewireTransport<TState>(options, { sse: useSse });\n}\n\n/** What `POST …/prewarm` answered. */\nexport interface DeepAgentWakeResult {\n status: number;\n /** The host activated the thread and its history is resident. */\n warm: boolean;\n /**\n * `'warm'` when the history was already memoized, `'fresh_load'` when this\n * call loaded it; `null` when the host did not say (a refusal, or a host\n * without the route).\n */\n history: \"fresh_load\" | \"warm\" | null;\n /**\n * The dial floor recorded for the thread off a 503/429 `Retry-After` — the\n * header's value, except a 503 `\"worker\"` refusal, capped at\n * {@link WAKE_WORKER_REFUSAL_FLOOR_MS}.\n */\n retryAfterMs: number | null;\n /** Who refused a 503/429 (see {@link DeepAgentWakeRefusal}); `null` for any other answer. */\n refusal: DeepAgentWakeRefusal;\n durationMs: number;\n}\n\n/**\n * Dial floor for a 503 the pinned worker produced about one instance's\n * lifecycle. Pinned answers every retriable 503 with a blanket\n * `Retry-After: 1`, but what those name — an instance record mid-teardown\n * (\"instance closing; retry\": fence release + placement release, ≈100 ms), a\n * full activation queue — clears far sooner than that, and the thread's own\n * attach is the request that carries the next activation. Holding it a full\n * second traded a ≈100 ms gap for a ≈1 s stall on every refused wake. A 429\n * is rate limiting and keeps its hint whatever the body says.\n */\nexport const WAKE_WORKER_REFUSAL_FLOOR_MS = 250;\n\n/**\n * The pinboard's own placement-refusal vocabulary — the `error` strings of\n * `@assistant-ui/pinboard` (`src/refusals.ts` plus the two inline refusals in\n * `src/server.ts`). Mirrors `PINBOARD_PLACEMENT_REFUSAL_ERRORS` in\n * `iris/scaler/src/v2AccessLog.ts`, whose test pins it to the installed\n * library; keep the two lists identical. A body with any other `error`\n * string is `\"unknown\"`, never `\"placement\"`.\n */\nexport const PINBOARD_PLACEMENT_REFUSAL_ERRORS: ReadonlySet<string> = new Set([\n \"no live backends for namespace\",\n \"registry cold start, retry\",\n \"not the serving fleet\",\n \"no live workers for hostname\",\n \"hostname binding displaced, retry\",\n \"hostname bindings inconsistent, retry\",\n \"takeover in progress, retry\",\n \"placement held by another hostname\",\n \"worker inflight cap exceeded, retry\",\n \"worker refused activation, retry\",\n]);\n\n/**\n * Pinned's instance-lifecycle refusals (`pinned/hosting/directory.py`,\n * `pinned/hosting/_records.py`): each names one instance on the worker the\n * thread is already placed on and clears in the time a teardown or an\n * activation slot takes. Anything else the worker answers 503 with — \"Thread\n * history load failed\", \"The regional conversation store is temporarily\n * unavailable\", a lease that expired — is not about one instance and keeps\n * the full hint.\n */\nexport const PINNED_TRANSIENT_WORKER_REFUSALS: ReadonlySet<string> = new Set([\n \"instance closing; retry\",\n \"instance aborted\",\n \"activation queue full; retry\",\n \"host draining; retry\",\n \"instance capacity reached; retry\",\n \"instance past its wind-down deadline; retry\",\n]);\n\n/**\n * Classify a 503/429 body (see {@link DeepAgentWakeRefusal}): a known pinboard\n * `error` is `\"placement\"`, a known pinned `detail` is `\"worker\"`, everything\n * else — including unfamiliar strings in either field — is `\"unknown\"`.\n */\nexport function classifyWakeRefusal(\n body: unknown,\n): Exclude<DeepAgentWakeRefusal, null> {\n if (typeof body === \"object\" && body !== null) {\n const record = body as Record<string, unknown>;\n if (\n typeof record.error === \"string\" &&\n PINBOARD_PLACEMENT_REFUSAL_ERRORS.has(record.error)\n ) {\n return \"placement\";\n }\n if (\n typeof record.detail === \"string\" &&\n PINNED_TRANSIENT_WORKER_REFUSALS.has(record.detail)\n ) {\n return \"worker\";\n }\n }\n return \"unknown\";\n}\n\n/** Structural `fetch` for the wake call — this package compiles without the DOM lib. */\nexport type DeepAgentWakeFetch = (\n input: string,\n init?: {\n method?: string;\n headers?: Record<string, string>;\n keepalive?: boolean;\n },\n) => Promise<{\n ok: boolean;\n status: number;\n headers: { get(name: string): string | null };\n json(): Promise<unknown>;\n}>;\n\nexport interface DeepAgentWakeOptions {\n /** Base URL of the deep-agent statewire host (the `…/v2/threads` mount). */\n baseUrl: string;\n threadId: string;\n headers: DeepAgentHeadersResolver;\n fetch?: DeepAgentWakeFetch | undefined;\n /** Dial floors from server retry hints; the process-wide gate by default. */\n retryGate?: AttachRetryGate;\n onAttachTiming?: ((event: DeepAgentAttachTimingEvent) => void) | undefined;\n now?: () => number;\n /** The surface pages cut lanes: declare what its attach declares (see `DeepAgentAttachTransportOptions`). */\n laneHistory?: boolean | undefined;\n}\n\n/**\n * Wake a thread's server instance ahead of its attach. `POST …/prewarm` runs\n * the host's `authorize` and history load — the fence adopt, graph compile and\n * checkpoint read that make a cold attach's hello take ≈1 s — and answers with\n * no thread content, only whether the history was already resident. Fire it\n * on hover intent, before a pooled attach or the click's own dial, so the\n * activation overlaps the handshake and the attach that follows finds the\n * instance warm.\n *\n * Fire-and-forget by contract: every failure resolves `null`, and a host\n * without the route (404) is reported like any other non-OK answer. A 503/429\n * `Retry-After` is recorded as a dial floor for the thread, so the attach that\n * follows waits it out instead of bouncing — in full, except a 503 that names\n * one of pinned's instance-lifecycle refusals (one instance mid-teardown on\n * the worker the thread already has; see {@link DeepAgentWakeRefusal}), whose\n * floor is capped at {@link WAKE_WORKER_REFUSAL_FLOOR_MS}.\n */\nexport async function wakeDeepAgentThread({\n baseUrl,\n threadId,\n headers,\n fetch: fetchOverride,\n retryGate = attachRetryGate,\n onAttachTiming,\n now = () => Date.now(),\n laneHistory = false,\n}: DeepAgentWakeOptions): Promise<DeepAgentWakeResult | null> {\n const fetchImpl =\n fetchOverride ?? (globalThis as { fetch?: DeepAgentWakeFetch }).fetch;\n if (typeof fetchImpl !== \"function\") return null;\n const threadUrl = deepAgentThreadUrl({ baseUrl, threadId });\n const emit = (event: DeepAgentAttachTimingEvent): void => {\n try {\n onAttachTiming?.(event);\n } catch {\n // Observers are best-effort.\n }\n };\n const startedAt = now();\n try {\n const resolved = withDeclaredProtocolVersion(\n await headers({ staleAuth: false }),\n { laneHistory },\n );\n const response = await fetchImpl(`${threadUrl}/prewarm`, {\n method: \"POST\",\n headers: resolved,\n keepalive: true,\n });\n const durationMs = now() - startedAt;\n let retryAfterMs: number | null = null;\n let refusal: DeepAgentWakeRefusal = null;\n if (response.status === 503 || response.status === 429) {\n let body: unknown = null;\n try {\n body = await response.json();\n } catch {\n // A refusal without a readable body is classified by nothing.\n }\n refusal = classifyWakeRefusal(body);\n const hinted = parseRetryAfterHeaderMs(\n response.headers.get(\"retry-after\"),\n now,\n );\n if (hinted !== null) {\n retryAfterMs =\n response.status === 503 && refusal === \"worker\"\n ? Math.min(hinted, WAKE_WORKER_REFUSAL_FLOOR_MS)\n : hinted;\n if (retryAfterMs > 0) {\n retryGate.noteRetryAfter(threadUrl, retryAfterMs);\n emit({\n type: \"retry-after\",\n url: threadUrl,\n delayMs: retryAfterMs,\n source: \"http-header\",\n });\n }\n }\n }\n let warm = false;\n let history: DeepAgentWakeResult[\"history\"] = null;\n if (response.ok) {\n try {\n const body = (await response.json()) as {\n warm?: unknown;\n history?: unknown;\n } | null;\n warm = body?.warm === true;\n history =\n body?.history === \"warm\" || body?.history === \"fresh_load\"\n ? body.history\n : null;\n } catch {\n // A 200 without a JSON body still means the instance is up.\n warm = true;\n }\n }\n emit({\n type: \"wake\",\n url: threadUrl,\n status: response.status,\n durationMs,\n history,\n refusal,\n });\n return {\n status: response.status,\n warm,\n history,\n retryAfterMs,\n refusal,\n durationMs,\n };\n } catch {\n return null;\n }\n}\n"],"names":[],"mappings":";;;;AA4BO,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA;AACF,GAGW;AACT,SAAO,GAAG,QAAQ,QAAQ,QAAQ,EAAE,CAAC,IAAI,mBAAmB,QAAQ,CAAC;AACvE;AAmDO,SAAS,+BAAiD;AAAA,EAC/D;AAAA,EACA;AAAA,EACA;AAAA,EACA,MAAM;AAAA,EACN,QAAQ;AAAA,EACR;AAAA,EACA;AAAA,EACA;AAAA,EACA,YAAY;AAAA,EACZ;AAAA,EACA,cAAc;AAChB,GAEE;AACA,QAAM,MAAM,mBAAmB,EAAE,SAAS,UAAU;AAGpD,QAAM,SAAS,8BAA8B,EAAE,IAAA,CAAK,MAAM;AAC1D,QAAM,kBAAkB,4BAA4B;AAAA,IAClD;AAAA,IACA,KAAK;AAAA,IACL,SAAS;AAAA,IACT;AAAA,EAAA,CACD;AACD,QAAM,UAAqC;AAAA,IACzC;AAAA,IACA,GAAI,SAAS,EAAE,OAAO,KAAA;AAAA,IACtB,SAAS,OAAO,QAAgC;AAC9C,YAAM,UAAU,YAAY,GAAG;AAC/B,qDAAgB;AAChB,aAAO;AAAA,QACL,4BAA4B,MAAM,QAAQ,GAAG,GAAG,EAAE,aAAa;AAAA,QAC/D;AAAA,MAAA;AAAA,IAEJ;AAAA,IACA,GAAI,gBAAgB,EAAE,aAAA;AAAA;AAAA;AAAA,IAGtB,GAAI,gBAAgB,aAAa;AAAA,MAC/B,WACE,gBAAgB;AAAA,IAAA;AAAA,IAEpB,GAAI,gBAAgB,SAAS;AAAA,MAC3B,OACE,gBAAgB;AAAA,IAAA;AAAA,EACpB;AAEF,SAAO,mBAA2B,SAAS,EAAE,KAAK,QAAQ;AAC5D;"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/** Authenticated desktop handoffs carry references, never document/chat contents or credentials. */
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
export declare const DESKTOP_HANDOFF_PROTOCOL_VERSION: 1;
|
|
4
|
+
export declare const DESKTOP_HANDOFF_MAX_ASSETS = 50;
|
|
5
|
+
export declare const desktopHandoffAssetSchema: z.ZodObject<{
|
|
6
|
+
asset_id: z.ZodString;
|
|
7
|
+
reference: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
8
|
+
}, z.core.$strip>;
|
|
9
|
+
export type DesktopHandoffAsset = z.infer<typeof desktopHandoffAssetSchema>;
|
|
10
|
+
export declare const desktopHandoffResultSchema: z.ZodObject<{
|
|
11
|
+
desktop_version: z.ZodString;
|
|
12
|
+
protocol_version: z.ZodLiteral<1>;
|
|
13
|
+
thread_opened: z.ZodBoolean;
|
|
14
|
+
assets: z.ZodArray<z.ZodObject<{
|
|
15
|
+
asset_id: z.ZodString;
|
|
16
|
+
status: z.ZodEnum<{
|
|
17
|
+
failed: "failed";
|
|
18
|
+
opened: "opened";
|
|
19
|
+
web_fallback: "web_fallback";
|
|
20
|
+
}>;
|
|
21
|
+
reason: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
22
|
+
}, z.core.$strip>>;
|
|
23
|
+
}, z.core.$strip>;
|
|
24
|
+
export type DesktopHandoffResult = z.infer<typeof desktopHandoffResultSchema>;
|
|
25
|
+
export declare const desktopHandoffViewSchema: z.ZodObject<{
|
|
26
|
+
handoff_id: z.ZodString;
|
|
27
|
+
thread_id: z.ZodNullable<z.ZodString>;
|
|
28
|
+
session_asset_id: z.ZodNullable<z.ZodString>;
|
|
29
|
+
source: z.ZodLiteral<"spaces">;
|
|
30
|
+
destination: z.ZodLiteral<"desktop">;
|
|
31
|
+
environment: z.ZodEnum<{
|
|
32
|
+
localhost: "localhost";
|
|
33
|
+
production: "production";
|
|
34
|
+
staging: "staging";
|
|
35
|
+
}>;
|
|
36
|
+
state: z.ZodEnum<{
|
|
37
|
+
acknowledged: "acknowledged";
|
|
38
|
+
claimed: "claimed";
|
|
39
|
+
failed: "failed";
|
|
40
|
+
issued: "issued";
|
|
41
|
+
launched: "launched";
|
|
42
|
+
}>;
|
|
43
|
+
issued_at: z.ZodISODateTime;
|
|
44
|
+
expires_at: z.ZodISODateTime;
|
|
45
|
+
claimed_at: z.ZodNullable<z.ZodISODateTime>;
|
|
46
|
+
acknowledged_at: z.ZodNullable<z.ZodISODateTime>;
|
|
47
|
+
failure_reason: z.ZodNullable<z.ZodString>;
|
|
48
|
+
assets: z.ZodArray<z.ZodObject<{
|
|
49
|
+
asset_id: z.ZodString;
|
|
50
|
+
reference: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
51
|
+
}, z.core.$strip>>;
|
|
52
|
+
active_asset_id: z.ZodNullable<z.ZodString>;
|
|
53
|
+
result: z.ZodNullable<z.ZodObject<{
|
|
54
|
+
desktop_version: z.ZodString;
|
|
55
|
+
protocol_version: z.ZodLiteral<1>;
|
|
56
|
+
thread_opened: z.ZodBoolean;
|
|
57
|
+
assets: z.ZodArray<z.ZodObject<{
|
|
58
|
+
asset_id: z.ZodString;
|
|
59
|
+
status: z.ZodEnum<{
|
|
60
|
+
failed: "failed";
|
|
61
|
+
opened: "opened";
|
|
62
|
+
web_fallback: "web_fallback";
|
|
63
|
+
}>;
|
|
64
|
+
reason: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
65
|
+
}, z.core.$strip>>;
|
|
66
|
+
}, z.core.$strip>>;
|
|
67
|
+
}, z.core.$strip>;
|
|
68
|
+
export type DesktopHandoffView = z.infer<typeof desktopHandoffViewSchema>;
|
|
69
|
+
export declare const desktopHandoffLaunchSchema: z.ZodObject<{
|
|
70
|
+
kind: z.ZodLiteral<"desktop">;
|
|
71
|
+
scheme_url: z.ZodString;
|
|
72
|
+
download_url: z.ZodURL;
|
|
73
|
+
deployment_url: z.ZodURL;
|
|
74
|
+
protocol_version: z.ZodLiteral<1>;
|
|
75
|
+
}, z.core.$strip>;
|
|
76
|
+
export type DesktopHandoffLaunch = z.infer<typeof desktopHandoffLaunchSchema>;
|
|
77
|
+
export declare const createDesktopHandoffResponseSchema: z.ZodObject<{
|
|
78
|
+
handoff: z.ZodObject<{
|
|
79
|
+
handoff_id: z.ZodString;
|
|
80
|
+
thread_id: z.ZodNullable<z.ZodString>;
|
|
81
|
+
session_asset_id: z.ZodNullable<z.ZodString>;
|
|
82
|
+
source: z.ZodLiteral<"spaces">;
|
|
83
|
+
destination: z.ZodLiteral<"desktop">;
|
|
84
|
+
environment: z.ZodEnum<{
|
|
85
|
+
localhost: "localhost";
|
|
86
|
+
production: "production";
|
|
87
|
+
staging: "staging";
|
|
88
|
+
}>;
|
|
89
|
+
state: z.ZodEnum<{
|
|
90
|
+
acknowledged: "acknowledged";
|
|
91
|
+
claimed: "claimed";
|
|
92
|
+
failed: "failed";
|
|
93
|
+
issued: "issued";
|
|
94
|
+
launched: "launched";
|
|
95
|
+
}>;
|
|
96
|
+
issued_at: z.ZodISODateTime;
|
|
97
|
+
expires_at: z.ZodISODateTime;
|
|
98
|
+
claimed_at: z.ZodNullable<z.ZodISODateTime>;
|
|
99
|
+
acknowledged_at: z.ZodNullable<z.ZodISODateTime>;
|
|
100
|
+
failure_reason: z.ZodNullable<z.ZodString>;
|
|
101
|
+
assets: z.ZodArray<z.ZodObject<{
|
|
102
|
+
asset_id: z.ZodString;
|
|
103
|
+
reference: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
104
|
+
}, z.core.$strip>>;
|
|
105
|
+
active_asset_id: z.ZodNullable<z.ZodString>;
|
|
106
|
+
result: z.ZodNullable<z.ZodObject<{
|
|
107
|
+
desktop_version: z.ZodString;
|
|
108
|
+
protocol_version: z.ZodLiteral<1>;
|
|
109
|
+
thread_opened: z.ZodBoolean;
|
|
110
|
+
assets: z.ZodArray<z.ZodObject<{
|
|
111
|
+
asset_id: z.ZodString;
|
|
112
|
+
status: z.ZodEnum<{
|
|
113
|
+
failed: "failed";
|
|
114
|
+
opened: "opened";
|
|
115
|
+
web_fallback: "web_fallback";
|
|
116
|
+
}>;
|
|
117
|
+
reason: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
118
|
+
}, z.core.$strip>>;
|
|
119
|
+
}, z.core.$strip>>;
|
|
120
|
+
}, z.core.$strip>;
|
|
121
|
+
launch: z.ZodObject<{
|
|
122
|
+
kind: z.ZodLiteral<"desktop">;
|
|
123
|
+
scheme_url: z.ZodString;
|
|
124
|
+
download_url: z.ZodURL;
|
|
125
|
+
deployment_url: z.ZodURL;
|
|
126
|
+
protocol_version: z.ZodLiteral<1>;
|
|
127
|
+
}, z.core.$strip>;
|
|
128
|
+
}, z.core.$strip>;
|
|
129
|
+
export type CreateDesktopHandoffResponse = z.infer<typeof createDesktopHandoffResponseSchema>;
|
|
130
|
+
export interface CreateDesktopHandoffInput {
|
|
131
|
+
thread_id?: string | null;
|
|
132
|
+
assets: DesktopHandoffAsset[];
|
|
133
|
+
active_asset_id?: string | null;
|
|
134
|
+
source: "spaces";
|
|
135
|
+
}
|
|
136
|
+
/** Only a destination acknowledgement proves a launch. Timeouts prove no installation state. */
|
|
137
|
+
export declare function desktopHandoffSummary({ handoff, }: {
|
|
138
|
+
handoff: DesktopHandoffView;
|
|
139
|
+
}): string;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const threadSnapshotCache = require("./thread-snapshot-cache.cjs");
|
|
4
|
+
const threadSnapshotMirror = require("./thread-snapshot-mirror.cjs");
|
|
5
|
+
const DEFAULT_MAX_THREADS = 30;
|
|
6
|
+
const OFFLINE_SNAPSHOT_MAX_AGE_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
7
|
+
function browserOffline() {
|
|
8
|
+
var _a;
|
|
9
|
+
const host = globalThis;
|
|
10
|
+
return ((_a = host.navigator) == null ? void 0 : _a.onLine) === false;
|
|
11
|
+
}
|
|
12
|
+
function createDurableThreadSnapshotCache({
|
|
13
|
+
mirror,
|
|
14
|
+
isOffline = browserOffline,
|
|
15
|
+
maxThreads = DEFAULT_MAX_THREADS,
|
|
16
|
+
maxAgeMs,
|
|
17
|
+
offlineMaxAgeMs = OFFLINE_SNAPSHOT_MAX_AGE_MS,
|
|
18
|
+
now = () => Date.now()
|
|
19
|
+
}) {
|
|
20
|
+
let ownerId = null;
|
|
21
|
+
let epoch = 0;
|
|
22
|
+
let primed = null;
|
|
23
|
+
let hydration = Promise.resolve();
|
|
24
|
+
const offline = /* @__PURE__ */ new Map();
|
|
25
|
+
const offlineSeeds = /* @__PURE__ */ new Map();
|
|
26
|
+
const restored = /* @__PURE__ */ new Set();
|
|
27
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
28
|
+
const notify = () => {
|
|
29
|
+
for (const listener of listeners) {
|
|
30
|
+
try {
|
|
31
|
+
listener();
|
|
32
|
+
} catch {
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
const clearOfflineSeed = (threadId) => {
|
|
37
|
+
if (offlineSeeds.delete(threadId)) notify();
|
|
38
|
+
};
|
|
39
|
+
const keepOffline = (threadId, entry) => {
|
|
40
|
+
offline.delete(threadId);
|
|
41
|
+
offline.set(threadId, entry);
|
|
42
|
+
while (offline.size > maxThreads) {
|
|
43
|
+
const oldest = offline.keys().next().value;
|
|
44
|
+
if (oldest === void 0) break;
|
|
45
|
+
offline.delete(oldest);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
const memory = threadSnapshotCache.createDeepAgentThreadSnapshotCache({
|
|
49
|
+
maxThreads,
|
|
50
|
+
maxAgeMs,
|
|
51
|
+
now,
|
|
52
|
+
onChange: (change) => {
|
|
53
|
+
const owner = ownerId;
|
|
54
|
+
if (owner === null) return;
|
|
55
|
+
switch (change.type) {
|
|
56
|
+
case "remember":
|
|
57
|
+
mirror.write({ ownerId: owner, threadId: change.threadId, state: change.state, at: change.at });
|
|
58
|
+
return;
|
|
59
|
+
case "forget":
|
|
60
|
+
mirror.remove({ ownerId: owner, threadId: change.threadId });
|
|
61
|
+
return;
|
|
62
|
+
case "clear":
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
const offlineEntry = (threadId) => {
|
|
68
|
+
const entry = offline.get(threadId);
|
|
69
|
+
return entry && now() - entry.at <= offlineMaxAgeMs ? entry : void 0;
|
|
70
|
+
};
|
|
71
|
+
const dropEverything = () => {
|
|
72
|
+
memory.clear();
|
|
73
|
+
offline.clear();
|
|
74
|
+
restored.clear();
|
|
75
|
+
if (offlineSeeds.size > 0) {
|
|
76
|
+
offlineSeeds.clear();
|
|
77
|
+
notify();
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
return {
|
|
81
|
+
remember(threadId, state) {
|
|
82
|
+
memory.remember(threadId, state);
|
|
83
|
+
restored.delete(threadId);
|
|
84
|
+
if (threadSnapshotMirror.isRestingThreadSnapshot(state)) keepOffline(threadId, { state, at: now() });
|
|
85
|
+
clearOfflineSeed(threadId);
|
|
86
|
+
},
|
|
87
|
+
take(threadId) {
|
|
88
|
+
if (!isOffline()) return memory.take(threadId);
|
|
89
|
+
const entry = offlineEntry(threadId);
|
|
90
|
+
if (!entry) return void 0;
|
|
91
|
+
if (offlineSeeds.get(threadId) !== entry.at) {
|
|
92
|
+
offlineSeeds.set(threadId, entry.at);
|
|
93
|
+
notify();
|
|
94
|
+
}
|
|
95
|
+
return entry.state;
|
|
96
|
+
},
|
|
97
|
+
peek(threadId) {
|
|
98
|
+
return isOffline() ? offlineEntry(threadId) !== void 0 : memory.peek(threadId);
|
|
99
|
+
},
|
|
100
|
+
forget(threadId) {
|
|
101
|
+
memory.forget(threadId);
|
|
102
|
+
offline.delete(threadId);
|
|
103
|
+
restored.delete(threadId);
|
|
104
|
+
clearOfflineSeed(threadId);
|
|
105
|
+
},
|
|
106
|
+
clear() {
|
|
107
|
+
dropEverything();
|
|
108
|
+
},
|
|
109
|
+
owner: () => ownerId,
|
|
110
|
+
setOwner(next) {
|
|
111
|
+
if (next === ownerId) return hydration;
|
|
112
|
+
const previous = ownerId;
|
|
113
|
+
ownerId = next;
|
|
114
|
+
epoch += 1;
|
|
115
|
+
dropEverything();
|
|
116
|
+
if (previous !== null) void mirror.clearOwner(previous);
|
|
117
|
+
if (next === null) {
|
|
118
|
+
hydration = Promise.resolve();
|
|
119
|
+
return hydration;
|
|
120
|
+
}
|
|
121
|
+
const readEpoch = epoch;
|
|
122
|
+
const read = (primed == null ? void 0 : primed.ownerId) === next ? primed.read : mirror.load(next);
|
|
123
|
+
primed = null;
|
|
124
|
+
hydration = read.then((entries) => {
|
|
125
|
+
if (readEpoch !== epoch || ownerId !== next) return;
|
|
126
|
+
for (const entry of entries) {
|
|
127
|
+
if (!offline.has(entry.threadId)) keepOffline(entry.threadId, { state: entry.state, at: entry.at });
|
|
128
|
+
if (memory.peek(entry.threadId)) continue;
|
|
129
|
+
memory.restore(entry.threadId, entry.state, entry.at);
|
|
130
|
+
if (memory.peek(entry.threadId)) restored.add(entry.threadId);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
return hydration;
|
|
134
|
+
},
|
|
135
|
+
prime(next) {
|
|
136
|
+
if (next === ownerId || (primed == null ? void 0 : primed.ownerId) === next) return;
|
|
137
|
+
primed = { ownerId: next, read: mirror.load(next) };
|
|
138
|
+
},
|
|
139
|
+
offlineSeedAt: (threadId) => offlineSeeds.get(threadId) ?? null,
|
|
140
|
+
subscribeOfflineSeeds(listener) {
|
|
141
|
+
listeners.add(listener);
|
|
142
|
+
return () => {
|
|
143
|
+
listeners.delete(listener);
|
|
144
|
+
};
|
|
145
|
+
},
|
|
146
|
+
isRestored: (threadId) => restored.has(threadId),
|
|
147
|
+
whenHydrated: () => hydration,
|
|
148
|
+
async wipe() {
|
|
149
|
+
epoch += 1;
|
|
150
|
+
primed = null;
|
|
151
|
+
dropEverything();
|
|
152
|
+
await mirror.clearAll();
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
exports.OFFLINE_SNAPSHOT_MAX_AGE_MS = OFFLINE_SNAPSHOT_MAX_AGE_MS;
|
|
157
|
+
exports.createDurableThreadSnapshotCache = createDurableThreadSnapshotCache;
|
|
158
|
+
//# sourceMappingURL=durable-thread-snapshot-cache.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"durable-thread-snapshot-cache.cjs","sources":["../../../../agent-runtime/src/durable-thread-snapshot-cache.ts"],"sourcesContent":["import {\n createDeepAgentThreadSnapshotCache,\n type DeepAgentThreadSnapshotCache,\n} from \"./thread-snapshot-cache\";\nimport { isRestingThreadSnapshot, type ThreadSnapshotMirror } from \"./thread-snapshot-mirror\";\nimport type { DeepAgentStreamValues } from \"./types\";\n\n/**\n * The thread snapshot cache with a durable, encrypted mirror behind it (`thread-snapshot-mirror.ts`):\n * a reload seeds a recently visited thread from what it last showed, and a thread can be read while\n * the transport cannot connect at all.\n *\n * - **Online, nothing changes.** `take` serves the in-memory entry within its age bound (one hour by\n * default), exactly as the plain cache does, and the attach snapshot replaces the seed.\n * - **Offline** (`isOffline()`: the host's own word that Athena can't be reached), `take` serves the\n * thread's last resting transcript this page holds (what it read, or what the mirror kept), up to\n * `offlineMaxAgeMs` old and past the online bound, so a person can read their recent\n * conversations on a plane. Never a mid-stream state: a run the connection dropped is a partial\n * transcript, and the resting one before it is what shows. Every offline seed, however recent, is\n * recorded with its capture time (`offlineSeedAt`) so the host can say the transcript is \"as of\"\n * then; only the next state the wire delivers for the thread (its attach) clears it.\n * - **Owned.** Entries belong to one owner (`setOwner`): a change drops every entry, deletes the\n * previous owner's mirrored records and reads the new owner's. A snapshot captured under one\n * account never seeds a mount under another. `wipe` drops everything (a sign-out).\n */\nexport interface DurableThreadSnapshotCache extends DeepAgentThreadSnapshotCache {\n peek(threadId: string): boolean;\n /** Bind the cache to the acting owner (`null`: nobody signed in; nothing is mirrored). */\n setOwner(ownerId: string | null): Promise<void>;\n /**\n * Start reading an owner's mirrored snapshots before the owner is known for sure (a host's\n * last-owner hint at boot): `setOwner` adopts the read if that owner is the one bound, and it\n * is discarded otherwise. Binds nothing and deletes nothing.\n */\n prime(ownerId: string): void;\n /** The owner the cache is bound to. */\n owner(): string | null;\n /**\n * When the seed `take` last served for `threadId` was captured, if it was served while Athena\n * could not be reached; `null` otherwise, and again once the wire delivers the thread.\n */\n offlineSeedAt(threadId: string): number | null;\n /** Calls `listener` whenever an offline seed is served or cleared; returns what stops it. */\n subscribeOfflineSeeds(listener: () => void): () => void;\n /** Whether the entry `take` would serve for `threadId` came back from the mirror. */\n isRestored(threadId: string): boolean;\n /** Resolves once the current owner's mirrored snapshots have been read (tests, telemetry). */\n whenHydrated(): Promise<void>;\n /** Drop every entry, in memory and in the mirror (a sign-out, a workspace switch). */\n wipe(): Promise<void>;\n}\n\nexport interface DurableThreadSnapshotCacheOptions {\n mirror: ThreadSnapshotMirror;\n /** Whether Athena can't be reached right now (the host's reachability, or the browser's). */\n isOffline?: () => boolean;\n maxThreads?: number;\n /** The online age bound (the plain cache's). */\n maxAgeMs?: number;\n /** How old a mirrored snapshot may be and still be read offline. */\n offlineMaxAgeMs?: number;\n now?: () => number;\n}\n\nconst DEFAULT_MAX_THREADS = 30;\n/** What a device keeps for reading offline: the offline plan's 30 days. */\nexport const OFFLINE_SNAPSHOT_MAX_AGE_MS = 30 * 24 * 60 * 60 * 1000;\n\nfunction browserOffline(): boolean {\n const host = globalThis as { navigator?: { onLine?: boolean } };\n return host.navigator?.onLine === false;\n}\n\nexport function createDurableThreadSnapshotCache({\n mirror,\n isOffline = browserOffline,\n maxThreads = DEFAULT_MAX_THREADS,\n maxAgeMs,\n offlineMaxAgeMs = OFFLINE_SNAPSHOT_MAX_AGE_MS,\n now = () => Date.now(),\n}: DurableThreadSnapshotCacheOptions): DurableThreadSnapshotCache {\n let ownerId: string | null = null;\n // Bumped on every owner change and wipe: a mirror read in flight then must not admit what it read.\n let epoch = 0;\n let primed: { ownerId: string; read: ReturnType<ThreadSnapshotMirror[\"load\"]> } | null = null;\n let hydration: Promise<void> = Promise.resolve();\n // Every resting snapshot readable offline (the mirror's, and this page's own), newest last.\n const offline = new Map<string, { state: DeepAgentStreamValues; at: number }>();\n const offlineSeeds = new Map<string, number>();\n const restored = new Set<string>();\n const listeners = new Set<() => void>();\n\n const notify = (): void => {\n for (const listener of listeners) {\n try {\n listener();\n } catch {\n // A host listener's fault never reaches the wire path.\n }\n }\n };\n const clearOfflineSeed = (threadId: string): void => {\n if (offlineSeeds.delete(threadId)) notify();\n };\n const keepOffline = (threadId: string, entry: { state: DeepAgentStreamValues; at: number }): void => {\n offline.delete(threadId);\n offline.set(threadId, entry);\n while (offline.size > maxThreads) {\n const oldest = offline.keys().next().value;\n if (oldest === undefined) break;\n offline.delete(oldest);\n }\n };\n\n const memory = createDeepAgentThreadSnapshotCache({\n maxThreads,\n maxAgeMs,\n now,\n onChange: (change) => {\n const owner = ownerId;\n if (owner === null) return;\n switch (change.type) {\n case \"remember\":\n mirror.write({ ownerId: owner, threadId: change.threadId, state: change.state, at: change.at });\n return;\n case \"forget\":\n mirror.remove({ ownerId: owner, threadId: change.threadId });\n return;\n case \"clear\":\n return;\n }\n },\n });\n\n /** The thread's last resting transcript within the offline bound. */\n const offlineEntry = (threadId: string): { state: DeepAgentStreamValues; at: number } | undefined => {\n const entry = offline.get(threadId);\n return entry && now() - entry.at <= offlineMaxAgeMs ? entry : undefined;\n };\n\n const dropEverything = (): void => {\n memory.clear();\n offline.clear();\n restored.clear();\n if (offlineSeeds.size > 0) {\n offlineSeeds.clear();\n notify();\n }\n };\n\n return {\n remember(threadId, state) {\n memory.remember(threadId, state);\n restored.delete(threadId);\n // A mid-stream state keeps the resting transcript before it readable offline, as the mirror\n // keeps that one's record. One too long to seal still reads from memory.\n if (isRestingThreadSnapshot(state)) keepOffline(threadId, { state, at: now() });\n // The wire delivered the thread: the transcript is current again.\n clearOfflineSeed(threadId);\n },\n take(threadId) {\n if (!isOffline()) return memory.take(threadId);\n const entry = offlineEntry(threadId);\n if (!entry) return undefined;\n if (offlineSeeds.get(threadId) !== entry.at) {\n offlineSeeds.set(threadId, entry.at);\n notify();\n }\n return entry.state;\n },\n peek(threadId) {\n return isOffline() ? offlineEntry(threadId) !== undefined : memory.peek(threadId);\n },\n forget(threadId) {\n memory.forget(threadId);\n offline.delete(threadId);\n restored.delete(threadId);\n clearOfflineSeed(threadId);\n },\n clear() {\n dropEverything();\n },\n owner: () => ownerId,\n setOwner(next) {\n if (next === ownerId) return hydration;\n const previous = ownerId;\n ownerId = next;\n epoch += 1;\n dropEverything();\n if (previous !== null) void mirror.clearOwner(previous);\n if (next === null) {\n hydration = Promise.resolve();\n return hydration;\n }\n const readEpoch = epoch;\n const read = primed?.ownerId === next ? primed.read : mirror.load(next);\n primed = null;\n hydration = read.then((entries) => {\n // The owner moved on, or everything was wiped, while the read was in flight.\n if (readEpoch !== epoch || ownerId !== next) return;\n for (const entry of entries) {\n if (!offline.has(entry.threadId)) keepOffline(entry.threadId, { state: entry.state, at: entry.at });\n if (memory.peek(entry.threadId)) continue;\n memory.restore(entry.threadId, entry.state, entry.at);\n if (memory.peek(entry.threadId)) restored.add(entry.threadId);\n }\n });\n return hydration;\n },\n prime(next) {\n if (next === ownerId || primed?.ownerId === next) return;\n primed = { ownerId: next, read: mirror.load(next) };\n },\n offlineSeedAt: (threadId) => offlineSeeds.get(threadId) ?? null,\n subscribeOfflineSeeds(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n isRestored: (threadId) => restored.has(threadId),\n whenHydrated: () => hydration,\n async wipe() {\n epoch += 1;\n primed = null;\n dropEverything();\n await mirror.clearAll();\n },\n };\n}\n"],"names":["createDeepAgentThreadSnapshotCache","isRestingThreadSnapshot"],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { type DeepAgentThreadSnapshotCache } from "./thread-snapshot-cache";
|
|
2
|
+
import { type ThreadSnapshotMirror } from "./thread-snapshot-mirror";
|
|
3
|
+
/**
|
|
4
|
+
* The thread snapshot cache with a durable, encrypted mirror behind it (`thread-snapshot-mirror.ts`):
|
|
5
|
+
* a reload seeds a recently visited thread from what it last showed, and a thread can be read while
|
|
6
|
+
* the transport cannot connect at all.
|
|
7
|
+
*
|
|
8
|
+
* - **Online, nothing changes.** `take` serves the in-memory entry within its age bound (one hour by
|
|
9
|
+
* default), exactly as the plain cache does, and the attach snapshot replaces the seed.
|
|
10
|
+
* - **Offline** (`isOffline()`: the host's own word that Athena can't be reached), `take` serves the
|
|
11
|
+
* thread's last resting transcript this page holds (what it read, or what the mirror kept), up to
|
|
12
|
+
* `offlineMaxAgeMs` old and past the online bound, so a person can read their recent
|
|
13
|
+
* conversations on a plane. Never a mid-stream state: a run the connection dropped is a partial
|
|
14
|
+
* transcript, and the resting one before it is what shows. Every offline seed, however recent, is
|
|
15
|
+
* recorded with its capture time (`offlineSeedAt`) so the host can say the transcript is "as of"
|
|
16
|
+
* then; only the next state the wire delivers for the thread (its attach) clears it.
|
|
17
|
+
* - **Owned.** Entries belong to one owner (`setOwner`): a change drops every entry, deletes the
|
|
18
|
+
* previous owner's mirrored records and reads the new owner's. A snapshot captured under one
|
|
19
|
+
* account never seeds a mount under another. `wipe` drops everything (a sign-out).
|
|
20
|
+
*/
|
|
21
|
+
export interface DurableThreadSnapshotCache extends DeepAgentThreadSnapshotCache {
|
|
22
|
+
peek(threadId: string): boolean;
|
|
23
|
+
/** Bind the cache to the acting owner (`null`: nobody signed in; nothing is mirrored). */
|
|
24
|
+
setOwner(ownerId: string | null): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Start reading an owner's mirrored snapshots before the owner is known for sure (a host's
|
|
27
|
+
* last-owner hint at boot): `setOwner` adopts the read if that owner is the one bound, and it
|
|
28
|
+
* is discarded otherwise. Binds nothing and deletes nothing.
|
|
29
|
+
*/
|
|
30
|
+
prime(ownerId: string): void;
|
|
31
|
+
/** The owner the cache is bound to. */
|
|
32
|
+
owner(): string | null;
|
|
33
|
+
/**
|
|
34
|
+
* When the seed `take` last served for `threadId` was captured, if it was served while Athena
|
|
35
|
+
* could not be reached; `null` otherwise, and again once the wire delivers the thread.
|
|
36
|
+
*/
|
|
37
|
+
offlineSeedAt(threadId: string): number | null;
|
|
38
|
+
/** Calls `listener` whenever an offline seed is served or cleared; returns what stops it. */
|
|
39
|
+
subscribeOfflineSeeds(listener: () => void): () => void;
|
|
40
|
+
/** Whether the entry `take` would serve for `threadId` came back from the mirror. */
|
|
41
|
+
isRestored(threadId: string): boolean;
|
|
42
|
+
/** Resolves once the current owner's mirrored snapshots have been read (tests, telemetry). */
|
|
43
|
+
whenHydrated(): Promise<void>;
|
|
44
|
+
/** Drop every entry, in memory and in the mirror (a sign-out, a workspace switch). */
|
|
45
|
+
wipe(): Promise<void>;
|
|
46
|
+
}
|
|
47
|
+
export interface DurableThreadSnapshotCacheOptions {
|
|
48
|
+
mirror: ThreadSnapshotMirror;
|
|
49
|
+
/** Whether Athena can't be reached right now (the host's reachability, or the browser's). */
|
|
50
|
+
isOffline?: () => boolean;
|
|
51
|
+
maxThreads?: number;
|
|
52
|
+
/** The online age bound (the plain cache's). */
|
|
53
|
+
maxAgeMs?: number;
|
|
54
|
+
/** How old a mirrored snapshot may be and still be read offline. */
|
|
55
|
+
offlineMaxAgeMs?: number;
|
|
56
|
+
now?: () => number;
|
|
57
|
+
}
|
|
58
|
+
/** What a device keeps for reading offline: the offline plan's 30 days. */
|
|
59
|
+
export declare const OFFLINE_SNAPSHOT_MAX_AGE_MS: number;
|
|
60
|
+
export declare function createDurableThreadSnapshotCache({ mirror, isOffline, maxThreads, maxAgeMs, offlineMaxAgeMs, now, }: DurableThreadSnapshotCacheOptions): DurableThreadSnapshotCache;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { createDeepAgentThreadSnapshotCache } from "./thread-snapshot-cache.js";
|
|
2
|
+
import { isRestingThreadSnapshot } from "./thread-snapshot-mirror.js";
|
|
3
|
+
const DEFAULT_MAX_THREADS = 30;
|
|
4
|
+
const OFFLINE_SNAPSHOT_MAX_AGE_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
5
|
+
function browserOffline() {
|
|
6
|
+
var _a;
|
|
7
|
+
const host = globalThis;
|
|
8
|
+
return ((_a = host.navigator) == null ? void 0 : _a.onLine) === false;
|
|
9
|
+
}
|
|
10
|
+
function createDurableThreadSnapshotCache({
|
|
11
|
+
mirror,
|
|
12
|
+
isOffline = browserOffline,
|
|
13
|
+
maxThreads = DEFAULT_MAX_THREADS,
|
|
14
|
+
maxAgeMs,
|
|
15
|
+
offlineMaxAgeMs = OFFLINE_SNAPSHOT_MAX_AGE_MS,
|
|
16
|
+
now = () => Date.now()
|
|
17
|
+
}) {
|
|
18
|
+
let ownerId = null;
|
|
19
|
+
let epoch = 0;
|
|
20
|
+
let primed = null;
|
|
21
|
+
let hydration = Promise.resolve();
|
|
22
|
+
const offline = /* @__PURE__ */ new Map();
|
|
23
|
+
const offlineSeeds = /* @__PURE__ */ new Map();
|
|
24
|
+
const restored = /* @__PURE__ */ new Set();
|
|
25
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
26
|
+
const notify = () => {
|
|
27
|
+
for (const listener of listeners) {
|
|
28
|
+
try {
|
|
29
|
+
listener();
|
|
30
|
+
} catch {
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
const clearOfflineSeed = (threadId) => {
|
|
35
|
+
if (offlineSeeds.delete(threadId)) notify();
|
|
36
|
+
};
|
|
37
|
+
const keepOffline = (threadId, entry) => {
|
|
38
|
+
offline.delete(threadId);
|
|
39
|
+
offline.set(threadId, entry);
|
|
40
|
+
while (offline.size > maxThreads) {
|
|
41
|
+
const oldest = offline.keys().next().value;
|
|
42
|
+
if (oldest === void 0) break;
|
|
43
|
+
offline.delete(oldest);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
const memory = createDeepAgentThreadSnapshotCache({
|
|
47
|
+
maxThreads,
|
|
48
|
+
maxAgeMs,
|
|
49
|
+
now,
|
|
50
|
+
onChange: (change) => {
|
|
51
|
+
const owner = ownerId;
|
|
52
|
+
if (owner === null) return;
|
|
53
|
+
switch (change.type) {
|
|
54
|
+
case "remember":
|
|
55
|
+
mirror.write({ ownerId: owner, threadId: change.threadId, state: change.state, at: change.at });
|
|
56
|
+
return;
|
|
57
|
+
case "forget":
|
|
58
|
+
mirror.remove({ ownerId: owner, threadId: change.threadId });
|
|
59
|
+
return;
|
|
60
|
+
case "clear":
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
const offlineEntry = (threadId) => {
|
|
66
|
+
const entry = offline.get(threadId);
|
|
67
|
+
return entry && now() - entry.at <= offlineMaxAgeMs ? entry : void 0;
|
|
68
|
+
};
|
|
69
|
+
const dropEverything = () => {
|
|
70
|
+
memory.clear();
|
|
71
|
+
offline.clear();
|
|
72
|
+
restored.clear();
|
|
73
|
+
if (offlineSeeds.size > 0) {
|
|
74
|
+
offlineSeeds.clear();
|
|
75
|
+
notify();
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
return {
|
|
79
|
+
remember(threadId, state) {
|
|
80
|
+
memory.remember(threadId, state);
|
|
81
|
+
restored.delete(threadId);
|
|
82
|
+
if (isRestingThreadSnapshot(state)) keepOffline(threadId, { state, at: now() });
|
|
83
|
+
clearOfflineSeed(threadId);
|
|
84
|
+
},
|
|
85
|
+
take(threadId) {
|
|
86
|
+
if (!isOffline()) return memory.take(threadId);
|
|
87
|
+
const entry = offlineEntry(threadId);
|
|
88
|
+
if (!entry) return void 0;
|
|
89
|
+
if (offlineSeeds.get(threadId) !== entry.at) {
|
|
90
|
+
offlineSeeds.set(threadId, entry.at);
|
|
91
|
+
notify();
|
|
92
|
+
}
|
|
93
|
+
return entry.state;
|
|
94
|
+
},
|
|
95
|
+
peek(threadId) {
|
|
96
|
+
return isOffline() ? offlineEntry(threadId) !== void 0 : memory.peek(threadId);
|
|
97
|
+
},
|
|
98
|
+
forget(threadId) {
|
|
99
|
+
memory.forget(threadId);
|
|
100
|
+
offline.delete(threadId);
|
|
101
|
+
restored.delete(threadId);
|
|
102
|
+
clearOfflineSeed(threadId);
|
|
103
|
+
},
|
|
104
|
+
clear() {
|
|
105
|
+
dropEverything();
|
|
106
|
+
},
|
|
107
|
+
owner: () => ownerId,
|
|
108
|
+
setOwner(next) {
|
|
109
|
+
if (next === ownerId) return hydration;
|
|
110
|
+
const previous = ownerId;
|
|
111
|
+
ownerId = next;
|
|
112
|
+
epoch += 1;
|
|
113
|
+
dropEverything();
|
|
114
|
+
if (previous !== null) void mirror.clearOwner(previous);
|
|
115
|
+
if (next === null) {
|
|
116
|
+
hydration = Promise.resolve();
|
|
117
|
+
return hydration;
|
|
118
|
+
}
|
|
119
|
+
const readEpoch = epoch;
|
|
120
|
+
const read = (primed == null ? void 0 : primed.ownerId) === next ? primed.read : mirror.load(next);
|
|
121
|
+
primed = null;
|
|
122
|
+
hydration = read.then((entries) => {
|
|
123
|
+
if (readEpoch !== epoch || ownerId !== next) return;
|
|
124
|
+
for (const entry of entries) {
|
|
125
|
+
if (!offline.has(entry.threadId)) keepOffline(entry.threadId, { state: entry.state, at: entry.at });
|
|
126
|
+
if (memory.peek(entry.threadId)) continue;
|
|
127
|
+
memory.restore(entry.threadId, entry.state, entry.at);
|
|
128
|
+
if (memory.peek(entry.threadId)) restored.add(entry.threadId);
|
|
129
|
+
}
|
|
130
|
+
});
|
|
131
|
+
return hydration;
|
|
132
|
+
},
|
|
133
|
+
prime(next) {
|
|
134
|
+
if (next === ownerId || (primed == null ? void 0 : primed.ownerId) === next) return;
|
|
135
|
+
primed = { ownerId: next, read: mirror.load(next) };
|
|
136
|
+
},
|
|
137
|
+
offlineSeedAt: (threadId) => offlineSeeds.get(threadId) ?? null,
|
|
138
|
+
subscribeOfflineSeeds(listener) {
|
|
139
|
+
listeners.add(listener);
|
|
140
|
+
return () => {
|
|
141
|
+
listeners.delete(listener);
|
|
142
|
+
};
|
|
143
|
+
},
|
|
144
|
+
isRestored: (threadId) => restored.has(threadId),
|
|
145
|
+
whenHydrated: () => hydration,
|
|
146
|
+
async wipe() {
|
|
147
|
+
epoch += 1;
|
|
148
|
+
primed = null;
|
|
149
|
+
dropEverything();
|
|
150
|
+
await mirror.clearAll();
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
export {
|
|
155
|
+
OFFLINE_SNAPSHOT_MAX_AGE_MS,
|
|
156
|
+
createDurableThreadSnapshotCache
|
|
157
|
+
};
|
|
158
|
+
//# sourceMappingURL=durable-thread-snapshot-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"durable-thread-snapshot-cache.js","sources":["../../../../agent-runtime/src/durable-thread-snapshot-cache.ts"],"sourcesContent":["import {\n createDeepAgentThreadSnapshotCache,\n type DeepAgentThreadSnapshotCache,\n} from \"./thread-snapshot-cache\";\nimport { isRestingThreadSnapshot, type ThreadSnapshotMirror } from \"./thread-snapshot-mirror\";\nimport type { DeepAgentStreamValues } from \"./types\";\n\n/**\n * The thread snapshot cache with a durable, encrypted mirror behind it (`thread-snapshot-mirror.ts`):\n * a reload seeds a recently visited thread from what it last showed, and a thread can be read while\n * the transport cannot connect at all.\n *\n * - **Online, nothing changes.** `take` serves the in-memory entry within its age bound (one hour by\n * default), exactly as the plain cache does, and the attach snapshot replaces the seed.\n * - **Offline** (`isOffline()`: the host's own word that Athena can't be reached), `take` serves the\n * thread's last resting transcript this page holds (what it read, or what the mirror kept), up to\n * `offlineMaxAgeMs` old and past the online bound, so a person can read their recent\n * conversations on a plane. Never a mid-stream state: a run the connection dropped is a partial\n * transcript, and the resting one before it is what shows. Every offline seed, however recent, is\n * recorded with its capture time (`offlineSeedAt`) so the host can say the transcript is \"as of\"\n * then; only the next state the wire delivers for the thread (its attach) clears it.\n * - **Owned.** Entries belong to one owner (`setOwner`): a change drops every entry, deletes the\n * previous owner's mirrored records and reads the new owner's. A snapshot captured under one\n * account never seeds a mount under another. `wipe` drops everything (a sign-out).\n */\nexport interface DurableThreadSnapshotCache extends DeepAgentThreadSnapshotCache {\n peek(threadId: string): boolean;\n /** Bind the cache to the acting owner (`null`: nobody signed in; nothing is mirrored). */\n setOwner(ownerId: string | null): Promise<void>;\n /**\n * Start reading an owner's mirrored snapshots before the owner is known for sure (a host's\n * last-owner hint at boot): `setOwner` adopts the read if that owner is the one bound, and it\n * is discarded otherwise. Binds nothing and deletes nothing.\n */\n prime(ownerId: string): void;\n /** The owner the cache is bound to. */\n owner(): string | null;\n /**\n * When the seed `take` last served for `threadId` was captured, if it was served while Athena\n * could not be reached; `null` otherwise, and again once the wire delivers the thread.\n */\n offlineSeedAt(threadId: string): number | null;\n /** Calls `listener` whenever an offline seed is served or cleared; returns what stops it. */\n subscribeOfflineSeeds(listener: () => void): () => void;\n /** Whether the entry `take` would serve for `threadId` came back from the mirror. */\n isRestored(threadId: string): boolean;\n /** Resolves once the current owner's mirrored snapshots have been read (tests, telemetry). */\n whenHydrated(): Promise<void>;\n /** Drop every entry, in memory and in the mirror (a sign-out, a workspace switch). */\n wipe(): Promise<void>;\n}\n\nexport interface DurableThreadSnapshotCacheOptions {\n mirror: ThreadSnapshotMirror;\n /** Whether Athena can't be reached right now (the host's reachability, or the browser's). */\n isOffline?: () => boolean;\n maxThreads?: number;\n /** The online age bound (the plain cache's). */\n maxAgeMs?: number;\n /** How old a mirrored snapshot may be and still be read offline. */\n offlineMaxAgeMs?: number;\n now?: () => number;\n}\n\nconst DEFAULT_MAX_THREADS = 30;\n/** What a device keeps for reading offline: the offline plan's 30 days. */\nexport const OFFLINE_SNAPSHOT_MAX_AGE_MS = 30 * 24 * 60 * 60 * 1000;\n\nfunction browserOffline(): boolean {\n const host = globalThis as { navigator?: { onLine?: boolean } };\n return host.navigator?.onLine === false;\n}\n\nexport function createDurableThreadSnapshotCache({\n mirror,\n isOffline = browserOffline,\n maxThreads = DEFAULT_MAX_THREADS,\n maxAgeMs,\n offlineMaxAgeMs = OFFLINE_SNAPSHOT_MAX_AGE_MS,\n now = () => Date.now(),\n}: DurableThreadSnapshotCacheOptions): DurableThreadSnapshotCache {\n let ownerId: string | null = null;\n // Bumped on every owner change and wipe: a mirror read in flight then must not admit what it read.\n let epoch = 0;\n let primed: { ownerId: string; read: ReturnType<ThreadSnapshotMirror[\"load\"]> } | null = null;\n let hydration: Promise<void> = Promise.resolve();\n // Every resting snapshot readable offline (the mirror's, and this page's own), newest last.\n const offline = new Map<string, { state: DeepAgentStreamValues; at: number }>();\n const offlineSeeds = new Map<string, number>();\n const restored = new Set<string>();\n const listeners = new Set<() => void>();\n\n const notify = (): void => {\n for (const listener of listeners) {\n try {\n listener();\n } catch {\n // A host listener's fault never reaches the wire path.\n }\n }\n };\n const clearOfflineSeed = (threadId: string): void => {\n if (offlineSeeds.delete(threadId)) notify();\n };\n const keepOffline = (threadId: string, entry: { state: DeepAgentStreamValues; at: number }): void => {\n offline.delete(threadId);\n offline.set(threadId, entry);\n while (offline.size > maxThreads) {\n const oldest = offline.keys().next().value;\n if (oldest === undefined) break;\n offline.delete(oldest);\n }\n };\n\n const memory = createDeepAgentThreadSnapshotCache({\n maxThreads,\n maxAgeMs,\n now,\n onChange: (change) => {\n const owner = ownerId;\n if (owner === null) return;\n switch (change.type) {\n case \"remember\":\n mirror.write({ ownerId: owner, threadId: change.threadId, state: change.state, at: change.at });\n return;\n case \"forget\":\n mirror.remove({ ownerId: owner, threadId: change.threadId });\n return;\n case \"clear\":\n return;\n }\n },\n });\n\n /** The thread's last resting transcript within the offline bound. */\n const offlineEntry = (threadId: string): { state: DeepAgentStreamValues; at: number } | undefined => {\n const entry = offline.get(threadId);\n return entry && now() - entry.at <= offlineMaxAgeMs ? entry : undefined;\n };\n\n const dropEverything = (): void => {\n memory.clear();\n offline.clear();\n restored.clear();\n if (offlineSeeds.size > 0) {\n offlineSeeds.clear();\n notify();\n }\n };\n\n return {\n remember(threadId, state) {\n memory.remember(threadId, state);\n restored.delete(threadId);\n // A mid-stream state keeps the resting transcript before it readable offline, as the mirror\n // keeps that one's record. One too long to seal still reads from memory.\n if (isRestingThreadSnapshot(state)) keepOffline(threadId, { state, at: now() });\n // The wire delivered the thread: the transcript is current again.\n clearOfflineSeed(threadId);\n },\n take(threadId) {\n if (!isOffline()) return memory.take(threadId);\n const entry = offlineEntry(threadId);\n if (!entry) return undefined;\n if (offlineSeeds.get(threadId) !== entry.at) {\n offlineSeeds.set(threadId, entry.at);\n notify();\n }\n return entry.state;\n },\n peek(threadId) {\n return isOffline() ? offlineEntry(threadId) !== undefined : memory.peek(threadId);\n },\n forget(threadId) {\n memory.forget(threadId);\n offline.delete(threadId);\n restored.delete(threadId);\n clearOfflineSeed(threadId);\n },\n clear() {\n dropEverything();\n },\n owner: () => ownerId,\n setOwner(next) {\n if (next === ownerId) return hydration;\n const previous = ownerId;\n ownerId = next;\n epoch += 1;\n dropEverything();\n if (previous !== null) void mirror.clearOwner(previous);\n if (next === null) {\n hydration = Promise.resolve();\n return hydration;\n }\n const readEpoch = epoch;\n const read = primed?.ownerId === next ? primed.read : mirror.load(next);\n primed = null;\n hydration = read.then((entries) => {\n // The owner moved on, or everything was wiped, while the read was in flight.\n if (readEpoch !== epoch || ownerId !== next) return;\n for (const entry of entries) {\n if (!offline.has(entry.threadId)) keepOffline(entry.threadId, { state: entry.state, at: entry.at });\n if (memory.peek(entry.threadId)) continue;\n memory.restore(entry.threadId, entry.state, entry.at);\n if (memory.peek(entry.threadId)) restored.add(entry.threadId);\n }\n });\n return hydration;\n },\n prime(next) {\n if (next === ownerId || primed?.ownerId === next) return;\n primed = { ownerId: next, read: mirror.load(next) };\n },\n offlineSeedAt: (threadId) => offlineSeeds.get(threadId) ?? null,\n subscribeOfflineSeeds(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n isRestored: (threadId) => restored.has(threadId),\n whenHydrated: () => hydration,\n async wipe() {\n epoch += 1;\n primed = null;\n dropEverything();\n await mirror.clearAll();\n },\n };\n}\n"],"names":[],"mappings":";;AAgEA,MAAM,sBAAsB;AAErB,MAAM,8BAA8B,KAAK,KAAK,KAAK,KAAK;AAE/D,SAAS,iBAA0B;;AACjC,QAAM,OAAO;AACb,WAAO,UAAK,cAAL,mBAAgB,YAAW;AACpC;AAEO,SAAS,iCAAiC;AAAA,EAC/C;AAAA,EACA,YAAY;AAAA,EACZ,aAAa;AAAA,EACb;AAAA,EACA,kBAAkB;AAAA,EAClB,MAAM,MAAM,KAAK,IAAA;AACnB,GAAkE;AAChE,MAAI,UAAyB;AAE7B,MAAI,QAAQ;AACZ,MAAI,SAAqF;AACzF,MAAI,YAA2B,QAAQ,QAAA;AAEvC,QAAM,8BAAc,IAAA;AACpB,QAAM,mCAAmB,IAAA;AACzB,QAAM,+BAAe,IAAA;AACrB,QAAM,gCAAgB,IAAA;AAEtB,QAAM,SAAS,MAAY;AACzB,eAAW,YAAY,WAAW;AAChC,UAAI;AACF,iBAAA;AAAA,MACF,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACA,QAAM,mBAAmB,CAAC,aAA2B;AACnD,QAAI,aAAa,OAAO,QAAQ,EAAG,QAAA;AAAA,EACrC;AACA,QAAM,cAAc,CAAC,UAAkB,UAA8D;AACnG,YAAQ,OAAO,QAAQ;AACvB,YAAQ,IAAI,UAAU,KAAK;AAC3B,WAAO,QAAQ,OAAO,YAAY;AAChC,YAAM,SAAS,QAAQ,KAAA,EAAO,OAAO;AACrC,UAAI,WAAW,OAAW;AAC1B,cAAQ,OAAO,MAAM;AAAA,IACvB;AAAA,EACF;AAEA,QAAM,SAAS,mCAAmC;AAAA,IAChD;AAAA,IACA;AAAA,IACA;AAAA,IACA,UAAU,CAAC,WAAW;AACpB,YAAM,QAAQ;AACd,UAAI,UAAU,KAAM;AACpB,cAAQ,OAAO,MAAA;AAAA,QACb,KAAK;AACH,iBAAO,MAAM,EAAE,SAAS,OAAO,UAAU,OAAO,UAAU,OAAO,OAAO,OAAO,IAAI,OAAO,IAAI;AAC9F;AAAA,QACF,KAAK;AACH,iBAAO,OAAO,EAAE,SAAS,OAAO,UAAU,OAAO,UAAU;AAC3D;AAAA,QACF,KAAK;AACH;AAAA,MAAA;AAAA,IAEN;AAAA,EAAA,CACD;AAGD,QAAM,eAAe,CAAC,aAA+E;AACnG,UAAM,QAAQ,QAAQ,IAAI,QAAQ;AAClC,WAAO,SAAS,QAAQ,MAAM,MAAM,kBAAkB,QAAQ;AAAA,EAChE;AAEA,QAAM,iBAAiB,MAAY;AACjC,WAAO,MAAA;AACP,YAAQ,MAAA;AACR,aAAS,MAAA;AACT,QAAI,aAAa,OAAO,GAAG;AACzB,mBAAa,MAAA;AACb,aAAA;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AAAA,IACL,SAAS,UAAU,OAAO;AACxB,aAAO,SAAS,UAAU,KAAK;AAC/B,eAAS,OAAO,QAAQ;AAGxB,UAAI,wBAAwB,KAAK,EAAG,aAAY,UAAU,EAAE,OAAO,IAAI,IAAA,GAAO;AAE9E,uBAAiB,QAAQ;AAAA,IAC3B;AAAA,IACA,KAAK,UAAU;AACb,UAAI,CAAC,UAAA,EAAa,QAAO,OAAO,KAAK,QAAQ;AAC7C,YAAM,QAAQ,aAAa,QAAQ;AACnC,UAAI,CAAC,MAAO,QAAO;AACnB,UAAI,aAAa,IAAI,QAAQ,MAAM,MAAM,IAAI;AAC3C,qBAAa,IAAI,UAAU,MAAM,EAAE;AACnC,eAAA;AAAA,MACF;AACA,aAAO,MAAM;AAAA,IACf;AAAA,IACA,KAAK,UAAU;AACb,aAAO,UAAA,IAAc,aAAa,QAAQ,MAAM,SAAY,OAAO,KAAK,QAAQ;AAAA,IAClF;AAAA,IACA,OAAO,UAAU;AACf,aAAO,OAAO,QAAQ;AACtB,cAAQ,OAAO,QAAQ;AACvB,eAAS,OAAO,QAAQ;AACxB,uBAAiB,QAAQ;AAAA,IAC3B;AAAA,IACA,QAAQ;AACN,qBAAA;AAAA,IACF;AAAA,IACA,OAAO,MAAM;AAAA,IACb,SAAS,MAAM;AACb,UAAI,SAAS,QAAS,QAAO;AAC7B,YAAM,WAAW;AACjB,gBAAU;AACV,eAAS;AACT,qBAAA;AACA,UAAI,aAAa,KAAM,MAAK,OAAO,WAAW,QAAQ;AACtD,UAAI,SAAS,MAAM;AACjB,oBAAY,QAAQ,QAAA;AACpB,eAAO;AAAA,MACT;AACA,YAAM,YAAY;AAClB,YAAM,QAAO,iCAAQ,aAAY,OAAO,OAAO,OAAO,OAAO,KAAK,IAAI;AACtE,eAAS;AACT,kBAAY,KAAK,KAAK,CAAC,YAAY;AAEjC,YAAI,cAAc,SAAS,YAAY,KAAM;AAC7C,mBAAW,SAAS,SAAS;AAC3B,cAAI,CAAC,QAAQ,IAAI,MAAM,QAAQ,EAAG,aAAY,MAAM,UAAU,EAAE,OAAO,MAAM,OAAO,IAAI,MAAM,IAAI;AAClG,cAAI,OAAO,KAAK,MAAM,QAAQ,EAAG;AACjC,iBAAO,QAAQ,MAAM,UAAU,MAAM,OAAO,MAAM,EAAE;AACpD,cAAI,OAAO,KAAK,MAAM,QAAQ,EAAG,UAAS,IAAI,MAAM,QAAQ;AAAA,QAC9D;AAAA,MACF,CAAC;AACD,aAAO;AAAA,IACT;AAAA,IACA,MAAM,MAAM;AACV,UAAI,SAAS,YAAW,iCAAQ,aAAY,KAAM;AAClD,eAAS,EAAE,SAAS,MAAM,MAAM,OAAO,KAAK,IAAI,EAAA;AAAA,IAClD;AAAA,IACA,eAAe,CAAC,aAAa,aAAa,IAAI,QAAQ,KAAK;AAAA,IAC3D,sBAAsB,UAAU;AAC9B,gBAAU,IAAI,QAAQ;AACtB,aAAO,MAAM;AACX,kBAAU,OAAO,QAAQ;AAAA,MAC3B;AAAA,IACF;AAAA,IACA,YAAY,CAAC,aAAa,SAAS,IAAI,QAAQ;AAAA,IAC/C,cAAc,MAAM;AAAA,IACpB,MAAM,OAAO;AACX,eAAS;AACT,eAAS;AACT,qBAAA;AACA,YAAM,OAAO,SAAA;AAAA,IACf;AAAA,EAAA;AAEJ;"}
|