@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
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
// Single source of truth for pairing server-side tool blocks (e.g. native
|
|
2
|
+
// web_search) across a message list. Pure leaf module: consumed by the
|
|
3
|
+
// provider formatter, load-time history repair, and any other pass that must
|
|
4
|
+
// distinguish a genuine orphan from a pair the provider manages itself.
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Minimal structural message shape shared by daemon `Message[]` and
|
|
8
|
+
* `Anthropic.MessageParam[]`.
|
|
9
|
+
*/
|
|
10
|
+
export interface ServerToolPairingMessage {
|
|
11
|
+
role: string;
|
|
12
|
+
content: string | ReadonlyArray<unknown>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** Type-guard for server_tool_use blocks. */
|
|
16
|
+
export function isServerToolUseBlock(
|
|
17
|
+
block: unknown,
|
|
18
|
+
): block is { type: "server_tool_use"; id: string; name: string } {
|
|
19
|
+
return (
|
|
20
|
+
typeof block === "object" &&
|
|
21
|
+
block != null &&
|
|
22
|
+
(block as { type: string }).type === "server_tool_use"
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Type-guard for web_search_tool_result blocks. */
|
|
27
|
+
export function isWebSearchToolResultBlock(block: unknown): block is {
|
|
28
|
+
type: "web_search_tool_result";
|
|
29
|
+
tool_use_id: string;
|
|
30
|
+
content: unknown;
|
|
31
|
+
} {
|
|
32
|
+
return (
|
|
33
|
+
typeof block === "object" &&
|
|
34
|
+
block != null &&
|
|
35
|
+
(block as { type: string }).type === "web_search_tool_result"
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function isToolResultShapedBlock(block: unknown): boolean {
|
|
40
|
+
return (
|
|
41
|
+
typeof block === "object" &&
|
|
42
|
+
block != null &&
|
|
43
|
+
(block as { type?: string }).type === "tool_result"
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function contentBlocks(msg: ServerToolPairingMessage): ReadonlyArray<unknown> {
|
|
48
|
+
return Array.isArray(msg.content) ? msg.content : [];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Pairing analysis for server-side tool blocks across the whole message list.
|
|
53
|
+
*
|
|
54
|
+
* Server-side tools are provider-executed, and the pair can legitimately span
|
|
55
|
+
* messages: when the model requests a server tool and a client tool in the
|
|
56
|
+
* same parallel tool-call group, the API defers the search (stop_reason
|
|
57
|
+
* `tool_use`, no result emitted) and executes it on the next request, placing
|
|
58
|
+
* the web_search_tool_result at the head of the next assistant message. Both
|
|
59
|
+
* the deferred tail and the resulting split pair must be sent back verbatim
|
|
60
|
+
* for the provider to pair and execute them.
|
|
61
|
+
*/
|
|
62
|
+
export interface ServerToolPairing {
|
|
63
|
+
/**
|
|
64
|
+
* Ids with a complete use/result pair: the server_tool_use appears in the
|
|
65
|
+
* same message as its web_search_tool_result or in an earlier one.
|
|
66
|
+
*/
|
|
67
|
+
resolvedPairIds: Set<string>;
|
|
68
|
+
/**
|
|
69
|
+
* Unanswered use ids in the final assistant message of an active tool-loop
|
|
70
|
+
* continuation (only user messages after it, carrying tool_result blocks or
|
|
71
|
+
* nothing at all). The provider executes these on this request.
|
|
72
|
+
*/
|
|
73
|
+
deferredUseIds: Set<string>;
|
|
74
|
+
/** Ids whose use/result pair spans two messages. */
|
|
75
|
+
crossMessageIds: Set<string>;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function analyzeServerToolPairing(
|
|
79
|
+
messages: ReadonlyArray<ServerToolPairingMessage>,
|
|
80
|
+
): ServerToolPairing {
|
|
81
|
+
const useIndexById = new Map<string, number>();
|
|
82
|
+
const resultIndexById = new Map<string, number>();
|
|
83
|
+
let lastAssistantIndex = -1;
|
|
84
|
+
|
|
85
|
+
messages.forEach((msg, index) => {
|
|
86
|
+
if (msg.role !== "assistant") {
|
|
87
|
+
// Server-tool blocks legitimately live only in assistant messages; a
|
|
88
|
+
// stray result in a user message is a repair concern, not a pair.
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
lastAssistantIndex = index;
|
|
92
|
+
for (const block of contentBlocks(msg)) {
|
|
93
|
+
if (isServerToolUseBlock(block) && !useIndexById.has(block.id)) {
|
|
94
|
+
useIndexById.set(block.id, index);
|
|
95
|
+
}
|
|
96
|
+
if (
|
|
97
|
+
isWebSearchToolResultBlock(block) &&
|
|
98
|
+
!resultIndexById.has(block.tool_use_id)
|
|
99
|
+
) {
|
|
100
|
+
resultIndexById.set(block.tool_use_id, index);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
const resolvedPairIds = new Set<string>();
|
|
106
|
+
const crossMessageIds = new Set<string>();
|
|
107
|
+
useIndexById.forEach((useIndex, id) => {
|
|
108
|
+
const resultIndex = resultIndexById.get(id);
|
|
109
|
+
if (resultIndex !== undefined && resultIndex >= useIndex) {
|
|
110
|
+
resolvedPairIds.add(id);
|
|
111
|
+
if (resultIndex > useIndex) {
|
|
112
|
+
crossMessageIds.add(id);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
const deferredUseIds = new Set<string>();
|
|
118
|
+
if (lastAssistantIndex >= 0) {
|
|
119
|
+
const trailing = messages.slice(lastAssistantIndex + 1);
|
|
120
|
+
const trailingAllUser = trailing.every((m) => m.role === "user");
|
|
121
|
+
const trailingHasToolResult = trailing.some((m) =>
|
|
122
|
+
contentBlocks(m).some(isToolResultShapedBlock),
|
|
123
|
+
);
|
|
124
|
+
if (trailingAllUser && (trailing.length === 0 || trailingHasToolResult)) {
|
|
125
|
+
for (const block of contentBlocks(messages[lastAssistantIndex])) {
|
|
126
|
+
if (isServerToolUseBlock(block) && !resolvedPairIds.has(block.id)) {
|
|
127
|
+
deferredUseIds.add(block.id);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return { resolvedPairIds, deferredUseIds, crossMessageIds };
|
|
134
|
+
}
|
|
@@ -58,9 +58,27 @@ mock.module("../../../security/credential-key.js", () => ({
|
|
|
58
58
|
|
|
59
59
|
let mockVellumAvailable = false;
|
|
60
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Arguments the managed batch adapter was called with. The managed path has
|
|
63
|
+
* no constructor to spy on (the platform connection is the credential), so
|
|
64
|
+
* the language it forwards is observable only at the transcribe call.
|
|
65
|
+
*/
|
|
66
|
+
const vellumManagedTranscribeCalls: Array<{
|
|
67
|
+
mimeType: string;
|
|
68
|
+
language: string | undefined;
|
|
69
|
+
}> = [];
|
|
70
|
+
|
|
61
71
|
mock.module("../vellum-managed.js", () => ({
|
|
62
72
|
vellumManagedSpeechAvailable: async () => mockVellumAvailable,
|
|
63
|
-
vellumManagedTranscribe: async (
|
|
73
|
+
vellumManagedTranscribe: async (
|
|
74
|
+
_audio: Buffer,
|
|
75
|
+
mimeType: string,
|
|
76
|
+
_signal?: AbortSignal,
|
|
77
|
+
language?: string,
|
|
78
|
+
) => {
|
|
79
|
+
vellumManagedTranscribeCalls.push({ mimeType, language });
|
|
80
|
+
return { text: "" };
|
|
81
|
+
},
|
|
64
82
|
sttErrorFromManagedSpeech: (failure: unknown) => new Error(String(failure)),
|
|
65
83
|
}));
|
|
66
84
|
|
|
@@ -172,6 +190,7 @@ mock.module("../xai-realtime.js", () => ({
|
|
|
172
190
|
// ---------------------------------------------------------------------------
|
|
173
191
|
|
|
174
192
|
const {
|
|
193
|
+
effectiveSttLanguage,
|
|
175
194
|
resolveBatchTranscriber,
|
|
176
195
|
sttCredentialGapReason,
|
|
177
196
|
resolveConversationStreamingSttCapability,
|
|
@@ -1044,7 +1063,9 @@ describe("vellum managed resolution", () => {
|
|
|
1044
1063
|
expect(vellumStreamCtorCalls).toEqual([
|
|
1045
1064
|
{
|
|
1046
1065
|
connection: mockVelayConnection,
|
|
1047
|
-
|
|
1066
|
+
// No language is configured here, so the managed default rides along
|
|
1067
|
+
// with the connection plumbing this test is about.
|
|
1068
|
+
options: { sampleRate: 24000, language: "multi" },
|
|
1048
1069
|
},
|
|
1049
1070
|
]);
|
|
1050
1071
|
});
|
|
@@ -1178,16 +1199,76 @@ describe("resolveStreamingTranscriber language plumbing", () => {
|
|
|
1178
1199
|
expect(deepgramCtorCalls[0]?.options).toMatchObject({ language: "hi" });
|
|
1179
1200
|
});
|
|
1180
1201
|
|
|
1181
|
-
test("no configured language
|
|
1182
|
-
//
|
|
1183
|
-
//
|
|
1202
|
+
test("no configured language falls to multilingual on BYOK Deepgram", async () => {
|
|
1203
|
+
// Unset is not a neutral state on Deepgram: sending no language decodes
|
|
1204
|
+
// as English, so an unconfigured Hindi speaker gets English-sounding
|
|
1205
|
+
// nonsense. The default fills that gap with code-switching, which also
|
|
1206
|
+
// pins nova-3 the way any explicit language does.
|
|
1184
1207
|
mockProviderKeys = { deepgram: "dg-key" };
|
|
1185
1208
|
applyConfig({ provider: "deepgram" });
|
|
1186
1209
|
|
|
1187
1210
|
await resolveStreamingTranscriber({ sampleRate: 16000 });
|
|
1188
1211
|
|
|
1189
1212
|
expect(deepgramCtorCalls).toHaveLength(1);
|
|
1190
|
-
expect(deepgramCtorCalls[0]?.options).
|
|
1213
|
+
expect(deepgramCtorCalls[0]?.options).toMatchObject({
|
|
1214
|
+
language: "multi",
|
|
1215
|
+
model: "nova-3",
|
|
1216
|
+
});
|
|
1217
|
+
});
|
|
1218
|
+
|
|
1219
|
+
test("no configured language falls to multilingual on the managed relay", async () => {
|
|
1220
|
+
// The relay dials Deepgram server-side, so it inherits the same English
|
|
1221
|
+
// default and needs the same fill-in.
|
|
1222
|
+
mockVellumAvailable = true;
|
|
1223
|
+
mockVelayConnection = {
|
|
1224
|
+
wsBaseUrl: "ws://gateway.test",
|
|
1225
|
+
httpBaseUrl: "http://gateway.test",
|
|
1226
|
+
mintServiceToken: () => "vk-test",
|
|
1227
|
+
};
|
|
1228
|
+
applyConfig({ provider: "vellum" });
|
|
1229
|
+
|
|
1230
|
+
await resolveStreamingTranscriber({ sampleRate: 24000 });
|
|
1231
|
+
|
|
1232
|
+
expect(vellumStreamCtorCalls).toEqual([
|
|
1233
|
+
{
|
|
1234
|
+
connection: mockVelayConnection,
|
|
1235
|
+
options: { sampleRate: 24000, language: "multi" },
|
|
1236
|
+
},
|
|
1237
|
+
]);
|
|
1238
|
+
});
|
|
1239
|
+
|
|
1240
|
+
test("an explicitly configured language still wins over the default", async () => {
|
|
1241
|
+
// The default only fills the unset case: someone who picked Tamil (off
|
|
1242
|
+
// the code-switching roster entirely) must keep it.
|
|
1243
|
+
mockProviderKeys = { deepgram: "dg-key" };
|
|
1244
|
+
applyConfig({ provider: "deepgram", language: "ta" });
|
|
1245
|
+
|
|
1246
|
+
await resolveStreamingTranscriber({ sampleRate: 16000 });
|
|
1247
|
+
|
|
1248
|
+
expect(deepgramCtorCalls[0]?.options).toMatchObject({ language: "ta" });
|
|
1249
|
+
});
|
|
1250
|
+
|
|
1251
|
+
test("an explicit English pin is honored rather than treated as unset", async () => {
|
|
1252
|
+
// "en" is what the settings picker writes for a deliberate English pin,
|
|
1253
|
+
// so it must not collapse back into the multilingual default.
|
|
1254
|
+
mockProviderKeys = { deepgram: "dg-key" };
|
|
1255
|
+
applyConfig({ provider: "deepgram", language: "en" });
|
|
1256
|
+
|
|
1257
|
+
await resolveStreamingTranscriber({ sampleRate: 16000 });
|
|
1258
|
+
|
|
1259
|
+
expect(deepgramCtorCalls[0]?.options).toMatchObject({ language: "en" });
|
|
1260
|
+
});
|
|
1261
|
+
|
|
1262
|
+
test("providers that detect natively keep receiving no language when unset", async () => {
|
|
1263
|
+
// xAI reads unset as native auto-detection, so the multilingual default
|
|
1264
|
+
// would replace a broader capability with a ten-language one.
|
|
1265
|
+
mockProviderKeys = { xai: "xai-key" };
|
|
1266
|
+
applyConfig({ provider: "xai" });
|
|
1267
|
+
|
|
1268
|
+
await resolveStreamingTranscriber({ sampleRate: 16000 });
|
|
1269
|
+
|
|
1270
|
+
expect(xaiCtorCalls).toHaveLength(1);
|
|
1271
|
+
expect(xaiCtorCalls[0]?.options).not.toHaveProperty("language");
|
|
1191
1272
|
});
|
|
1192
1273
|
|
|
1193
1274
|
test("providers that auto-detect natively never receive a language", async () => {
|
|
@@ -1245,6 +1326,61 @@ describe("resolveStreamingTranscriber language plumbing", () => {
|
|
|
1245
1326
|
model: "nova-3",
|
|
1246
1327
|
});
|
|
1247
1328
|
});
|
|
1329
|
+
|
|
1330
|
+
test("managed batch forwards the configured language to the platform", async () => {
|
|
1331
|
+
// The platform proxy passes it to Deepgram server-side, so a managed
|
|
1332
|
+
// voice note decodes in the same language the live session does.
|
|
1333
|
+
vellumManagedTranscribeCalls.length = 0;
|
|
1334
|
+
mockVellumAvailable = true;
|
|
1335
|
+
applyConfig({ provider: "vellum", language: "ta" });
|
|
1336
|
+
|
|
1337
|
+
const transcriber = await resolveBatchTranscriber();
|
|
1338
|
+
await transcriber!.transcribe({
|
|
1339
|
+
audio: Buffer.from("fake-audio"),
|
|
1340
|
+
mimeType: "audio/ogg",
|
|
1341
|
+
});
|
|
1342
|
+
|
|
1343
|
+
expect(vellumManagedTranscribeCalls).toHaveLength(1);
|
|
1344
|
+
expect(vellumManagedTranscribeCalls[0]?.language).toBe("ta");
|
|
1345
|
+
});
|
|
1346
|
+
|
|
1347
|
+
test("managed batch falls to multilingual when no language is configured", async () => {
|
|
1348
|
+
// The gap this closes: managed voice notes used to decode as English no
|
|
1349
|
+
// matter what the user had chosen, because nothing was forwarded.
|
|
1350
|
+
vellumManagedTranscribeCalls.length = 0;
|
|
1351
|
+
mockVellumAvailable = true;
|
|
1352
|
+
applyConfig({ provider: "vellum" });
|
|
1353
|
+
|
|
1354
|
+
const transcriber = await resolveBatchTranscriber();
|
|
1355
|
+
await transcriber!.transcribe({
|
|
1356
|
+
audio: Buffer.from("fake-audio"),
|
|
1357
|
+
mimeType: "audio/ogg",
|
|
1358
|
+
});
|
|
1359
|
+
|
|
1360
|
+
expect(vellumManagedTranscribeCalls).toHaveLength(1);
|
|
1361
|
+
expect(vellumManagedTranscribeCalls[0]?.language).toBe("multi");
|
|
1362
|
+
});
|
|
1363
|
+
|
|
1364
|
+
test("batch resolution falls to multilingual when no language is configured", async () => {
|
|
1365
|
+
// Dictation and voice notes ride the batch path, and they read the same
|
|
1366
|
+
// config the live session does. A user whose spoken language works in
|
|
1367
|
+
// voice mode must not find it broken in a voice note.
|
|
1368
|
+
deepgramBatchCtorCalls.length = 0;
|
|
1369
|
+
mockProviderKeys = { deepgram: "dg-key" };
|
|
1370
|
+
applyConfig({ provider: "deepgram" });
|
|
1371
|
+
|
|
1372
|
+
const transcriber = await resolveBatchTranscriber();
|
|
1373
|
+
await transcriber!.transcribe({
|
|
1374
|
+
audio: Buffer.from("fake-audio"),
|
|
1375
|
+
mimeType: "audio/ogg",
|
|
1376
|
+
});
|
|
1377
|
+
|
|
1378
|
+
expect(deepgramBatchCtorCalls).toHaveLength(1);
|
|
1379
|
+
expect(deepgramBatchCtorCalls[0]?.options).toMatchObject({
|
|
1380
|
+
language: "multi",
|
|
1381
|
+
model: "nova-3",
|
|
1382
|
+
});
|
|
1383
|
+
});
|
|
1248
1384
|
});
|
|
1249
1385
|
|
|
1250
1386
|
describe("sttCredentialGapReason", () => {
|
|
@@ -1254,3 +1390,48 @@ describe("sttCredentialGapReason", () => {
|
|
|
1254
1390
|
expect(sttCredentialGapReason("deepgram")).toContain("API key");
|
|
1255
1391
|
});
|
|
1256
1392
|
});
|
|
1393
|
+
|
|
1394
|
+
describe("effectiveSttLanguage", () => {
|
|
1395
|
+
test("fills the unset case only where unset would mean English", () => {
|
|
1396
|
+
// Deepgram and the managed relay decode language-less audio as English,
|
|
1397
|
+
// so leaving them unset is a silent pin rather than a neutral state.
|
|
1398
|
+
expect(effectiveSttLanguage("deepgram", undefined)).toBe("multi");
|
|
1399
|
+
expect(effectiveSttLanguage("vellum", undefined)).toBe("multi");
|
|
1400
|
+
// Everyone else detects natively from the audio; filling in a ten-language
|
|
1401
|
+
// roster would narrow what they can already do.
|
|
1402
|
+
expect(effectiveSttLanguage("xai", undefined)).toBeUndefined();
|
|
1403
|
+
expect(effectiveSttLanguage("google-gemini", undefined)).toBeUndefined();
|
|
1404
|
+
expect(effectiveSttLanguage("openai-whisper", undefined)).toBeUndefined();
|
|
1405
|
+
});
|
|
1406
|
+
|
|
1407
|
+
test("a configured language always wins, including English", () => {
|
|
1408
|
+
// The default decides what happens when nobody has chosen, nothing more.
|
|
1409
|
+
expect(effectiveSttLanguage("deepgram", "ta")).toBe("ta");
|
|
1410
|
+
expect(effectiveSttLanguage("deepgram", "en")).toBe("en");
|
|
1411
|
+
expect(effectiveSttLanguage("vellum", "multi")).toBe("multi");
|
|
1412
|
+
expect(effectiveSttLanguage("xai", "hi")).toBe("hi");
|
|
1413
|
+
});
|
|
1414
|
+
});
|
|
1415
|
+
|
|
1416
|
+
describe("the multilingual default reaches configs with no stt block", () => {
|
|
1417
|
+
test("a config that omits services.stt entirely still resolves multilingual", () => {
|
|
1418
|
+
// The services-level default supplies the stt block for a fresh
|
|
1419
|
+
// workspace. Handing that default a literal would short-circuit the
|
|
1420
|
+
// inner parse and leave `language` undefined, so the block is parsed
|
|
1421
|
+
// through its own schema and the field default materializes.
|
|
1422
|
+
setConfig("services", {});
|
|
1423
|
+
expect(getConfig().services.stt.language).toBe("multi");
|
|
1424
|
+
});
|
|
1425
|
+
|
|
1426
|
+
test("a config that omits only the language gets it filled", () => {
|
|
1427
|
+
setConfig("services", { stt: { provider: "deepgram", providers: {} } });
|
|
1428
|
+
expect(getConfig().services.stt.language).toBe("multi");
|
|
1429
|
+
});
|
|
1430
|
+
|
|
1431
|
+
test("an explicit language is never overwritten by the default", () => {
|
|
1432
|
+
setConfig("services", {
|
|
1433
|
+
stt: { provider: "deepgram", language: "ta", providers: {} },
|
|
1434
|
+
});
|
|
1435
|
+
expect(getConfig().services.stt.language).toBe("ta");
|
|
1436
|
+
});
|
|
1437
|
+
});
|
|
@@ -16,6 +16,64 @@ import {
|
|
|
16
16
|
|
|
17
17
|
const log = getLogger("stt-resolver");
|
|
18
18
|
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
// Default spoken language
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Providers that decode language-less audio as English rather than detecting
|
|
25
|
+
* the spoken language: Deepgram directly, and the managed relay, which dials
|
|
26
|
+
* Deepgram server-side. For these, an unset `services.stt.language` is not a
|
|
27
|
+
* neutral state: it is a silent English pin that returns non-English speech
|
|
28
|
+
* as English-sounding nonsense.
|
|
29
|
+
*
|
|
30
|
+
* Providers absent from this set need no default: xAI, Gemini and Whisper all
|
|
31
|
+
* detect natively from the audio when no language is sent.
|
|
32
|
+
*/
|
|
33
|
+
const MULTILINGUAL_DEFAULT_PROVIDERS: ReadonlySet<SttProviderId> = new Set([
|
|
34
|
+
"deepgram",
|
|
35
|
+
"vellum",
|
|
36
|
+
] as SttProviderId[]);
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The language an unset config resolves to on the providers above: nova-3's
|
|
40
|
+
* code-switching mode, which follows a speaker between the ten languages of
|
|
41
|
+
* Deepgram's multi roster (`DEEPGRAM_MULTI_LANGUAGE_CODES` in `deepgram.ts`)
|
|
42
|
+
* without being told which one they are speaking. Chosen over an English pin
|
|
43
|
+
* because the failure it replaces is
|
|
44
|
+
* silent: a Hindi speaker under the English default gets fluent-looking
|
|
45
|
+
* garbage rather than an error, and has no way to tell recognition is
|
|
46
|
+
* misconfigured from the transcript alone.
|
|
47
|
+
*
|
|
48
|
+
* It is a default, not a ceiling. Speakers of the other 39 languages on the
|
|
49
|
+
* monolingual roster still pick theirs explicitly, and that pick continues to
|
|
50
|
+
* win here. This only decides what happens when nobody has chosen.
|
|
51
|
+
*/
|
|
52
|
+
const DEFAULT_MULTILINGUAL_CODE = "multi";
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* The spoken language to transcribe with, given what config holds and which
|
|
56
|
+
* provider will receive it. Configured values always win; the default only
|
|
57
|
+
* fills the unset case, and only where unset would otherwise mean English.
|
|
58
|
+
*
|
|
59
|
+
* Applied inside the resolvers rather than at the config layer so config keeps
|
|
60
|
+
* recording what the user chose (or that they chose nothing). The settings
|
|
61
|
+
* surfaces read that distinction to show which rows are defaults, and the live
|
|
62
|
+
* session compares raw config values to decide whether a language change needs
|
|
63
|
+
* a re-dial.
|
|
64
|
+
*/
|
|
65
|
+
export function effectiveSttLanguage(
|
|
66
|
+
providerId: SttProviderId,
|
|
67
|
+
configured: string | undefined,
|
|
68
|
+
): string | undefined {
|
|
69
|
+
if (configured) {
|
|
70
|
+
return configured;
|
|
71
|
+
}
|
|
72
|
+
return MULTILINGUAL_DEFAULT_PROVIDERS.has(providerId)
|
|
73
|
+
? DEFAULT_MULTILINGUAL_CODE
|
|
74
|
+
: undefined;
|
|
75
|
+
}
|
|
76
|
+
|
|
19
77
|
// ---------------------------------------------------------------------------
|
|
20
78
|
// Batch transcriber resolver (existing public API — unchanged contract)
|
|
21
79
|
// ---------------------------------------------------------------------------
|
|
@@ -38,7 +96,10 @@ export async function resolveBatchTranscriber(): Promise<BatchTranscriber | null
|
|
|
38
96
|
// change cannot pair one setting's old value with another's new value.
|
|
39
97
|
const stt = getConfig().services.stt;
|
|
40
98
|
const provider = stt.provider;
|
|
41
|
-
const language =
|
|
99
|
+
const language = effectiveSttLanguage(
|
|
100
|
+
provider as SttProviderId,
|
|
101
|
+
stt.language,
|
|
102
|
+
);
|
|
42
103
|
|
|
43
104
|
// Look up credential provider via the catalog.
|
|
44
105
|
const credentialProviderName = getCredentialProvider(
|
|
@@ -54,11 +115,12 @@ export async function resolveBatchTranscriber(): Promise<BatchTranscriber | null
|
|
|
54
115
|
}
|
|
55
116
|
|
|
56
117
|
if (provider === "vellum") {
|
|
57
|
-
// Managed batch
|
|
58
|
-
//
|
|
59
|
-
//
|
|
118
|
+
// Managed batch rides the platform's speech proxy, which forwards the
|
|
119
|
+
// language to Deepgram server-side. A platform build predating that
|
|
120
|
+
// field ignores it rather than failing, so the daemon can send one
|
|
121
|
+
// before the platform side deploys.
|
|
60
122
|
return (await sttProviderKeyResolves("vellum"))
|
|
61
|
-
? createDaemonBatchTranscriber(null, "vellum")
|
|
123
|
+
? createDaemonBatchTranscriber(null, "vellum", language)
|
|
62
124
|
: null;
|
|
63
125
|
}
|
|
64
126
|
|
|
@@ -304,9 +366,11 @@ export interface ResolveStreamingTranscriberOptions {
|
|
|
304
366
|
* Defaults to `services.stt.language`; pass explicitly to override the
|
|
305
367
|
* config for a single session.
|
|
306
368
|
*
|
|
307
|
-
*
|
|
308
|
-
*
|
|
309
|
-
*
|
|
369
|
+
* Leaving both unset does not reach the adapters as "no language": on
|
|
370
|
+
* Deepgram and the managed relay, where that would mean English rather
|
|
371
|
+
* than detection, {@link effectiveSttLanguage} fills in code-switching
|
|
372
|
+
* first. See {@link CreateStreamingTranscriberOptions.language} for how
|
|
373
|
+
* each adapter treats what it finally receives.
|
|
310
374
|
*/
|
|
311
375
|
language?: string;
|
|
312
376
|
}
|
|
@@ -339,8 +403,14 @@ export async function resolveStreamingTranscriber(
|
|
|
339
403
|
const provider = options.providerId ?? (stt.provider as SttProviderId);
|
|
340
404
|
// Config-level language applies to every streaming caller (live voice,
|
|
341
405
|
// dictation, telephony) unless one overrides it for a single session, so
|
|
342
|
-
// the setting lands in one place rather than at each call site.
|
|
343
|
-
|
|
406
|
+
// the setting lands in one place rather than at each call site. An unset
|
|
407
|
+
// config falls to the provider's default (see `effectiveSttLanguage`),
|
|
408
|
+
// which is where a caller passing no language gets multilingual rather
|
|
409
|
+
// than a silent English pin.
|
|
410
|
+
const language = effectiveSttLanguage(
|
|
411
|
+
provider,
|
|
412
|
+
options.language ?? stt.language,
|
|
413
|
+
);
|
|
344
414
|
const diarizePreference: DiarizePreference = options.diarize ?? "off";
|
|
345
415
|
|
|
346
416
|
// Look up credential provider via the catalog.
|
|
@@ -95,8 +95,14 @@ export async function vellumManagedTranscribe(
|
|
|
95
95
|
audio: Buffer,
|
|
96
96
|
mimeType: string,
|
|
97
97
|
signal?: AbortSignal,
|
|
98
|
+
language?: string,
|
|
98
99
|
): Promise<SttTranscribeResult> {
|
|
99
|
-
const result = await managedSpeechTranscribe({
|
|
100
|
+
const result = await managedSpeechTranscribe({
|
|
101
|
+
audio,
|
|
102
|
+
mimeType,
|
|
103
|
+
signal,
|
|
104
|
+
language,
|
|
105
|
+
});
|
|
100
106
|
if (!result.ok) {
|
|
101
107
|
throw sttErrorFromManagedSpeech(result);
|
|
102
108
|
}
|
|
@@ -59,7 +59,9 @@ export async function resolveSpeechRelayConnection(): Promise<SpeechRelayConnect
|
|
|
59
59
|
mintToken({
|
|
60
60
|
aud: "vellum-gateway",
|
|
61
61
|
sub: DAEMON_SERVICE_SUB,
|
|
62
|
-
|
|
62
|
+
// Least-privilege (ATL-1033): this token rides in the dial URL, so it
|
|
63
|
+
// must open nothing but the speech relay.
|
|
64
|
+
scope_profile: "speech_relay_v1",
|
|
63
65
|
policy_epoch: CURRENT_POLICY_EPOCH,
|
|
64
66
|
ttlSeconds: RELAY_TOKEN_TTL_SECONDS,
|
|
65
67
|
});
|
package/src/providers/types.ts
CHANGED
|
@@ -332,12 +332,32 @@ export interface SendMessageConfig {
|
|
|
332
332
|
*/
|
|
333
333
|
logit_bias?: Record<string, number>;
|
|
334
334
|
/**
|
|
335
|
-
* When true, the
|
|
336
|
-
*
|
|
337
|
-
* it
|
|
338
|
-
*
|
|
339
|
-
*
|
|
340
|
-
*
|
|
335
|
+
* When true, the TURN-STARTING user message carries content that will not
|
|
336
|
+
* recur byte-identically on the next turn, so a long-TTL breakpoint placed
|
|
337
|
+
* on it could never be read back across turns. The agent loop is the only
|
|
338
|
+
* producer: it sets the flag from the history it is about to send, when the
|
|
339
|
+
* turn-starting message carries a memory-v3 `<memory_spotlight>` block (the
|
|
340
|
+
* one injected block strip-and-replaced from every user message each turn).
|
|
341
|
+
*
|
|
342
|
+
* The flag describes the turn, not the request, so it holds for every
|
|
343
|
+
* request the turn makes, including tool-loop iterations, whose trailing
|
|
344
|
+
* tool-result message is user-role but carries no injected blocks.
|
|
345
|
+
*
|
|
346
|
+
* Consumed by the Anthropic client only, where it selects the TTL of the
|
|
347
|
+
* turn-start breakpoint: short instead of long. The block is still marked,
|
|
348
|
+
* so the turn's tool-loop iterations read the prefix back and each hit
|
|
349
|
+
* refreshes the entry; nothing is spent on a long-TTL entry whose bytes
|
|
350
|
+
* change before the next turn could reach it. Holding the flag steady across
|
|
351
|
+
* the turn is what keeps that one boundary on a single TTL; marking it at
|
|
352
|
+
* two would bill two writes for one reusable prefix.
|
|
353
|
+
*
|
|
354
|
+
* The OpenAI Responses transport ignores the flag and marks every markable
|
|
355
|
+
* user item: a volatile message is fixed within its own turn, so the write is
|
|
356
|
+
* prepaid once and read back by each tool-loop iteration.
|
|
357
|
+
*
|
|
358
|
+
* Default false. Providers that place no message-level breakpoints, or that
|
|
359
|
+
* key their cache on a request-level identifier rather than message bytes,
|
|
360
|
+
* can ignore it.
|
|
341
361
|
*/
|
|
342
362
|
mutableLatestUserMessage?: boolean;
|
|
343
363
|
/**
|
|
@@ -55,16 +55,15 @@ export const VELLUM_MANAGED_CONNECTION_NAME = "vellum";
|
|
|
55
55
|
|
|
56
56
|
/**
|
|
57
57
|
* Whether a connection is the provider-agnostic Vellum-managed connection.
|
|
58
|
+
* The provider column alone identifies the managed route: platform auth
|
|
59
|
+
* always accompanies it (auth derivation pairs them, the connection routes
|
|
60
|
+
* reject writes that split them, and DB migration 361 reconciles stored
|
|
61
|
+
* rows).
|
|
58
62
|
* Structurally typed so this stays a pure module with no connection-schema
|
|
59
63
|
* import.
|
|
60
64
|
*/
|
|
61
|
-
export function isVellumManagedConnection(conn: {
|
|
62
|
-
provider
|
|
63
|
-
auth: { type: string };
|
|
64
|
-
}): boolean {
|
|
65
|
-
return (
|
|
66
|
-
conn.provider === VELLUM_MANAGED_PROVIDER && conn.auth.type === "platform"
|
|
67
|
-
);
|
|
65
|
+
export function isVellumManagedConnection(conn: { provider: string }): boolean {
|
|
66
|
+
return conn.provider === VELLUM_MANAGED_PROVIDER;
|
|
68
67
|
}
|
|
69
68
|
|
|
70
69
|
export interface VellumModelRoute {
|
package/src/runtime/AGENTS.md
CHANGED
|
@@ -12,6 +12,8 @@ The single HTTP send endpoint is `POST /v1/messages`. Key behaviors:
|
|
|
12
12
|
|
|
13
13
|
Do NOT add new send endpoints. All message ingress should go through `POST /v1/messages` (HTTP).
|
|
14
14
|
|
|
15
|
+
**A user interrupt ends the turn, not the queue.** `POST /v1/conversations/:id/cancel` (Stop / Esc, and the CLI's cancel signal file) aborts the turn in flight; anything the same user queued behind it survives and runs on that turn's drain, because the aborted loop reaches its `finally`, which calls `kickDrainQueue` like any other turn end. `abortConversation` discards the queue only for abort kinds where the conversation itself is going away (dispose, eviction, voice supersession, subagent teardown), and every discarded row a client is showing gets `message_queued_deleted` alongside `generation_cancelled` (echo-suppressed rows are skipped, since they never got a `message_queued` ack to close). Two invariants to keep: an unconditional `queue.clear()` emits no per-row terminal event, so clients keep rendering a queued row whose cancel/steer buttons are dead (DELETE 404s, steer reports `not_processing`) and whose message is silently lost on the next reload; and a teardown must discard even when the processing flag already reads idle, since a turn that cleared the flag can still be unwinding through its awaited turn-boundary commit with a `kickDrainQueue` ahead of it.
|
|
16
|
+
|
|
15
17
|
### Channel inbound honors "queue if busy" via defer-until-idle
|
|
16
18
|
|
|
17
19
|
Channel inbound turns (Slack/Telegram/etc. — `processChannelMessageInBackground`) obey the same "process when the current turn completes" contract, but they do **not** route through the conversation's queue. A channel turn delivers its reply back through the provider callback URL (streaming session + `finalizeEventDelivery` + processed/delivery bookkeeping); the queue drain fans replies onto the SSE hub only and performs none of that. So a channel turn that arrives while the conversation is mid-turn is **deferred until the processing lock frees** (`withChannelTurnAdmission` in `routes/inbound-stages/channel-turn-admission.ts`: per-conversation single-flight for FIFO ordering + event-driven `waitForIdle`), then run with its delivery orchestration intact.
|