@vellumai/assistant 0.11.2 → 0.11.3-staging.2
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/ARCHITECTURE.md +58 -3
- package/docs/trusted-contact-access.md +9 -5
- package/docs/vellum-doctor.md +195 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/channels.ts +39 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/ingress.ts +10 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +6 -0
- package/node_modules/@vellumai/ces-client/src/index.ts +1 -0
- package/node_modules/@vellumai/ces-client/src/rpc-client.ts +19 -2
- package/node_modules/@vellumai/environments/package.json +2 -1
- package/node_modules/@vellumai/environments/src/__tests__/cloud-assistant-hub-url.test.ts +38 -0
- package/node_modules/@vellumai/environments/src/__tests__/install-layout.test.ts +98 -0
- package/node_modules/@vellumai/environments/src/__tests__/package-boundary.test.ts +5 -5
- package/node_modules/@vellumai/environments/src/index.ts +17 -6
- package/node_modules/@vellumai/environments/src/install-layout.ts +49 -0
- package/node_modules/@vellumai/environments/src/seeds.ts +29 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/channels.ts +39 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/ingress.ts +10 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +6 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +4 -0
- package/node_modules/@vellumai/gateway-client/src/verification-session-contract.ts +91 -6
- package/node_modules/@vellumai/ipc-server-utils/src/endpoint.test.ts +36 -0
- package/node_modules/@vellumai/ipc-server-utils/src/endpoint.ts +142 -0
- package/node_modules/@vellumai/ipc-server-utils/src/index.ts +2 -0
- package/node_modules/@vellumai/ipc-server-utils/src/listen-options.ts +3 -0
- package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.test.ts +15 -1
- package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.ts +17 -2
- package/node_modules/@vellumai/service-contracts/src/channels.ts +39 -0
- package/node_modules/@vellumai/service-contracts/src/ingress.ts +10 -0
- package/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +6 -0
- package/node_modules/@vellumai/slack-text/src/index.ts +16 -2
- package/openapi.yaml +589 -30
- package/package.json +1 -1
- package/src/__tests__/agent-image-optimize.test.ts +4 -4
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +113 -66
- package/src/__tests__/agent-loop-override-profile.test.ts +38 -48
- package/src/__tests__/agent-loop-subagent-billing-headers.test.ts +166 -0
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +1 -0
- package/src/__tests__/agent-wake-override-profile.test.ts +1 -0
- package/src/__tests__/answered-question-persistence.test.ts +240 -0
- package/src/__tests__/anthropic-provider.test.ts +165 -30
- package/src/__tests__/app-control-flow.test.ts +9 -8
- package/src/__tests__/assistant-event-hub.test.ts +48 -0
- package/src/__tests__/attachments-store-heic-normalize.test.ts +16 -12
- package/src/__tests__/attachments-store.test.ts +130 -68
- package/src/__tests__/attachments.test.ts +36 -36
- package/src/__tests__/background-workers-disk-pressure.test.ts +1 -1
- package/src/__tests__/call-start-guardian-guard.test.ts +18 -4
- package/src/__tests__/canned-reply-release.test.ts +86 -0
- package/src/__tests__/channel-guardian.test.ts +59 -29
- package/src/__tests__/channel-readiness-telegram-remote.test.ts +154 -0
- package/src/__tests__/channel-setup-panel-ack.test.ts +6 -5
- package/src/__tests__/client-os-metadata-persistence.test.ts +103 -4
- package/src/__tests__/compactor-image-manifest-trust.test.ts +1 -1
- package/src/__tests__/consult-deadline.test.ts +65 -0
- package/src/__tests__/conversation-agent-loop.test.ts +438 -2
- package/src/__tests__/conversation-disk-view-integration.test.ts +5 -1
- package/src/__tests__/conversation-disk-view.test.ts +4 -4
- package/src/__tests__/conversation-error.test.ts +22 -3
- package/src/__tests__/conversation-fork-crud.test.ts +5 -1
- package/src/__tests__/conversation-fork-referential.test.ts +352 -0
- package/src/__tests__/conversation-fork-retrospective.test.ts +5 -1
- package/src/__tests__/conversation-group-tools.test.ts +32 -2
- package/src/__tests__/conversation-inference-profile-route.test.ts +27 -1
- package/src/__tests__/conversation-initial-prompt.test.ts +51 -22
- package/src/__tests__/conversation-key-store-bootstrap-cleanup.test.ts +119 -0
- package/src/__tests__/conversation-key-store-origin.test.ts +105 -0
- package/src/__tests__/conversation-list-recency-ordering.test.ts +104 -0
- package/src/__tests__/conversation-origin-at-creation.test.ts +153 -0
- package/src/__tests__/conversation-origin-channel-filter.test.ts +95 -0
- package/src/__tests__/conversation-placement-promotion.test.ts +172 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +123 -0
- package/src/__tests__/conversation-queue.test.ts +433 -1
- package/src/__tests__/conversation-retry-route.test.ts +3 -1
- package/src/__tests__/conversation-routes-hidden-queue.test.ts +64 -1
- package/src/__tests__/conversation-store-ephemeral.test.ts +4 -0
- package/src/__tests__/conversation-store.test.ts +26 -10
- package/src/__tests__/conversation-summarize-route.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +15 -6
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +6 -5
- package/src/__tests__/conversation-surfaces-app-control.test.ts +12 -11
- package/src/__tests__/conversation-surfaces-app-open.test.ts +11 -5
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +5 -4
- package/src/__tests__/conversation-surfaces-history-restored-completion.test.ts +967 -0
- package/src/__tests__/conversation-surfaces-persisted-info.test.ts +312 -0
- package/src/__tests__/conversation-surfaces-queued-emit.test.ts +6 -5
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -8
- package/src/__tests__/conversation-surfaces-standalone.test.ts +21 -11
- package/src/__tests__/conversation-surfaces-state-update.test.ts +7 -11
- package/src/__tests__/conversation-surfaces-table-action.test.ts +7 -6
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +11 -6
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +9 -6
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +70 -7
- package/src/__tests__/conversation-wait-for-idle.test.ts +6 -11
- package/src/__tests__/credential-prompt-route.test.ts +57 -7
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/cu-unified-flow.test.ts +89 -28
- package/src/__tests__/custom-group-listing-visibility.test.ts +1 -1
- package/src/__tests__/db-schedule-syntax-migration.test.ts +4 -1
- package/src/__tests__/discord-access-request-privacy.test.ts +366 -0
- package/src/__tests__/discord-requester-notice-privacy.test.ts +87 -0
- package/src/__tests__/disk-pressure-guard.test.ts +55 -55
- package/src/__tests__/disk-pressure-routes.test.ts +10 -10
- package/src/__tests__/disk-pressure-tools.test.ts +2 -2
- package/src/__tests__/disk-usage.test.ts +35 -20
- package/src/__tests__/document-sync-tags.test.ts +379 -0
- package/src/__tests__/document-update-default-surface.test.ts +28 -0
- package/src/__tests__/dynamic-skill-background-guard.test.ts +2 -2
- package/src/__tests__/emit-signal-routing-intent.test.ts +3 -4
- package/src/__tests__/ensure-conversation-exists.test.ts +8 -5
- package/src/__tests__/events-dev-bypass-actor.test.ts +183 -1
- package/src/__tests__/evict-conversations-for-reload.test.ts +90 -0
- package/src/__tests__/file-list-tool.test.ts +12 -10
- package/src/__tests__/file-ops-service.test.ts +151 -44
- package/src/__tests__/file-read-container-boundary.test.ts +137 -0
- package/src/__tests__/file-read-tool.test.ts +21 -9
- package/src/__tests__/file-url-path-guard.test.ts +83 -0
- package/src/__tests__/filesystem-tools.test.ts +82 -66
- package/src/__tests__/guardian-outbound-http.test.ts +8 -8
- package/src/__tests__/helpers/gateway-verification-sessions-stub.ts +14 -1
- package/src/__tests__/helpers/hub-clients.ts +42 -0
- package/src/__tests__/helpers/mock-conversation.ts +46 -0
- package/src/__tests__/helpers/verification-sessions-ipc-sim.ts +61 -57
- package/src/__tests__/history-repair.test.ts +112 -12
- package/src/__tests__/host-bash-proxy.test.ts +10 -5
- package/src/__tests__/host-bash-routes.test.ts +67 -0
- package/src/__tests__/host-browser-proxy.test.ts +2 -2
- package/src/__tests__/host-cu-proxy.test.ts +3 -7
- package/src/__tests__/host-file-proxy.test.ts +3 -7
- package/src/__tests__/host-file-read-tool.test.ts +5 -1
- package/src/__tests__/host-transfer-proxy-targeted.test.ts +6 -4
- package/src/__tests__/http-conversation-lineage.test.ts +2 -5
- package/src/__tests__/http-user-message-parity.test.ts +44 -0
- package/src/__tests__/identity-routes.test.ts +13 -13
- package/src/__tests__/image-conversion.test.ts +29 -26
- package/src/__tests__/image-source-path-reinject.test.ts +2 -2
- package/src/__tests__/inference-profile-session-handler.test.ts +95 -0
- package/src/__tests__/inference-profile-session-ipc.test.ts +25 -0
- package/src/__tests__/introduction-card-resolver.test.ts +6 -1
- package/src/__tests__/list-messages-attachments.test.ts +56 -32
- package/src/__tests__/list-messages-background-tool-completion.test.ts +4 -4
- package/src/__tests__/list-messages-client-message-id.test.ts +2 -2
- package/src/__tests__/list-messages-hidden-metadata.test.ts +16 -16
- package/src/__tests__/list-messages-page-latest.test.ts +61 -61
- package/src/__tests__/list-messages-provider-error.test.ts +6 -6
- package/src/__tests__/list-messages-queued.test.ts +49 -6
- package/src/__tests__/list-messages-system-card.test.ts +4 -4
- package/src/__tests__/list-messages-tool-merge.test.ts +9 -9
- package/src/__tests__/llm-resolver-override-or-default.test.ts +141 -0
- package/src/__tests__/llm-usage-store.test.ts +55 -0
- package/src/__tests__/manual-token-reconciliation.test.ts +45 -0
- package/src/__tests__/mcp-tool-annotations-risk.test.ts +133 -0
- package/src/__tests__/media-stream-server-integration.test.ts +36 -0
- package/src/__tests__/migration-export-http.test.ts +1 -1
- package/src/__tests__/migration-import-commit-http.test.ts +1 -1
- package/src/__tests__/migration-import-preflight-http.test.ts +1 -1
- package/src/__tests__/migration-validate-http.test.ts +1 -1
- package/src/__tests__/mtime-cache.test.ts +65 -3
- package/src/__tests__/notification-platform-adapter.test.ts +104 -0
- package/src/__tests__/notification-schedule-notify-dedup.test.ts +1 -1
- package/src/__tests__/oauth-provider-profiles.test.ts +4 -2
- package/src/__tests__/oauth-provider-seed-logos.test.ts +65 -0
- package/src/__tests__/oauth-provider-serializer.test.ts +17 -0
- package/src/__tests__/oauth-providers-routes.test.ts +1 -0
- package/src/__tests__/openai-responses-prompt-cache.test.ts +5 -2
- package/src/__tests__/path-policy.test.ts +164 -1
- package/src/__tests__/persist-media-references.test.ts +2 -2
- package/src/__tests__/persist-unsendable-image-downscale.test.ts +5 -5
- package/src/__tests__/persist-unsendable-image.test.ts +23 -23
- package/src/__tests__/persona-resolver.test.ts +154 -0
- package/src/__tests__/plugin-api-webhook-url.test.ts +170 -0
- package/src/__tests__/plugin-import-boundary-guard.test.ts +6 -0
- package/src/__tests__/processing-flag-persist-failure.test.ts +15 -10
- package/src/__tests__/profile-availability-incomplete.test.ts +113 -0
- package/src/__tests__/profiler-routes.test.ts +13 -13
- package/src/__tests__/prompt-cache-cross-turn-stability.test.ts +593 -0
- package/src/__tests__/proxy-approval-callback.test.ts +3 -3
- package/src/__tests__/queued-message-cancel-and-steer.test.ts +189 -0
- package/src/__tests__/queued-message-steer-actor-scoping.test.ts +164 -0
- package/src/__tests__/resolve-trust-class.test.ts +20 -0
- package/src/__tests__/run-conversation-turn-persistence.test.ts +1 -1
- package/src/__tests__/run-due-schedules.test.ts +174 -0
- package/src/__tests__/runtime-attachment-metadata.test.ts +15 -7
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +166 -0
- package/src/__tests__/schedule-routes.test.ts +730 -8
- package/src/__tests__/schedule-store.test.ts +540 -0
- package/src/__tests__/schedule-tools.test.ts +103 -0
- package/src/__tests__/scheduler-wake.test.ts +5 -0
- package/src/__tests__/secret-routes-platform-proxy.test.ts +29 -1
- package/src/__tests__/secure-keys.test.ts +91 -0
- package/src/__tests__/server-history-render.test.ts +97 -7
- package/src/__tests__/size-guard.test.ts +8 -8
- package/src/__tests__/skill-docs-sync-guard.test.ts +3 -2
- package/src/__tests__/skill-tool-factory.test.ts +247 -0
- package/src/__tests__/skills-install-staging.test.ts +15 -6
- package/src/__tests__/slack-edit-ordering-characterization.test.ts +103 -0
- package/src/__tests__/slack-inbound-verification.test.ts +4 -1
- package/src/__tests__/slack-mention-binding-invariance.test.ts +103 -0
- package/src/__tests__/slack-mention-provider-leak-audit.test.ts +135 -0
- package/src/__tests__/starter-task-flow.test.ts +5 -4
- package/src/__tests__/steer-on-enqueue-question.test.ts +3 -2
- package/src/__tests__/stt-language-catalog-parity.test.ts +38 -0
- package/src/__tests__/subagent-allowlist-validation.test.ts +26 -4
- package/src/__tests__/subagent-cron-run-attribution.test.ts +301 -0
- package/src/__tests__/subagent-disposal.test.ts +10 -0
- package/src/__tests__/subagent-fork-notifications.test.ts +10 -0
- package/src/__tests__/subagent-fork-prompt-role.test.ts +85 -11
- package/src/__tests__/subagent-fork-spawn.test.ts +15 -7
- package/src/__tests__/subagent-manager-notify.test.ts +148 -0
- package/src/__tests__/subagent-notify-parent.test.ts +1 -1
- package/src/__tests__/subagent-persistence.test.ts +141 -0
- package/src/__tests__/subagent-role-registry.test.ts +172 -63
- package/src/__tests__/subagent-role-resolution.test.ts +88 -0
- package/src/__tests__/subagent-spawn-and-await.test.ts +48 -0
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +111 -10
- package/src/__tests__/subagent-terminal-message.test.ts +88 -1
- package/src/__tests__/subagent-tool-gate-mode.test.ts +225 -10
- package/src/__tests__/subagent-tools.test.ts +1901 -108
- package/src/__tests__/surface-completion-compaction-boundary.test.ts +124 -0
- package/src/__tests__/surface-completion-in-flight-snapshot.test.ts +298 -0
- package/src/__tests__/system-prompt.test.ts +82 -7
- package/src/__tests__/tool-grant-request-escalation.test.ts +40 -1
- package/src/__tests__/tool-result-spool.test.ts +74 -18
- package/src/__tests__/tool-side-effects-documents.test.ts +174 -0
- package/src/__tests__/tool-side-effects-hook-failures.test.ts +129 -0
- package/src/__tests__/tools-audio-read.test.ts +10 -10
- package/src/__tests__/tools-get-route.test.ts +85 -12
- package/src/__tests__/tools-list-cli.test.ts +171 -0
- package/src/__tests__/top-level-renderer.test.ts +54 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +68 -1
- package/src/__tests__/trusted-contact-multichannel.test.ts +4 -1
- package/src/__tests__/turn-tail-chain.test.ts +135 -0
- package/src/__tests__/ui-choice-copy-surfaces.test.ts +6 -4
- package/src/__tests__/ui-visual-surface.test.ts +5 -4
- package/src/__tests__/ui-work-result-surface.test.ts +5 -4
- package/src/__tests__/unified-turn-context-visible-app.test.ts +7 -8
- package/src/__tests__/usage-routes.test.ts +62 -0
- package/src/__tests__/verification-outbound-delivery.test.ts +176 -0
- package/src/__tests__/visible-app-context.test.ts +20 -4
- package/src/__tests__/web-search-history.test.ts +96 -0
- package/src/__tests__/workspace-migration-139-clear-renamed-cost-profile-label.test.ts +6 -6
- package/src/__tests__/workspace-migration-140-repair-seed-pinned-memory-v3-live.test.ts +330 -0
- package/src/acp/failure-error.ts +3 -5
- package/src/agent/attachments.ts +26 -24
- package/src/agent/history-repair/history-repair.ts +27 -26
- package/src/agent/image-optimize.ts +6 -6
- package/src/agent/loop.ts +40 -22
- package/src/agent/message-types.ts +3 -3
- package/src/api/constants/document-tools.ts +55 -0
- package/src/api/events/question-answered.ts +53 -0
- package/src/api/events/tool-result.ts +7 -0
- package/src/api/index.ts +13 -0
- package/src/api/responses/conversation-message.ts +11 -0
- package/src/api/surfaces-oauth-connect.test.ts +96 -0
- package/src/api/surfaces.ts +36 -8
- package/src/approvals/guardian-channel-delivery.ts +83 -0
- package/src/approvals/guardian-expiry-notifier.ts +13 -11
- package/src/approvals/guardian-request-resolvers.ts +222 -135
- package/src/calls/__tests__/voice-session-bridge.test.ts +50 -0
- package/src/calls/media-stream-server.ts +9 -1
- package/src/calls/voice-session-bridge.ts +38 -0
- package/src/channels/__tests__/gateway-verification-sessions.test.ts +3 -3
- package/src/channels/config.ts +7 -2
- package/src/channels/gateway-verification-sessions.ts +7 -2
- package/src/channels/types.ts +7 -1
- package/src/cli/commands/__tests__/cache.test.ts +7 -4
- package/src/cli/commands/__tests__/cli-test-harness.ts +82 -0
- package/src/cli/commands/__tests__/conversations-wake.test.ts +51 -6
- package/src/cli/commands/__tests__/inference-models.test.ts +14 -0
- package/src/cli/commands/__tests__/inference-profiles.test.ts +44 -1
- package/src/cli/commands/__tests__/inference-providers.test.ts +7 -0
- package/src/cli/commands/__tests__/plugins.test.ts +692 -0
- package/src/cli/commands/__tests__/schedules.test.ts +136 -37
- package/src/cli/commands/conversations.ts +7 -3
- package/src/cli/commands/credentials.help.ts +7 -0
- package/src/cli/commands/inference-profiles.ts +9 -3
- package/src/cli/commands/inference.help.ts +16 -2
- package/src/cli/commands/mcp.help.ts +4 -2
- package/src/cli/commands/memory/memory-retrospective.ts +18 -0
- package/src/cli/commands/notifications.ts +3 -6
- package/src/cli/commands/oauth/connect-surface-guidance.test.ts +16 -0
- package/src/cli/commands/oauth/connect-surface-guidance.ts +25 -7
- package/src/cli/commands/oauth/connect.test.ts +26 -1
- package/src/cli/commands/oauth/connect.ts +4 -1
- package/src/cli/commands/oauth/index.help.ts +3 -1
- package/src/cli/commands/oauth/providers.ts +3 -0
- package/src/cli/commands/plugins.help.ts +25 -2
- package/src/cli/commands/plugins.ts +289 -10
- package/src/cli/commands/schedules.help.ts +14 -12
- package/src/cli/commands/schedules.ts +19 -5
- package/src/cli/commands/tools.help.ts +4 -2
- package/src/cli/commands/tools.ts +38 -0
- package/src/cli/lib/__tests__/inspect-plugin.test.ts +1 -0
- package/src/cli/lib/__tests__/install-from-github.test.ts +79 -0
- package/src/cli/lib/__tests__/install-from-platform.test.ts +47 -1
- package/src/cli/lib/__tests__/plugin-surfaces.test.ts +86 -7
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +122 -0
- package/src/cli/lib/install-from-github.ts +61 -0
- package/src/cli/lib/install-from-platform.ts +13 -2
- package/src/cli/lib/plugin-surfaces.ts +124 -4
- package/src/cli/lib/upgrade-plugin.ts +18 -0
- package/src/cli.ts +1 -1
- package/src/config/__tests__/deployment-context-defaults.test.ts +73 -0
- package/src/config/__tests__/memory-retrospective-schema.test.ts +40 -0
- package/src/config/__tests__/plugin-updates-schema.test.ts +43 -0
- package/src/config/__tests__/profile-tool-support.test.ts +131 -0
- package/src/config/bundled-skills/AGENTS.md +1 -1
- package/src/config/bundled-skills/app-builder/SKILL.md +1 -1
- package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +3 -3
- package/src/config/bundled-skills/schedule/SKILL.md +5 -1
- package/src/config/bundled-skills/schedule/TOOLS.json +2 -2
- package/src/config/bundled-skills/settings/TOOLS.json +2 -2
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +1 -0
- package/src/config/bundled-skills/subagent/SKILL.md +53 -22
- package/src/config/bundled-skills/subagent/TOOLS.json +14 -13
- package/src/config/bundled-skills/visualize/SKILL.md +1 -1
- package/src/config/default-profile-catalog.ts +6 -2
- package/src/config/feature-flag-registry.json +25 -17
- package/src/config/llm-resolver.ts +45 -15
- package/src/config/loader.ts +70 -1
- package/src/config/profile-tool-support.ts +110 -0
- package/src/config/sanitize-for-transfer.ts +11 -0
- package/src/config/schema.ts +4 -0
- package/src/config/schemas/__tests__/stt.test.ts +20 -5
- package/src/config/schemas/channels.ts +13 -0
- package/src/config/schemas/memory-retrospective.ts +25 -0
- package/src/config/schemas/plugin-updates.ts +55 -0
- package/src/config/schemas/services.ts +8 -4
- package/src/config/schemas/stt.ts +17 -5
- package/src/config/schemas/timeouts.ts +1 -1
- package/src/contacts/__tests__/guardian-delivery-reader.test.ts +16 -0
- package/src/contacts/guardian-delivery-reader.ts +29 -2
- package/src/context/compactor.ts +4 -4
- package/src/context/post-turn-tool-result-truncation.ts +32 -16
- package/src/context/strip-injections.ts +42 -0
- package/src/context/tool-result-spool.ts +32 -18
- package/src/credential-execution/ces-runtime.ts +3 -0
- package/src/credential-execution/client.ts +22 -1
- package/src/credential-execution/process-manager.test.ts +99 -0
- package/src/credential-execution/process-manager.ts +62 -16
- package/src/daemon/__tests__/abort-null-controller.test.ts +141 -5
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +8 -12
- package/src/daemon/__tests__/install-assistant-command.test.ts +234 -0
- package/src/daemon/__tests__/turn-tail-assistant-reply-notify.test.ts +2 -4
- package/src/daemon/__tests__/turn-tail-deleted-conversation.test.ts +20 -29
- package/src/daemon/channel-ui-capability.ts +4 -4
- package/src/daemon/conversation-agent-loop-handlers.ts +117 -61
- package/src/daemon/conversation-agent-loop.ts +318 -148
- package/src/daemon/conversation-attachments.ts +1 -1
- package/src/daemon/conversation-error.ts +8 -1
- package/src/daemon/conversation-initial-prompt.ts +16 -38
- package/src/daemon/conversation-lifecycle.ts +154 -32
- package/src/daemon/conversation-messaging.ts +106 -43
- package/src/daemon/conversation-process.ts +131 -33
- package/src/daemon/conversation-queue-manager.ts +10 -0
- package/src/daemon/conversation-runtime-assembly.ts +9 -4
- package/src/daemon/conversation-store.ts +52 -3
- package/src/daemon/conversation-surface-state.ts +9 -0
- package/src/daemon/conversation-surfaces.ts +403 -210
- package/src/daemon/conversation-tool-setup.ts +56 -7
- package/src/daemon/conversation-turn-finalize.ts +134 -89
- package/src/daemon/conversation.ts +111 -27
- package/src/daemon/disk-pressure-guard-lifecycle.ts +2 -2
- package/src/daemon/disk-pressure-guard.ts +3 -3
- package/src/daemon/doordash-steps.ts +5 -5
- package/src/daemon/external-plugins-bootstrap.ts +7 -1
- package/src/daemon/handlers/config-channels.ts +48 -5
- package/src/daemon/handlers/conversation-history.ts +1 -1
- package/src/daemon/handlers/conversations.ts +62 -17
- package/src/daemon/handlers/shared.ts +12 -0
- package/src/daemon/handlers/skills.ts +11 -1
- package/src/daemon/identity-helpers.ts +38 -10
- package/src/daemon/install-assistant-command.ts +322 -0
- package/src/daemon/lifecycle.ts +14 -3
- package/src/daemon/message-types/conversations.ts +6 -7
- package/src/daemon/message-types/sync.ts +1 -0
- package/src/daemon/persist-media-references.ts +23 -14
- package/src/daemon/process-message.ts +6 -6
- package/src/daemon/tool-setup-types.ts +19 -122
- package/src/daemon/tool-side-effects.ts +17 -94
- package/src/daemon/trust-context-types.ts +39 -0
- package/src/daemon/trust-context.ts +14 -6
- package/src/daemon/turn-tail-chain.ts +73 -0
- package/src/daemon/web-search-history.ts +47 -33
- package/src/heartbeat/heartbeat-service.ts +6 -6
- package/src/ipc/__tests__/socket-path.test.ts +21 -0
- package/src/ipc/assistant-server.ts +17 -10
- package/src/ipc/cli-client.ts +10 -1
- package/src/ipc/routes/__tests__/documents-sync-ipc-routes.test.ts +56 -0
- package/src/ipc/routes/documents-sync-ipc-routes.ts +42 -0
- package/src/ipc/socket-cleanup.ts +9 -7
- package/src/ipc/socket-path.ts +4 -96
- package/src/live-voice/__tests__/live-voice-archive.test.ts +16 -16
- package/src/live-voice/__tests__/live-voice-attach-image.test.ts +209 -0
- package/src/live-voice/__tests__/live-voice-connection.test.ts +20 -0
- package/src/live-voice/__tests__/live-voice-integration.test.ts +7 -5
- package/src/live-voice/__tests__/live-voice-session-telemetry.test.ts +265 -0
- package/src/live-voice/__tests__/live-voice-stt.test.ts +6 -1
- package/src/live-voice/__tests__/live-voice-vad.test.ts +35 -15
- package/src/live-voice/__tests__/protocol.test.ts +52 -0
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +3 -0
- package/src/live-voice/live-voice-archive.ts +13 -13
- package/src/live-voice/live-voice-connection.ts +7 -1
- package/src/live-voice/live-voice-photo.ts +169 -0
- package/src/live-voice/live-voice-session.ts +108 -4
- package/src/live-voice/protocol.ts +89 -1
- package/src/mcp/client.ts +10 -0
- package/src/messaging/providers/__tests__/callback-routing.test.ts +5 -1
- package/src/messaging/providers/__tests__/transport-dispatch.test.ts +66 -4
- package/src/messaging/providers/callback-routing.ts +1 -0
- package/src/messaging/providers/discord/api.ts +312 -0
- package/src/messaging/providers/discord/dm-delivery.test.ts +204 -0
- package/src/messaging/providers/discord/render.test.ts +204 -0
- package/src/messaging/providers/discord/render.ts +195 -0
- package/src/messaging/providers/discord/send.test.ts +179 -0
- package/src/messaging/providers/discord/send.ts +212 -0
- package/src/messaging/providers/discord/transport.ts +81 -0
- package/src/messaging/providers/index.ts +3 -1
- package/src/messaging/providers/retry-policy.test.ts +247 -0
- package/src/messaging/providers/retry-policy.ts +206 -0
- package/src/messaging/providers/slack/mention-source.test.ts +285 -0
- package/src/messaging/providers/slack/mention-source.ts +287 -0
- package/src/messaging/providers/telegram-bot/api.ts +47 -130
- package/src/messaging/providers/whatsapp/api.ts +47 -136
- package/src/monitoring/__tests__/db-integrity-sample.test.ts +4 -1
- package/src/monitoring/__tests__/plugin-auto-update.test.ts +332 -0
- package/src/monitoring/db-integrity-sample.ts +6 -1
- package/src/monitoring/plugin-auto-update.ts +359 -0
- package/src/monitoring/resource-sampler.ts +21 -5
- package/src/monitoring/worker.ts +13 -0
- package/src/notifications/__tests__/assistant-reply-producer.test.ts +375 -2
- package/src/notifications/__tests__/broadcaster.test.ts +37 -1
- package/src/notifications/__tests__/copy-composer.test.ts +165 -0
- package/src/notifications/__tests__/emit-signal-pipeline-failure.test.ts +205 -0
- package/src/notifications/__tests__/notification-utils.test.ts +249 -0
- package/src/notifications/adapters/platform.ts +31 -2
- package/src/notifications/assistant-reply-producer.ts +79 -32
- package/src/notifications/broadcaster.ts +30 -10
- package/src/notifications/copy-composer.ts +69 -0
- package/src/notifications/emit-signal.ts +82 -15
- package/src/notifications/events-store.ts +10 -2
- package/src/notifications/home-feed-side-effect.ts +6 -3
- package/src/notifications/notification-utils.ts +173 -5
- package/src/notifications/signal.ts +12 -0
- package/src/oauth/AGENTS.md +4 -2
- package/src/oauth/byo-connection.ts +6 -1
- package/src/oauth/credential-token-resolver.ts +3 -10
- package/src/oauth/manual-token-connection.ts +29 -64
- package/src/oauth/manual-token-providers.ts +62 -0
- package/src/oauth/provider-serializer.ts +13 -0
- package/src/oauth/seed-providers.ts +62 -11
- package/src/onboarding/onboarding-events-store.ts +91 -1
- package/src/permissions/question-prompter.test.ts +4 -0
- package/src/permissions/question-prompter.ts +21 -4
- package/src/persistence/__tests__/conversation-lineage.test.ts +248 -0
- package/src/persistence/attachments-store.ts +15 -15
- package/src/persistence/conversation-attention-store.ts +30 -10
- package/src/persistence/conversation-bootstrap.ts +17 -0
- package/src/persistence/conversation-crud.ts +363 -97
- package/src/persistence/conversation-group-migration.ts +1 -1
- package/src/persistence/conversation-key-store.ts +38 -10
- package/src/persistence/conversation-lineage.ts +226 -0
- package/src/persistence/conversation-plugin-facade.ts +28 -3
- package/src/persistence/conversation-queries.ts +207 -33
- package/src/persistence/conversation-types.ts +107 -1
- package/src/persistence/jobs-store.ts +32 -8
- package/src/persistence/llm-usage-store.ts +22 -0
- package/src/persistence/migrations/361-normalize-managed-connection-rows.test.ts +168 -0
- package/src/persistence/migrations/361-normalize-managed-connection-rows.ts +76 -0
- package/src/persistence/migrations/362-add-conversation-subagent-kind.test.ts +187 -0
- package/src/persistence/migrations/362-add-conversation-subagent-kind.ts +93 -0
- package/src/persistence/migrations/363-backfill-schedule-inference-profile.test.ts +229 -0
- package/src/persistence/migrations/363-backfill-schedule-inference-profile.ts +127 -0
- package/src/persistence/migrations/364-add-schedule-source-key.test.ts +120 -0
- package/src/persistence/migrations/364-add-schedule-source-key.ts +43 -0
- package/src/persistence/migrations/365-add-conversation-fork-strategy.ts +27 -0
- package/src/persistence/schema/conversations.ts +32 -0
- package/src/persistence/schema/infrastructure.ts +3 -0
- package/src/persistence/steps.ts +30 -0
- package/src/persistence/subagent-store.ts +148 -6
- package/src/platform/managed-speech.test.ts +20 -0
- package/src/platform/managed-speech.ts +9 -0
- package/src/plugin-api/index.ts +8 -0
- package/src/plugin-api/webhook-url.ts +151 -0
- package/src/plugins/__tests__/installed-plugin-dirs.test.ts +82 -0
- package/src/plugins/__tests__/source-fingerprint.test.ts +5 -1
- package/src/plugins/collect-source-versions.ts +4 -27
- package/src/plugins/defaults/exploration-drift/hooks/post-tool-use.ts +5 -5
- package/src/plugins/defaults/exploration-drift/package.json +1 -1
- package/src/plugins/defaults/image-recovery/hooks/post-model-call.ts +4 -2
- package/src/plugins/defaults/image-recovery/recover.ts +67 -57
- package/src/plugins/defaults/index.ts +1 -1
- package/src/plugins/defaults/memory/__tests__/conversation-queries.test.ts +64 -18
- package/src/plugins/defaults/memory/__tests__/jobs-worker-outcome-contract.test.ts +242 -0
- package/src/plugins/defaults/memory/__tests__/jobs-worker-retrospective-sweep.test.ts +24 -1
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +48 -3
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +511 -19
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +39 -3
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-provider-path.test.ts +493 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-wake-chain.test.ts +5 -4
- package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +5 -1
- package/src/plugins/defaults/memory/job-handlers.ts +87 -5
- package/src/plugins/defaults/memory/jobs-worker.ts +60 -6
- package/src/plugins/defaults/memory/memory-retrospective-constants.ts +11 -0
- package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +29 -0
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +342 -60
- package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +23 -3
- package/src/plugins/defaults/memory/substrate/consolidation-lock.ts +9 -4
- package/src/plugins/defaults/memory/substrate/sweep-job.ts +7 -0
- package/src/plugins/defaults/memory/v1/graph/injection.ts +1 -1
- package/src/plugins/defaults/memory/v2/router.ts +8 -0
- package/src/plugins/defaults/turn-context/unified-turn-context.ts +1 -2
- package/src/plugins/external-plugin-loader.ts +17 -8
- package/src/plugins/installed-plugin-dirs.ts +101 -0
- package/src/plugins/mtime-cache.ts +34 -22
- package/src/plugins/types.ts +69 -8
- package/src/prompts/persona-resolver.ts +6 -2
- package/src/prompts/system-prompt.ts +72 -17
- package/src/providers/__tests__/inference.test.ts +40 -0
- package/src/providers/__tests__/preflight-resolved-config.test.ts +58 -1
- package/src/providers/__tests__/retry-callsite.test.ts +67 -0
- package/src/providers/__tests__/vellum-connection-routing.test.ts +42 -11
- package/src/providers/anthropic/client.ts +112 -95
- package/src/providers/connection-resolution.ts +35 -1
- package/src/providers/gemini/client.ts +5 -5
- package/src/providers/inference/adapter-factory.ts +16 -10
- package/src/providers/inference/auth.ts +16 -0
- package/src/providers/inference/connection-availability.ts +164 -12
- package/src/providers/inference/connections.ts +25 -1
- package/src/providers/media-resolve.ts +21 -11
- package/src/providers/model-catalog.ts +15 -0
- package/src/providers/openai/chat-completions-provider.ts +4 -4
- package/src/providers/openai/responses-provider.ts +12 -25
- package/src/providers/registry.ts +9 -4
- package/src/providers/retry.ts +25 -0
- package/src/providers/server-tool-pairing.ts +134 -0
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +187 -6
- package/src/providers/speech-to-text/deepgram.ts +1 -0
- package/src/providers/speech-to-text/resolve.ts +80 -10
- package/src/providers/speech-to-text/vellum-managed.ts +7 -1
- package/src/providers/speech-to-text/vellum-speech-relay-connection.ts +3 -1
- package/src/providers/types.ts +26 -6
- package/src/providers/vellum-model-routing.ts +6 -7
- package/src/runtime/AGENTS.md +2 -0
- package/src/runtime/__tests__/agent-wake.test.ts +16 -16
- package/src/runtime/__tests__/background-job-runner.test.ts +0 -144
- package/src/runtime/__tests__/desktop-presence.test.ts +162 -0
- package/src/runtime/agent-wake.ts +63 -24
- package/src/runtime/assistant-event-hub.ts +87 -12
- package/src/runtime/auth/__tests__/guard-tests.test.ts +2 -0
- package/src/runtime/auth/__tests__/scopes.test.ts +20 -0
- package/src/runtime/auth/same-actor.ts +56 -8
- package/src/runtime/auth/scopes.ts +12 -0
- package/src/runtime/auth/types.ts +2 -0
- package/src/runtime/background-job-runner.ts +5 -27
- package/src/runtime/channel-readiness-service.ts +59 -3
- package/src/runtime/channel-readiness-types.ts +18 -0
- package/src/runtime/desktop-presence.ts +69 -0
- package/src/runtime/http-server.ts +12 -0
- package/src/runtime/local-actor-identity.ts +11 -9
- package/src/runtime/migrations/__tests__/vbundle-symlink-streaming-importer.test.ts +0 -0
- package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/client-routes.test.ts +186 -14
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +547 -1
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +162 -7
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +14 -10
- package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +340 -3
- package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +28 -1
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +173 -1
- package/src/runtime/routes/__tests__/question-routes.test.ts +64 -0
- package/src/runtime/routes/__tests__/retrospective-routes.test.ts +20 -0
- package/src/runtime/routes/__tests__/skill-history-route.test.ts +116 -0
- package/src/runtime/routes/__tests__/wake-conversation-routes.test.ts +60 -2
- package/src/runtime/routes/archive-utils.ts +16 -12
- package/src/runtime/routes/attachment-routes.ts +13 -6
- package/src/runtime/routes/canned-reply-release.ts +54 -0
- package/src/runtime/routes/channel-verification-routes.ts +2 -27
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +5 -0
- package/src/runtime/routes/client-routes.ts +114 -2
- package/src/runtime/routes/conversation-cli-routes.ts +10 -12
- package/src/runtime/routes/conversation-list-routes.ts +59 -10
- package/src/runtime/routes/conversation-management-routes.ts +47 -18
- package/src/runtime/routes/conversation-query-routes.ts +32 -53
- package/src/runtime/routes/conversation-routes.ts +360 -293
- package/src/runtime/routes/credential-prompt-routes.ts +23 -2
- package/src/runtime/routes/debug-routes.ts +4 -1
- package/src/runtime/routes/default-provider-routes.ts +7 -11
- package/src/runtime/routes/documents-routes.ts +44 -1
- package/src/runtime/routes/events-routes.ts +28 -1
- package/src/runtime/routes/host-app-control-routes.ts +2 -0
- package/src/runtime/routes/host-bash-routes.ts +2 -0
- package/src/runtime/routes/host-browser-routes.ts +2 -0
- package/src/runtime/routes/host-cu-routes.ts +2 -0
- package/src/runtime/routes/host-file-routes.ts +2 -0
- package/src/runtime/routes/host-transfer-routes.ts +4 -0
- package/src/runtime/routes/identity-routes.ts +6 -6
- package/src/runtime/routes/inbound-message-handler.ts +5 -5
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +7 -3
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +14 -0
- package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +2 -2
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +14 -11
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +14 -17
- package/src/runtime/routes/inference-profile-availability-guard.ts +171 -0
- package/src/runtime/routes/inference-profile-session-handler.ts +26 -2
- package/src/runtime/routes/inference-profile-session-routes.ts +2 -1
- package/src/runtime/routes/inference-profiles-routes.ts +152 -73
- package/src/runtime/routes/inference-provider-connection-routes.ts +0 -16
- package/src/runtime/routes/llm-call-sites-routes.ts +13 -0
- package/src/runtime/routes/log-export-routes.ts +1 -1
- package/src/runtime/routes/notification-routes.ts +0 -14
- package/src/runtime/routes/oauth-providers.ts +1 -0
- package/src/runtime/routes/plugins-routes.ts +106 -1
- package/src/runtime/routes/profiler-routes.ts +4 -2
- package/src/runtime/routes/question-routes.ts +28 -10
- package/src/runtime/routes/retrospective-routes.ts +9 -3
- package/src/runtime/routes/schedule-routes.ts +210 -12
- package/src/runtime/routes/secret-routes.ts +40 -23
- package/src/runtime/routes/settings-routes.ts +41 -13
- package/src/runtime/routes/skills-routes.ts +79 -0
- package/src/runtime/routes/ui-snapshot-routes.ts +1 -0
- package/src/runtime/routes/wake-conversation-routes.ts +23 -0
- package/src/runtime/services/__tests__/conversation-serializer.test.ts +1 -0
- package/src/runtime/services/conversation-serializer.ts +24 -9
- package/src/runtime/sync/documents-sidecar-publish.test.ts +101 -0
- package/src/runtime/sync/resource-sync-events.ts +79 -1
- package/src/runtime/sync/worker-daemon-notify.test.ts +34 -0
- package/src/runtime/sync/worker-daemon-notify.ts +44 -6
- package/src/runtime/verification-outbound-actions.ts +250 -222
- package/src/runtime/verification-templates.ts +41 -30
- package/src/schedule/__tests__/plugin-schedule-declarations.test.ts +614 -0
- package/src/schedule/__tests__/plugin-schedule-reconciler.test.ts +1066 -0
- package/src/schedule/inference-profile.ts +64 -3
- package/src/schedule/plugin-schedule-declarations.ts +518 -0
- package/src/schedule/plugin-schedule-reconciler.ts +605 -0
- package/src/schedule/plugin-schedules-gate.ts +23 -0
- package/src/schedule/schedule-store.ts +520 -26
- package/src/schedule/scheduler.ts +38 -0
- package/src/security/credential-backend.ts +51 -4
- package/src/security/encrypted-store.ts +64 -42
- package/src/security/secure-keys.ts +55 -7
- package/src/skills/catalog-install.ts +20 -7
- package/src/skills/inline-command-runner.ts +2 -7
- package/src/skills/skill-history.test.ts +269 -0
- package/src/skills/skill-history.ts +250 -0
- package/src/skills/skillssh-registry.ts +1 -1
- package/src/stt/daemon-batch-transcriber.ts +8 -6
- package/src/subagent/__tests__/consult-prompt.test.ts +25 -0
- package/src/subagent/consult-prompt.ts +3 -1
- package/src/subagent/consult-transcript.ts +1 -1
- package/src/subagent/manager.ts +304 -44
- package/src/subagent/progress-events.ts +35 -0
- package/src/subagent/role-resolution.ts +88 -0
- package/src/subagent/types.ts +302 -67
- package/src/subagent/validate-allowlists.ts +3 -4
- package/src/telegram/__tests__/webhook-health.test.ts +73 -1
- package/src/telegram/webhook-health.ts +101 -3
- package/src/telemetry/__tests__/telemetry-event-fixtures.ts +2 -0
- package/src/telemetry/activation-funnel.ts +6 -1
- package/src/telemetry/live-voice-funnel.ts +75 -0
- package/src/telemetry/telemetry-event-sources.ts +6 -0
- package/src/telemetry/telemetry-wire-source.json +1 -1
- package/src/telemetry/telemetry-wire.generated.ts +2 -0
- package/src/telemetry/types.ts +23 -4
- package/src/telemetry/usage-telemetry-reporter.test.ts +4 -0
- package/src/tools/__tests__/subagent-workflow-tool-input-schemas.test.ts +1 -1
- package/src/tools/ask-question/ask-question-tool.test.ts +118 -3
- package/src/tools/ask-question/ask-question-tool.ts +56 -2
- package/src/tools/browser/browser-execution.ts +1 -1
- package/src/tools/calls/call-start.ts +8 -5
- package/src/tools/conversation-groups/move_to_group.ts +10 -12
- package/src/tools/document/document-tool.ts +11 -4
- package/src/tools/execution-timeout.ts +9 -2
- package/src/tools/executor.ts +7 -6
- package/src/tools/filesystem/edit.ts +1 -1
- package/src/tools/filesystem/list.ts +1 -1
- package/src/tools/filesystem/read.ts +7 -13
- package/src/tools/filesystem/search.ts +23 -21
- package/src/tools/filesystem/write.ts +4 -1
- package/src/tools/host-filesystem/edit.ts +7 -2
- package/src/tools/host-filesystem/read.ts +21 -8
- package/src/tools/host-filesystem/write.ts +10 -2
- package/src/tools/host-terminal/host-shell.ts +2 -2
- package/src/tools/mcp/mcp-tool-factory.ts +25 -1
- package/src/tools/permission-checker.ts +8 -3
- package/src/tools/schedule/delete.ts +13 -1
- package/src/tools/schedule/list.ts +14 -3
- package/src/tools/schedule/update.ts +56 -33
- package/src/tools/shared/filesystem/audio-read.ts +6 -4
- package/src/tools/shared/filesystem/file-ops-service.ts +176 -116
- package/src/tools/shared/filesystem/image-read.ts +12 -12
- package/src/tools/shared/filesystem/path-policy.ts +70 -5
- package/src/tools/shared/filesystem/size-guard.ts +6 -6
- package/src/tools/shared/input-misuse.ts +72 -0
- package/src/tools/skills/scaffold-managed.ts +82 -0
- package/src/tools/skills/skill-tool-factory.ts +14 -1
- package/src/tools/subagent/consult-deadline.ts +12 -7
- package/src/tools/subagent/message.ts +3 -1
- package/src/tools/subagent/read.ts +66 -4
- package/src/tools/subagent/spawn.ts +500 -78
- package/src/tools/tool-approval-handler.ts +45 -4
- package/src/tools/types.ts +22 -3
- package/src/tools/ui-surface/surface-shape-docs.ts +1 -1
- package/src/tools/ui-surface/visual-validation.ts +2 -0
- package/src/usage/__tests__/subagent-attribution.test.ts +109 -0
- package/src/usage/subagent-attribution.ts +108 -0
- package/src/util/__tests__/sqlite-retry.test.ts +112 -0
- package/src/util/abort-reasons.ts +16 -0
- package/src/util/ansi.ts +44 -0
- package/src/util/disk-usage.ts +17 -13
- package/src/util/image-conversion.ts +20 -13
- package/src/util/schedule-source-key.ts +23 -0
- package/src/util/worker-process.ts +7 -1
- package/src/workspace/git-service.ts +33 -9
- package/src/workspace/migrations/140-repair-seed-pinned-memory-v3-live.ts +260 -0
- package/src/workspace/migrations/141-stt-english-default-to-multilingual.ts +111 -0
- package/src/workspace/migrations/__tests__/141-stt-english-default-to-multilingual.test.ts +126 -0
- package/src/workspace/migrations/registry.ts +4 -0
- package/src/workspace/top-level-renderer.ts +15 -2
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +0 -357
- package/src/daemon/install-symlink.ts +0 -207
- package/src/notifications/deferred-emit.ts +0 -147
|
@@ -134,10 +134,10 @@ function advanceGlobalSeq(count: number): void {
|
|
|
134
134
|
}
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
-
function callList(query: Record<string, string>): ListResponse {
|
|
138
|
-
return handleListMessages({
|
|
137
|
+
async function callList(query: Record<string, string>): Promise<ListResponse> {
|
|
138
|
+
return (await handleListMessages({
|
|
139
139
|
queryParams: query,
|
|
140
|
-
}) as unknown as ListResponse;
|
|
140
|
+
})) as unknown as ListResponse;
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
describe("handleListMessages page=latest", () => {
|
|
@@ -148,7 +148,7 @@ describe("handleListMessages page=latest", () => {
|
|
|
148
148
|
});
|
|
149
149
|
|
|
150
150
|
describe("persisted seq", () => {
|
|
151
|
-
test("getMaxPersistedConversationSeq reports the highest anchor across conversations", () => {
|
|
151
|
+
test("getMaxPersistedConversationSeq reports the highest anchor across conversations", async () => {
|
|
152
152
|
/**
|
|
153
153
|
* The startup seq floor resumes issuance above this value, so it
|
|
154
154
|
* must reflect the highest anchor any conversation has served.
|
|
@@ -161,7 +161,7 @@ describe("handleListMessages page=latest", () => {
|
|
|
161
161
|
expect(getMaxPersistedConversationSeq()).toBe(907779);
|
|
162
162
|
});
|
|
163
163
|
|
|
164
|
-
test("returns the recorded persisted seq for the conversation", () => {
|
|
164
|
+
test("returns the recorded persisted seq for the conversation", async () => {
|
|
165
165
|
/**
|
|
166
166
|
* The snapshot must advertise the `seq` of the last durably-persisted
|
|
167
167
|
* event so a client can align it with the `/events` stream.
|
|
@@ -174,13 +174,13 @@ describe("handleListMessages page=latest", () => {
|
|
|
174
174
|
recordConversationPersistedSeq(conv.id, 42);
|
|
175
175
|
|
|
176
176
|
// WHEN the snapshot is fetched
|
|
177
|
-
const body = callList({ conversationId: conv.id, page: "latest" });
|
|
177
|
+
const body = await callList({ conversationId: conv.id, page: "latest" });
|
|
178
178
|
|
|
179
179
|
// THEN the response carries that seq
|
|
180
180
|
expect(body.seq).toBe(42);
|
|
181
181
|
});
|
|
182
182
|
|
|
183
|
-
test("returns null seq when nothing has been persisted in-process", () => {
|
|
183
|
+
test("returns null seq when nothing has been persisted in-process", async () => {
|
|
184
184
|
/**
|
|
185
185
|
* A cold conversation (or one aged out / post-restart) reports no seq,
|
|
186
186
|
* signalling the client to cold-start rather than align to a stale
|
|
@@ -192,13 +192,13 @@ describe("handleListMessages page=latest", () => {
|
|
|
192
192
|
seedMessages(conv.id, 2);
|
|
193
193
|
|
|
194
194
|
// WHEN the snapshot is fetched
|
|
195
|
-
const body = callList({ conversationId: conv.id, page: "latest" });
|
|
195
|
+
const body = await callList({ conversationId: conv.id, page: "latest" });
|
|
196
196
|
|
|
197
197
|
// THEN seq is null
|
|
198
198
|
expect(body.seq).toBeNull();
|
|
199
199
|
});
|
|
200
200
|
|
|
201
|
-
test("the no-pagination path also returns the persisted seq", () => {
|
|
201
|
+
test("the no-pagination path also returns the persisted seq", async () => {
|
|
202
202
|
/** `seq` is present on every resolved-conversation response shape. */
|
|
203
203
|
|
|
204
204
|
// GIVEN a conversation with a recorded persisted seq
|
|
@@ -207,13 +207,13 @@ describe("handleListMessages page=latest", () => {
|
|
|
207
207
|
recordConversationPersistedSeq(conv.id, 7);
|
|
208
208
|
|
|
209
209
|
// WHEN fetched with no pagination params
|
|
210
|
-
const body = callList({ conversationId: conv.id });
|
|
210
|
+
const body = await callList({ conversationId: conv.id });
|
|
211
211
|
|
|
212
212
|
// THEN the seq still rides along
|
|
213
213
|
expect(body.seq).toBe(7);
|
|
214
214
|
});
|
|
215
215
|
|
|
216
|
-
test("recording advances the seq monotonically and never regresses", () => {
|
|
216
|
+
test("recording advances the seq monotonically and never regresses", async () => {
|
|
217
217
|
/**
|
|
218
218
|
* Out-of-order async commits must not lower the high-water mark — the
|
|
219
219
|
* `WHERE seq < ?` guard on the persist UPDATE keeps it monotonic.
|
|
@@ -227,14 +227,14 @@ describe("handleListMessages page=latest", () => {
|
|
|
227
227
|
recordConversationPersistedSeq(conv.id, 8);
|
|
228
228
|
|
|
229
229
|
// THEN the high-water seq is unchanged
|
|
230
|
-
expect(callList({ conversationId: conv.id }).seq).toBe(12);
|
|
230
|
+
expect((await callList({ conversationId: conv.id })).seq).toBe(12);
|
|
231
231
|
|
|
232
232
|
// AND a higher seq still advances it
|
|
233
233
|
recordConversationPersistedSeq(conv.id, 20);
|
|
234
|
-
expect(callList({ conversationId: conv.id }).seq).toBe(20);
|
|
234
|
+
expect((await callList({ conversationId: conv.id })).seq).toBe(20);
|
|
235
235
|
});
|
|
236
236
|
|
|
237
|
-
test("recording ignores non-positive and non-finite seq values", () => {
|
|
237
|
+
test("recording ignores non-positive and non-finite seq values", async () => {
|
|
238
238
|
// GIVEN a freshly created conversation (no stream activity → null seed)
|
|
239
239
|
const conv = createConversation();
|
|
240
240
|
|
|
@@ -245,10 +245,10 @@ describe("handleListMessages page=latest", () => {
|
|
|
245
245
|
recordConversationPersistedSeq(conv.id, Number.POSITIVE_INFINITY);
|
|
246
246
|
|
|
247
247
|
// THEN none take effect and seq stays null
|
|
248
|
-
expect(callList({ conversationId: conv.id }).seq).toBeNull();
|
|
248
|
+
expect((await callList({ conversationId: conv.id })).seq).toBeNull();
|
|
249
249
|
});
|
|
250
250
|
|
|
251
|
-
test("a freshly created conversation is anchored to the current global seq", () => {
|
|
251
|
+
test("a freshly created conversation is anchored to the current global seq", async () => {
|
|
252
252
|
/**
|
|
253
253
|
* Conversations created after some stream activity must not report a
|
|
254
254
|
* null `seq` — that would force the client to cold-start with no
|
|
@@ -262,13 +262,13 @@ describe("handleListMessages page=latest", () => {
|
|
|
262
262
|
|
|
263
263
|
// WHEN a brand-new conversation is created and its snapshot fetched
|
|
264
264
|
const conv = createConversation();
|
|
265
|
-
const body = callList({ conversationId: conv.id, page: "latest" });
|
|
265
|
+
const body = await callList({ conversationId: conv.id, page: "latest" });
|
|
266
266
|
|
|
267
267
|
// THEN the snapshot is anchored to the global seq at creation time
|
|
268
268
|
expect(body.seq).toBe(5);
|
|
269
269
|
});
|
|
270
270
|
|
|
271
|
-
test("a conversation created before any stream activity stays null", () => {
|
|
271
|
+
test("a conversation created before any stream activity stays null", async () => {
|
|
272
272
|
/**
|
|
273
273
|
* With nothing stamped this process, `getCurrentSeq()` is 0 and the
|
|
274
274
|
* creation seed stores NULL (non-positive seqs aren't recorded), so the
|
|
@@ -280,7 +280,7 @@ describe("handleListMessages page=latest", () => {
|
|
|
280
280
|
|
|
281
281
|
// WHEN a conversation is created and its snapshot fetched
|
|
282
282
|
const conv = createConversation();
|
|
283
|
-
const body = callList({ conversationId: conv.id, page: "latest" });
|
|
283
|
+
const body = await callList({ conversationId: conv.id, page: "latest" });
|
|
284
284
|
|
|
285
285
|
// THEN seq remains null
|
|
286
286
|
expect(body.seq).toBeNull();
|
|
@@ -288,7 +288,7 @@ describe("handleListMessages page=latest", () => {
|
|
|
288
288
|
});
|
|
289
289
|
|
|
290
290
|
describe("processing state", () => {
|
|
291
|
-
test("reports processing=true while the conversation is mid-turn", () => {
|
|
291
|
+
test("reports processing=true while the conversation is mid-turn", async () => {
|
|
292
292
|
/**
|
|
293
293
|
* The authoritative processing flag lets a client recover from a
|
|
294
294
|
* dropped stream: it can ask the server whether a turn is still
|
|
@@ -301,25 +301,25 @@ describe("handleListMessages page=latest", () => {
|
|
|
301
301
|
setConversationProcessingStartedAt(conv.id, Date.now());
|
|
302
302
|
|
|
303
303
|
// WHEN the snapshot is fetched
|
|
304
|
-
const body = callList({ conversationId: conv.id, page: "latest" });
|
|
304
|
+
const body = await callList({ conversationId: conv.id, page: "latest" });
|
|
305
305
|
|
|
306
306
|
// THEN it reports the conversation is processing
|
|
307
307
|
expect(body.processing).toBe(true);
|
|
308
308
|
});
|
|
309
309
|
|
|
310
|
-
test("reports processing=false when the conversation is idle", () => {
|
|
310
|
+
test("reports processing=false when the conversation is idle", async () => {
|
|
311
311
|
// GIVEN an idle conversation (processing_started_at is null)
|
|
312
312
|
const conv = createConversation();
|
|
313
313
|
seedMessages(conv.id, 2);
|
|
314
314
|
|
|
315
315
|
// WHEN the snapshot is fetched
|
|
316
|
-
const body = callList({ conversationId: conv.id, page: "latest" });
|
|
316
|
+
const body = await callList({ conversationId: conv.id, page: "latest" });
|
|
317
317
|
|
|
318
318
|
// THEN it reports the conversation is not processing
|
|
319
319
|
expect(body.processing).toBe(false);
|
|
320
320
|
});
|
|
321
321
|
|
|
322
|
-
test("the no-pagination path also reports processing state", () => {
|
|
322
|
+
test("the no-pagination path also reports processing state", async () => {
|
|
323
323
|
/** `processing` is present on every resolved-conversation shape. */
|
|
324
324
|
|
|
325
325
|
// GIVEN a processing conversation
|
|
@@ -328,15 +328,15 @@ describe("handleListMessages page=latest", () => {
|
|
|
328
328
|
setConversationProcessingStartedAt(conv.id, Date.now());
|
|
329
329
|
|
|
330
330
|
// WHEN fetched with no pagination params
|
|
331
|
-
const body = callList({ conversationId: conv.id });
|
|
331
|
+
const body = await callList({ conversationId: conv.id });
|
|
332
332
|
|
|
333
333
|
// THEN processing rides along
|
|
334
334
|
expect(body.processing).toBe(true);
|
|
335
335
|
});
|
|
336
336
|
|
|
337
|
-
test("an unresolved conversationKey reports processing=false (page=latest)", () => {
|
|
337
|
+
test("an unresolved conversationKey reports processing=false (page=latest)", async () => {
|
|
338
338
|
// WHEN a never-created key is fetched with the stable contract
|
|
339
|
-
const body = callList({
|
|
339
|
+
const body = await callList({
|
|
340
340
|
conversationKey: "no-such-key",
|
|
341
341
|
page: "latest",
|
|
342
342
|
});
|
|
@@ -346,11 +346,11 @@ describe("handleListMessages page=latest", () => {
|
|
|
346
346
|
});
|
|
347
347
|
});
|
|
348
348
|
|
|
349
|
-
test("page=latest with no limit returns all messages chronologically", () => {
|
|
349
|
+
test("page=latest with no limit returns all messages chronologically", async () => {
|
|
350
350
|
const conv = createConversation();
|
|
351
351
|
seedMessages(conv.id, 120);
|
|
352
352
|
|
|
353
|
-
const body = callList({ conversationId: conv.id, page: "latest" });
|
|
353
|
+
const body = await callList({ conversationId: conv.id, page: "latest" });
|
|
354
354
|
|
|
355
355
|
expect(body.messages).toHaveLength(120);
|
|
356
356
|
expect(body.messages[0].id).toBe("msg-1");
|
|
@@ -360,11 +360,11 @@ describe("handleListMessages page=latest", () => {
|
|
|
360
360
|
expect(body.oldestMessageId).toBe("msg-1");
|
|
361
361
|
});
|
|
362
362
|
|
|
363
|
-
test("page=latest&limit=50 with 120 seeded messages returns newest 50 chronologically", () => {
|
|
363
|
+
test("page=latest&limit=50 with 120 seeded messages returns newest 50 chronologically", async () => {
|
|
364
364
|
const conv = createConversation();
|
|
365
365
|
seedMessages(conv.id, 120);
|
|
366
366
|
|
|
367
|
-
const body = callList({
|
|
367
|
+
const body = await callList({
|
|
368
368
|
conversationId: conv.id,
|
|
369
369
|
page: "latest",
|
|
370
370
|
limit: "50",
|
|
@@ -379,11 +379,11 @@ describe("handleListMessages page=latest", () => {
|
|
|
379
379
|
expect(body.oldestMessageId).toBe("msg-71");
|
|
380
380
|
});
|
|
381
381
|
|
|
382
|
-
test("page=latest&limit=50 with 10 seeded messages returns all 10 with hasMore=false", () => {
|
|
382
|
+
test("page=latest&limit=50 with 10 seeded messages returns all 10 with hasMore=false", async () => {
|
|
383
383
|
const conv = createConversation();
|
|
384
384
|
seedMessages(conv.id, 10);
|
|
385
385
|
|
|
386
|
-
const body = callList({
|
|
386
|
+
const body = await callList({
|
|
387
387
|
conversationId: conv.id,
|
|
388
388
|
page: "latest",
|
|
389
389
|
limit: "50",
|
|
@@ -397,20 +397,20 @@ describe("handleListMessages page=latest", () => {
|
|
|
397
397
|
expect(body.oldestMessageId).toBe("msg-1");
|
|
398
398
|
});
|
|
399
399
|
|
|
400
|
-
test("beforeTimestamp wins when combined with page=latest", () => {
|
|
400
|
+
test("beforeTimestamp wins when combined with page=latest", async () => {
|
|
401
401
|
const conv = createConversation();
|
|
402
402
|
seedMessages(conv.id, 120);
|
|
403
403
|
|
|
404
404
|
// beforeTimestamp=100 + limit=50 should return msgs 50..99 (the 50 messages
|
|
405
405
|
// immediately older than ts=100), regardless of the page=latest signal.
|
|
406
|
-
const combinedBody = callList({
|
|
406
|
+
const combinedBody = await callList({
|
|
407
407
|
conversationId: conv.id,
|
|
408
408
|
page: "latest",
|
|
409
409
|
limit: "50",
|
|
410
410
|
beforeTimestamp: "100",
|
|
411
411
|
});
|
|
412
412
|
|
|
413
|
-
const beforeOnlyBody = callList({
|
|
413
|
+
const beforeOnlyBody = await callList({
|
|
414
414
|
conversationId: conv.id,
|
|
415
415
|
limit: "50",
|
|
416
416
|
beforeTimestamp: "100",
|
|
@@ -428,10 +428,10 @@ describe("handleListMessages page=latest", () => {
|
|
|
428
428
|
expect(combinedBody.messages[49].id).toBe("msg-99");
|
|
429
429
|
});
|
|
430
430
|
|
|
431
|
-
test("page=latest on empty conversation returns null pagination metadata", () => {
|
|
431
|
+
test("page=latest on empty conversation returns null pagination metadata", async () => {
|
|
432
432
|
const conv = createConversation();
|
|
433
433
|
|
|
434
|
-
const body = callList({ conversationId: conv.id, page: "latest" });
|
|
434
|
+
const body = await callList({ conversationId: conv.id, page: "latest" });
|
|
435
435
|
|
|
436
436
|
expect(body.messages).toEqual([]);
|
|
437
437
|
expect(body.hasMore).toBe(false);
|
|
@@ -439,7 +439,7 @@ describe("handleListMessages page=latest", () => {
|
|
|
439
439
|
expect(body.oldestMessageId).toBeNull();
|
|
440
440
|
});
|
|
441
441
|
|
|
442
|
-
test("messages expose Slack message and thread links from slackMeta", () => {
|
|
442
|
+
test("messages expose Slack message and thread links from slackMeta", async () => {
|
|
443
443
|
const conv = createConversation();
|
|
444
444
|
const db = getDb();
|
|
445
445
|
db.insert(messages)
|
|
@@ -464,7 +464,7 @@ describe("handleListMessages page=latest", () => {
|
|
|
464
464
|
})
|
|
465
465
|
.run();
|
|
466
466
|
|
|
467
|
-
const body = callList({ conversationId: conv.id, page: "latest" });
|
|
467
|
+
const body = await callList({ conversationId: conv.id, page: "latest" });
|
|
468
468
|
|
|
469
469
|
expect(body.messages[0].slackMessage).toEqual({
|
|
470
470
|
channelId: "C123ABCDEF",
|
|
@@ -491,7 +491,7 @@ describe("handleListMessages page=latest", () => {
|
|
|
491
491
|
});
|
|
492
492
|
});
|
|
493
493
|
|
|
494
|
-
test("top-level Slack messages with matching threadTs use plain permalinks", () => {
|
|
494
|
+
test("top-level Slack messages with matching threadTs use plain permalinks", async () => {
|
|
495
495
|
const conv = createConversation();
|
|
496
496
|
const db = getDb();
|
|
497
497
|
db.insert(messages)
|
|
@@ -516,7 +516,7 @@ describe("handleListMessages page=latest", () => {
|
|
|
516
516
|
})
|
|
517
517
|
.run();
|
|
518
518
|
|
|
519
|
-
const body = callList({ conversationId: conv.id, page: "latest" });
|
|
519
|
+
const body = await callList({ conversationId: conv.id, page: "latest" });
|
|
520
520
|
|
|
521
521
|
expect(body.messages[0].slackMessage).toEqual({
|
|
522
522
|
channelId: "C123ABCDEF",
|
|
@@ -537,7 +537,7 @@ describe("handleListMessages page=latest", () => {
|
|
|
537
537
|
});
|
|
538
538
|
});
|
|
539
539
|
|
|
540
|
-
test("assistant Slack messages without stored sender use the assistant name", () => {
|
|
540
|
+
test("assistant Slack messages without stored sender use the assistant name", async () => {
|
|
541
541
|
mockAssistantName = "Nova";
|
|
542
542
|
const conv = createConversation();
|
|
543
543
|
const db = getDb();
|
|
@@ -559,14 +559,14 @@ describe("handleListMessages page=latest", () => {
|
|
|
559
559
|
})
|
|
560
560
|
.run();
|
|
561
561
|
|
|
562
|
-
const body = callList({ conversationId: conv.id, page: "latest" });
|
|
562
|
+
const body = await callList({ conversationId: conv.id, page: "latest" });
|
|
563
563
|
|
|
564
564
|
expect(body.messages[0].slackMessage?.sender).toEqual({
|
|
565
565
|
displayName: "Nova",
|
|
566
566
|
});
|
|
567
567
|
});
|
|
568
568
|
|
|
569
|
-
test("user Slack messages without stored sender do not use the assistant name", () => {
|
|
569
|
+
test("user Slack messages without stored sender do not use the assistant name", async () => {
|
|
570
570
|
mockAssistantName = "Nova";
|
|
571
571
|
const conv = createConversation();
|
|
572
572
|
const db = getDb();
|
|
@@ -588,13 +588,13 @@ describe("handleListMessages page=latest", () => {
|
|
|
588
588
|
})
|
|
589
589
|
.run();
|
|
590
590
|
|
|
591
|
-
const body = callList({ conversationId: conv.id, page: "latest" });
|
|
591
|
+
const body = await callList({ conversationId: conv.id, page: "latest" });
|
|
592
592
|
|
|
593
593
|
expect(body.messages[0].slackMessage?.sender).toBeUndefined();
|
|
594
594
|
});
|
|
595
595
|
|
|
596
|
-
test("page=latest on unresolved conversationKey returns null metadata contract", () => {
|
|
597
|
-
const body = callList({
|
|
596
|
+
test("page=latest on unresolved conversationKey returns null metadata contract", async () => {
|
|
597
|
+
const body = await callList({
|
|
598
598
|
conversationKey: "no-such-key",
|
|
599
599
|
page: "latest",
|
|
600
600
|
});
|
|
@@ -605,8 +605,8 @@ describe("handleListMessages page=latest", () => {
|
|
|
605
605
|
expect(body.oldestMessageId).toBeNull();
|
|
606
606
|
});
|
|
607
607
|
|
|
608
|
-
test("no-page GET on unresolved conversationKey keeps minimal shape", () => {
|
|
609
|
-
const body = callList({ conversationKey: "no-such-key" });
|
|
608
|
+
test("no-page GET on unresolved conversationKey keeps minimal shape", async () => {
|
|
609
|
+
const body = await callList({ conversationKey: "no-such-key" });
|
|
610
610
|
|
|
611
611
|
expect(body.messages).toEqual([]);
|
|
612
612
|
expect("hasMore" in body).toBe(false);
|
|
@@ -614,26 +614,26 @@ describe("handleListMessages page=latest", () => {
|
|
|
614
614
|
expect("oldestMessageId" in body).toBe(false);
|
|
615
615
|
});
|
|
616
616
|
|
|
617
|
-
test("page=invalid throws BadRequestError", () => {
|
|
617
|
+
test("page=invalid throws BadRequestError", async () => {
|
|
618
618
|
const conv = createConversation();
|
|
619
619
|
|
|
620
|
-
expect(
|
|
620
|
+
await expect(
|
|
621
621
|
handleListMessages({
|
|
622
622
|
queryParams: { conversationId: conv.id, page: "invalid" },
|
|
623
623
|
}),
|
|
624
|
-
).toThrow(BadRequestError);
|
|
625
|
-
expect(
|
|
624
|
+
).rejects.toThrow(BadRequestError);
|
|
625
|
+
await expect(
|
|
626
626
|
handleListMessages({
|
|
627
627
|
queryParams: { conversationId: conv.id, page: "invalid" },
|
|
628
628
|
}),
|
|
629
|
-
).toThrow("page must be 'latest' when provided");
|
|
629
|
+
).rejects.toThrow("page must be 'latest' when provided");
|
|
630
630
|
});
|
|
631
631
|
|
|
632
|
-
test("no-param GET returns full history without pagination metadata", () => {
|
|
632
|
+
test("no-param GET returns full history without pagination metadata", async () => {
|
|
633
633
|
const conv = createConversation();
|
|
634
634
|
seedMessages(conv.id, 5);
|
|
635
635
|
|
|
636
|
-
const body = callList({ conversationId: conv.id });
|
|
636
|
+
const body = await callList({ conversationId: conv.id });
|
|
637
637
|
|
|
638
638
|
expect(body.messages).toHaveLength(5);
|
|
639
639
|
expect(body.messages[0].id).toBe("msg-1");
|
|
@@ -644,12 +644,12 @@ describe("handleListMessages page=latest", () => {
|
|
|
644
644
|
expect("oldestMessageId" in body).toBe(false);
|
|
645
645
|
});
|
|
646
646
|
|
|
647
|
-
test("beforeTimestamp-only GET keeps existing conditional-metadata shape (no results)", () => {
|
|
647
|
+
test("beforeTimestamp-only GET keeps existing conditional-metadata shape (no results)", async () => {
|
|
648
648
|
const conv = createConversation();
|
|
649
649
|
seedMessages(conv.id, 5);
|
|
650
650
|
|
|
651
651
|
// beforeTimestamp before all seeded rows => no results, metadata omitted.
|
|
652
|
-
const body = callList({
|
|
652
|
+
const body = await callList({
|
|
653
653
|
conversationId: conv.id,
|
|
654
654
|
limit: "10",
|
|
655
655
|
beforeTimestamp: "0",
|
|
@@ -662,11 +662,11 @@ describe("handleListMessages page=latest", () => {
|
|
|
662
662
|
expect("oldestMessageId" in body).toBe(false);
|
|
663
663
|
});
|
|
664
664
|
|
|
665
|
-
test("beforeTimestamp-only GET keeps existing conditional-metadata shape (with results)", () => {
|
|
665
|
+
test("beforeTimestamp-only GET keeps existing conditional-metadata shape (with results)", async () => {
|
|
666
666
|
const conv = createConversation();
|
|
667
667
|
seedMessages(conv.id, 5);
|
|
668
668
|
|
|
669
|
-
const body = callList({
|
|
669
|
+
const body = await callList({
|
|
670
670
|
conversationId: conv.id,
|
|
671
671
|
limit: "10",
|
|
672
672
|
beforeTimestamp: "100",
|
|
@@ -72,9 +72,9 @@ describe("handleListMessages provider-error projection", () => {
|
|
|
72
72
|
},
|
|
73
73
|
);
|
|
74
74
|
|
|
75
|
-
const response = handleListMessages({
|
|
75
|
+
const response = (await handleListMessages({
|
|
76
76
|
queryParams: { conversationId: conv.id },
|
|
77
|
-
}) as { messages: ProjectedMessage[] };
|
|
77
|
+
})) as { messages: ProjectedMessage[] };
|
|
78
78
|
|
|
79
79
|
// Every projected message validates against the wire schema.
|
|
80
80
|
for (const message of response.messages) {
|
|
@@ -106,9 +106,9 @@ describe("handleListMessages provider-error projection", () => {
|
|
|
106
106
|
},
|
|
107
107
|
);
|
|
108
108
|
|
|
109
|
-
const response = handleListMessages({
|
|
109
|
+
const response = (await handleListMessages({
|
|
110
110
|
queryParams: { conversationId: conv.id },
|
|
111
|
-
}) as { messages: ProjectedMessage[] };
|
|
111
|
+
})) as { messages: ProjectedMessage[] };
|
|
112
112
|
|
|
113
113
|
expect(response.messages).toHaveLength(1);
|
|
114
114
|
expect(response.messages[0]?.providerError).toEqual({});
|
|
@@ -130,9 +130,9 @@ describe("handleListMessages provider-error projection", () => {
|
|
|
130
130
|
JSON.stringify([{ type: "text", text: "hi there" }]),
|
|
131
131
|
);
|
|
132
132
|
|
|
133
|
-
const response = handleListMessages({
|
|
133
|
+
const response = (await handleListMessages({
|
|
134
134
|
queryParams: { conversationId: conv.id },
|
|
135
|
-
}) as { messages: ProjectedMessage[] };
|
|
135
|
+
})) as { messages: ProjectedMessage[] };
|
|
136
136
|
|
|
137
137
|
expect(response.messages).toHaveLength(2);
|
|
138
138
|
for (const message of response.messages) {
|
|
@@ -91,7 +91,7 @@ describe("handleListMessages in-memory queue", () => {
|
|
|
91
91
|
]);
|
|
92
92
|
|
|
93
93
|
// WHEN the messages snapshot is built for the newest page
|
|
94
|
-
const response = handleListMessages({
|
|
94
|
+
const response = await handleListMessages({
|
|
95
95
|
queryParams: { conversationId: conv.id },
|
|
96
96
|
});
|
|
97
97
|
const body = response as { messages: MessagePayload[] };
|
|
@@ -128,7 +128,7 @@ describe("handleListMessages in-memory queue", () => {
|
|
|
128
128
|
}),
|
|
129
129
|
]);
|
|
130
130
|
|
|
131
|
-
const response = handleListMessages({
|
|
131
|
+
const response = await handleListMessages({
|
|
132
132
|
queryParams: { conversationId: conv.id },
|
|
133
133
|
});
|
|
134
134
|
const body = response as { messages: MessagePayload[] };
|
|
@@ -156,7 +156,7 @@ describe("handleListMessages in-memory queue", () => {
|
|
|
156
156
|
}),
|
|
157
157
|
]);
|
|
158
158
|
|
|
159
|
-
const response = handleListMessages({
|
|
159
|
+
const response = await handleListMessages({
|
|
160
160
|
queryParams: { conversationId: conv.id },
|
|
161
161
|
});
|
|
162
162
|
const body = response as { messages: MessagePayload[] };
|
|
@@ -182,7 +182,50 @@ describe("handleListMessages in-memory queue", () => {
|
|
|
182
182
|
makeQueued({ requestId: "req-visible", content: "a real message" }),
|
|
183
183
|
]);
|
|
184
184
|
|
|
185
|
-
const response = handleListMessages({
|
|
185
|
+
const response = await handleListMessages({
|
|
186
|
+
queryParams: { conversationId: conv.id },
|
|
187
|
+
});
|
|
188
|
+
const body = response as { messages: MessagePayload[] };
|
|
189
|
+
|
|
190
|
+
expect(body.messages).toHaveLength(1);
|
|
191
|
+
expect(body.messages[0].id).toBe("req-visible");
|
|
192
|
+
expect(body.messages[0].queuePosition).toBe(1);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
test("filters daemon-injected notifications from the snapshot, keeping positions contiguous", async () => {
|
|
196
|
+
// A subagent's completion summary injected into a busy parent queues like
|
|
197
|
+
// any other turn, but it is scaffolding the user follows through the
|
|
198
|
+
// subagent card — never a queued bubble they could steer or cancel. Same
|
|
199
|
+
// for ACP run outcomes and wake triggers.
|
|
200
|
+
const conv = createConversation();
|
|
201
|
+
registerLiveConversation(conv.id, [
|
|
202
|
+
makeQueued({
|
|
203
|
+
requestId: "req-subagent",
|
|
204
|
+
content: '[Subagent "hermes-local-review" — important] review finished',
|
|
205
|
+
metadata: {
|
|
206
|
+
subagentNotification: {
|
|
207
|
+
subagentId: "sub-1",
|
|
208
|
+
label: "hermes-local-review",
|
|
209
|
+
status: "completed",
|
|
210
|
+
conversationId: "conv-sub-1",
|
|
211
|
+
objective: "review the diff",
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
}),
|
|
215
|
+
makeQueued({
|
|
216
|
+
requestId: "req-acp",
|
|
217
|
+
content: "[ACP run finished]",
|
|
218
|
+
metadata: { acpNotification: { acpSessionId: "acp-1" } },
|
|
219
|
+
}),
|
|
220
|
+
makeQueued({
|
|
221
|
+
requestId: "req-wake",
|
|
222
|
+
content: '<background_event source="schedule">',
|
|
223
|
+
metadata: { backgroundEventSource: "schedule" },
|
|
224
|
+
}),
|
|
225
|
+
makeQueued({ requestId: "req-visible", content: "a real message" }),
|
|
226
|
+
]);
|
|
227
|
+
|
|
228
|
+
const response = await handleListMessages({
|
|
186
229
|
queryParams: { conversationId: conv.id },
|
|
187
230
|
});
|
|
188
231
|
const body = response as { messages: MessagePayload[] };
|
|
@@ -204,7 +247,7 @@ describe("handleListMessages in-memory queue", () => {
|
|
|
204
247
|
registerLiveConversation(conv.id, [makeQueued({ requestId: "req-old" })]);
|
|
205
248
|
|
|
206
249
|
// WHEN paging older history
|
|
207
|
-
const response = handleListMessages({
|
|
250
|
+
const response = await handleListMessages({
|
|
208
251
|
queryParams: {
|
|
209
252
|
conversationId: conv.id,
|
|
210
253
|
beforeTimestamp: String(Date.now() + 1_000),
|
|
@@ -226,7 +269,7 @@ describe("handleListMessages in-memory queue", () => {
|
|
|
226
269
|
{ skipIndexing: true },
|
|
227
270
|
);
|
|
228
271
|
|
|
229
|
-
const response = handleListMessages({
|
|
272
|
+
const response = await handleListMessages({
|
|
230
273
|
queryParams: { conversationId: conv.id },
|
|
231
274
|
});
|
|
232
275
|
const body = response as { messages: MessagePayload[] };
|
|
@@ -60,9 +60,9 @@ describe("handleListMessages system-card projection", () => {
|
|
|
60
60
|
{ metadata: { messageKind: SYSTEM_CARD_MESSAGE_KIND } },
|
|
61
61
|
);
|
|
62
62
|
|
|
63
|
-
const response = handleListMessages({
|
|
63
|
+
const response = (await handleListMessages({
|
|
64
64
|
queryParams: { conversationId: conv.id },
|
|
65
|
-
}) as { messages: ProjectedMessage[] };
|
|
65
|
+
})) as { messages: ProjectedMessage[] };
|
|
66
66
|
|
|
67
67
|
// Every projected message validates against the wire schema.
|
|
68
68
|
for (const message of response.messages) {
|
|
@@ -87,9 +87,9 @@ describe("handleListMessages system-card projection", () => {
|
|
|
87
87
|
JSON.stringify([{ type: "text", text: "hi there" }]),
|
|
88
88
|
);
|
|
89
89
|
|
|
90
|
-
const response = handleListMessages({
|
|
90
|
+
const response = (await handleListMessages({
|
|
91
91
|
queryParams: { conversationId: conv.id },
|
|
92
|
-
}) as { messages: ProjectedMessage[] };
|
|
92
|
+
})) as { messages: ProjectedMessage[] };
|
|
93
93
|
|
|
94
94
|
expect(response.messages).toHaveLength(2);
|
|
95
95
|
for (const message of response.messages) {
|
|
@@ -86,7 +86,7 @@ describe("handleListMessages tool_result merging", () => {
|
|
|
86
86
|
]),
|
|
87
87
|
);
|
|
88
88
|
|
|
89
|
-
const response = handleListMessages(createTestArgs(conv.id));
|
|
89
|
+
const response = await handleListMessages(createTestArgs(conv.id));
|
|
90
90
|
const body = response as { messages: MessagePayload[] };
|
|
91
91
|
|
|
92
92
|
// Should be 2 messages: user prompt + assistant (tool_result user msg suppressed)
|
|
@@ -150,7 +150,7 @@ describe("handleListMessages tool_result merging", () => {
|
|
|
150
150
|
]),
|
|
151
151
|
);
|
|
152
152
|
|
|
153
|
-
const response = handleListMessages(createTestArgs(conv.id));
|
|
153
|
+
const response = await handleListMessages(createTestArgs(conv.id));
|
|
154
154
|
const body = response as { messages: MessagePayload[] };
|
|
155
155
|
|
|
156
156
|
expect(body.messages).toHaveLength(2);
|
|
@@ -180,7 +180,7 @@ describe("handleListMessages tool_result merging", () => {
|
|
|
180
180
|
JSON.stringify([{ type: "text", text: "how are you?" }]),
|
|
181
181
|
);
|
|
182
182
|
|
|
183
|
-
const response = handleListMessages(createTestArgs(conv.id));
|
|
183
|
+
const response = await handleListMessages(createTestArgs(conv.id));
|
|
184
184
|
const body = response as { messages: MessagePayload[] };
|
|
185
185
|
|
|
186
186
|
expect(body.messages).toHaveLength(3);
|
|
@@ -206,7 +206,7 @@ describe("handleListMessages tool_result merging", () => {
|
|
|
206
206
|
JSON.stringify([{ type: "text", text: "Done." }]),
|
|
207
207
|
);
|
|
208
208
|
|
|
209
|
-
const response = handleListMessages(createTestArgs(conv.id));
|
|
209
|
+
const response = await handleListMessages(createTestArgs(conv.id));
|
|
210
210
|
const body = response as { messages: MessagePayload[] };
|
|
211
211
|
|
|
212
212
|
expect(body.messages).toHaveLength(2);
|
|
@@ -241,7 +241,7 @@ describe("handleListMessages tool_result merging", () => {
|
|
|
241
241
|
JSON.stringify([{ type: "text", text: "response" }]),
|
|
242
242
|
);
|
|
243
243
|
|
|
244
|
-
const response = handleListMessages(createTestArgs(conv.id));
|
|
244
|
+
const response = await handleListMessages(createTestArgs(conv.id));
|
|
245
245
|
const body = response as { messages: MessagePayload[] };
|
|
246
246
|
|
|
247
247
|
// User row dropped entirely; only the assistant survives.
|
|
@@ -273,7 +273,7 @@ describe("handleListMessages tool_result merging", () => {
|
|
|
273
273
|
JSON.stringify([{ type: "text", text: "answering" }]),
|
|
274
274
|
);
|
|
275
275
|
|
|
276
|
-
const response = handleListMessages(createTestArgs(conv.id));
|
|
276
|
+
const response = await handleListMessages(createTestArgs(conv.id));
|
|
277
277
|
const body = response as { messages: MessagePayload[] };
|
|
278
278
|
|
|
279
279
|
expect(body.messages).toHaveLength(2);
|
|
@@ -307,7 +307,7 @@ describe("handleListMessages tool_result merging", () => {
|
|
|
307
307
|
JSON.stringify([{ type: "text", text: "ok" }]),
|
|
308
308
|
);
|
|
309
309
|
|
|
310
|
-
const response = handleListMessages(createTestArgs(conv.id));
|
|
310
|
+
const response = await handleListMessages(createTestArgs(conv.id));
|
|
311
311
|
const body = response as { messages: MessagePayload[] };
|
|
312
312
|
|
|
313
313
|
expect(body.messages).toHaveLength(1);
|
|
@@ -364,7 +364,7 @@ describe("handleListMessages tool_result merging", () => {
|
|
|
364
364
|
JSON.stringify([{ type: "text", text: "thanks" }]),
|
|
365
365
|
);
|
|
366
366
|
|
|
367
|
-
const response = handleListMessages(createTestArgs(conv.id));
|
|
367
|
+
const response = await handleListMessages(createTestArgs(conv.id));
|
|
368
368
|
const body = response as { messages: MessagePayload[] };
|
|
369
369
|
|
|
370
370
|
// Consecutive assistant messages are merged at query time so the client
|
|
@@ -414,7 +414,7 @@ describe("handleListMessages tool_result merging", () => {
|
|
|
414
414
|
]),
|
|
415
415
|
);
|
|
416
416
|
|
|
417
|
-
const response = handleListMessages(createTestArgs(conv.id));
|
|
417
|
+
const response = await handleListMessages(createTestArgs(conv.id));
|
|
418
418
|
const body = response as { messages: MessagePayload[] };
|
|
419
419
|
|
|
420
420
|
expect(body.messages).toHaveLength(2);
|