@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
|
@@ -27,6 +27,9 @@ mock.module("../registry.js", () => ({
|
|
|
27
27
|
// ── Imports (after mocks) ───────────────────────────────────────────────────
|
|
28
28
|
|
|
29
29
|
import { CODE_DEFAULT_PROFILE_ENTRIES } from "../../config/default-profile-catalog.js";
|
|
30
|
+
import { getDb } from "../../persistence/db-connection.js";
|
|
31
|
+
import { initializeDb } from "../../persistence/db-init.js";
|
|
32
|
+
import { resetSubagentAttributionCacheForTests } from "../../usage/subagent-attribution.js";
|
|
30
33
|
import { RetryProvider } from "../retry.js";
|
|
31
34
|
import type {
|
|
32
35
|
Message,
|
|
@@ -188,6 +191,70 @@ describe("RetryProvider — callSite resolution", () => {
|
|
|
188
191
|
).toBeUndefined();
|
|
189
192
|
});
|
|
190
193
|
|
|
194
|
+
// Delegated-work attribution on the authoritative billing path. Every
|
|
195
|
+
// subagent variety shares `llm_call_site = "subagentSpawn"`, so these two
|
|
196
|
+
// orthogonal headers are what let rated usage be decomposed by variety.
|
|
197
|
+
test("forwards subagent role and spawn mode headers for a subagent conversation", async () => {
|
|
198
|
+
await initializeDb();
|
|
199
|
+
resetSubagentAttributionCacheForTests();
|
|
200
|
+
getDb().run(
|
|
201
|
+
`INSERT INTO conversations (id, conversation_type, created_at, updated_at, subagent_role, subagent_spawn_mode)
|
|
202
|
+
VALUES ('conv-retry-advisor', 'background', 1000, 1000, 'advisor', 'advisor_consult')`,
|
|
203
|
+
);
|
|
204
|
+
setLlmConfig({
|
|
205
|
+
callSites: { subagentSpawn: { provider: "openai", model: "gpt-sub" } },
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
let seen: SendMessageOptions | undefined;
|
|
209
|
+
const wrapped = new RetryProvider(
|
|
210
|
+
makeProvider("openai", (options) => {
|
|
211
|
+
seen = options;
|
|
212
|
+
}),
|
|
213
|
+
{ forwardUsageAttributionHeaders: true },
|
|
214
|
+
);
|
|
215
|
+
|
|
216
|
+
await wrapped.sendMessage(DUMMY_MESSAGES, {
|
|
217
|
+
config: {
|
|
218
|
+
callSite: "subagentSpawn",
|
|
219
|
+
conversationId: "conv-retry-advisor",
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
const headers = (seen?.config as Record<string, unknown>)
|
|
224
|
+
.usageAttributionHeaders as Record<string, string>;
|
|
225
|
+
expect(headers["X-Vellum-Subagent-Role"]).toBe("advisor");
|
|
226
|
+
expect(headers["X-Vellum-Subagent-Spawn-Mode"]).toBe("advisor_consult");
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
test("omits subagent headers for a conversation that is not a subagent", async () => {
|
|
230
|
+
await initializeDb();
|
|
231
|
+
resetSubagentAttributionCacheForTests();
|
|
232
|
+
getDb().run(
|
|
233
|
+
`INSERT INTO conversations (id, conversation_type, created_at, updated_at)
|
|
234
|
+
VALUES ('conv-retry-plain', 'standard', 1000, 1000)`,
|
|
235
|
+
);
|
|
236
|
+
setLlmConfig({
|
|
237
|
+
callSites: { subagentSpawn: { provider: "openai", model: "gpt-sub" } },
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
let seen: SendMessageOptions | undefined;
|
|
241
|
+
const wrapped = new RetryProvider(
|
|
242
|
+
makeProvider("openai", (options) => {
|
|
243
|
+
seen = options;
|
|
244
|
+
}),
|
|
245
|
+
{ forwardUsageAttributionHeaders: true },
|
|
246
|
+
);
|
|
247
|
+
|
|
248
|
+
await wrapped.sendMessage(DUMMY_MESSAGES, {
|
|
249
|
+
config: { callSite: "subagentSpawn", conversationId: "conv-retry-plain" },
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
const headers = (seen?.config as Record<string, unknown>)
|
|
253
|
+
.usageAttributionHeaders as Record<string, string>;
|
|
254
|
+
expect(headers["X-Vellum-Subagent-Role"]).toBeUndefined();
|
|
255
|
+
expect(headers["X-Vellum-Subagent-Spawn-Mode"]).toBeUndefined();
|
|
256
|
+
});
|
|
257
|
+
|
|
191
258
|
test("omits attribution headers by default for direct provider transports", async () => {
|
|
192
259
|
setLlmConfig({
|
|
193
260
|
callSites: {
|
|
@@ -9,8 +9,9 @@ import { migrateProviderConnectionStatusLabel } from "../../persistence/migratio
|
|
|
9
9
|
import { migrateProviderConnectionBaseUrlAndModels } from "../../persistence/migrations/250-provider-connection-base-url-and-models.js";
|
|
10
10
|
import * as schema from "../../persistence/schema/index.js";
|
|
11
11
|
import { createAdapterFromConnection } from "../inference/adapter-factory.js";
|
|
12
|
-
import type { ProviderConnection } from "../inference/auth.js";
|
|
12
|
+
import type { Auth, ProviderConnection } from "../inference/auth.js";
|
|
13
13
|
import type { ResolvedAuth } from "../inference/auth.js";
|
|
14
|
+
import { effectiveConnectionAuth } from "../inference/auth.js";
|
|
14
15
|
import {
|
|
15
16
|
createConnection,
|
|
16
17
|
getConnection,
|
|
@@ -44,16 +45,11 @@ const resolvedAuth: ResolvedAuth = {
|
|
|
44
45
|
describe("vellum connection routing", () => {
|
|
45
46
|
test("isVellumManagedConnection identifies the sentinel connection", () => {
|
|
46
47
|
expect(isVellumManagedConnection(vellumConnection)).toBe(true);
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
).toBe(false);
|
|
53
|
-
// `vellum` provider with non-platform auth is not a managed vellum route.
|
|
54
|
-
expect(
|
|
55
|
-
isVellumManagedConnection({ provider: "vellum", auth: { type: "none" } }),
|
|
56
|
-
).toBe(false);
|
|
48
|
+
// The provider column alone decides: a concrete provider is never the
|
|
49
|
+
// managed route (platform auth always pairs with provider "vellum";
|
|
50
|
+
// DB migration 361 reconciles stored rows).
|
|
51
|
+
expect(isVellumManagedConnection({ provider: "fireworks" })).toBe(false);
|
|
52
|
+
expect(isVellumManagedConnection({ provider: "vellum" })).toBe(true);
|
|
57
53
|
});
|
|
58
54
|
|
|
59
55
|
test("the vellum sentinel is not a real provider without an override", () => {
|
|
@@ -82,6 +78,41 @@ describe("vellum connection routing", () => {
|
|
|
82
78
|
});
|
|
83
79
|
});
|
|
84
80
|
|
|
81
|
+
describe("effectiveConnectionAuth", () => {
|
|
82
|
+
test("a vellum row dispatches on platform auth regardless of the stored variant", () => {
|
|
83
|
+
for (const stored of [
|
|
84
|
+
{ type: "api_key", credential: "vault/x" },
|
|
85
|
+
{ type: "none" },
|
|
86
|
+
{ type: "platform" },
|
|
87
|
+
] as Auth[]) {
|
|
88
|
+
expect(
|
|
89
|
+
effectiveConnectionAuth({ provider: "vellum", auth: stored }),
|
|
90
|
+
).toEqual({ type: "platform" });
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test("payload-carrying rows keep their stored auth verbatim", () => {
|
|
95
|
+
const keyed: Auth = { type: "api_key", credential: "vault/anthropic" };
|
|
96
|
+
expect(
|
|
97
|
+
effectiveConnectionAuth({ provider: "anthropic", auth: keyed }),
|
|
98
|
+
).toBe(keyed);
|
|
99
|
+
const subscription: Auth = { type: "oauth_subscription" } as Auth;
|
|
100
|
+
expect(
|
|
101
|
+
effectiveConnectionAuth({ provider: "openai", auth: subscription }),
|
|
102
|
+
).toBe(subscription);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
test("a deliberately keyed keyless provider keeps its key", () => {
|
|
106
|
+
// Keyless means no key REQUIRED, not no key possible: the ollama adapter
|
|
107
|
+
// accepts one, so stored api_key auth on an ollama row is payload and
|
|
108
|
+
// must never be derived away.
|
|
109
|
+
const keyed: Auth = { type: "api_key", credential: "vault/ollama" };
|
|
110
|
+
expect(effectiveConnectionAuth({ provider: "ollama", auth: keyed })).toBe(
|
|
111
|
+
keyed,
|
|
112
|
+
);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
85
116
|
describe("vellum connection persistence (DB round-trip)", () => {
|
|
86
117
|
// Guards the P1: a persisted `provider: "vellum"` row must survive the DB
|
|
87
118
|
// loaders and create route, which validate against VALID_CONNECTION_PROVIDERS.
|
|
@@ -18,6 +18,12 @@ import {
|
|
|
18
18
|
PLACEHOLDER_EMPTY_TURN,
|
|
19
19
|
} from "../placeholder-sentinels.js";
|
|
20
20
|
import { recordProviderRequestDiagnostics } from "../request-diagnostics.js";
|
|
21
|
+
import {
|
|
22
|
+
analyzeServerToolPairing,
|
|
23
|
+
isServerToolUseBlock,
|
|
24
|
+
isWebSearchToolResultBlock,
|
|
25
|
+
type ServerToolPairing,
|
|
26
|
+
} from "../server-tool-pairing.js";
|
|
21
27
|
import { createStreamTimeout } from "../stream-timeout.js";
|
|
22
28
|
import type {
|
|
23
29
|
ContentBlock,
|
|
@@ -489,73 +495,54 @@ function normalizeFollowingUserContent(
|
|
|
489
495
|
};
|
|
490
496
|
}
|
|
491
497
|
|
|
492
|
-
/** Type-guard for server_tool_use blocks. */
|
|
493
|
-
function isServerToolUseBlock(
|
|
494
|
-
block: unknown,
|
|
495
|
-
): block is { type: "server_tool_use"; id: string; name: string } {
|
|
496
|
-
return (
|
|
497
|
-
typeof block === "object" &&
|
|
498
|
-
block != null &&
|
|
499
|
-
(block as { type: string }).type === "server_tool_use"
|
|
500
|
-
);
|
|
501
|
-
}
|
|
502
|
-
|
|
503
|
-
/** Type-guard for web_search_tool_result blocks. */
|
|
504
|
-
function isWebSearchToolResultBlock(block: unknown): block is {
|
|
505
|
-
type: "web_search_tool_result";
|
|
506
|
-
tool_use_id: string;
|
|
507
|
-
content: unknown;
|
|
508
|
-
} {
|
|
509
|
-
return (
|
|
510
|
-
typeof block === "object" &&
|
|
511
|
-
block != null &&
|
|
512
|
-
(block as { type: string }).type === "web_search_tool_result"
|
|
513
|
-
);
|
|
514
|
-
}
|
|
515
|
-
|
|
516
498
|
/**
|
|
517
|
-
* Repair orphaned server-side tool blocks within assistant messages
|
|
518
|
-
*
|
|
519
|
-
*
|
|
520
|
-
*
|
|
521
|
-
*
|
|
522
|
-
*
|
|
523
|
-
* handles both directions:
|
|
499
|
+
* Repair orphaned server-side tool blocks within assistant messages, using the
|
|
500
|
+
* cross-message pairing from {@link analyzeServerToolPairing}. A pair can go
|
|
501
|
+
* missing on either side: a partial stream may drop the result, or a
|
|
502
|
+
* downstream step (history reload, message split, compaction) may drop the use
|
|
503
|
+
* block. Both cases trigger an Anthropic 400 on the next request, so this
|
|
504
|
+
* function handles both directions:
|
|
524
505
|
*
|
|
525
|
-
* - server_tool_use without paired result: inject a synthetic error
|
|
526
|
-
*
|
|
506
|
+
* - server_tool_use without a paired result: inject a synthetic error
|
|
507
|
+
* result.
|
|
508
|
+
* - web_search_tool_result without a paired server_tool_use: downgrade to a
|
|
527
509
|
* text block describing what was found so the model retains context.
|
|
510
|
+
*
|
|
511
|
+
* Deferred use blocks (see {@link ServerToolPairing.deferredUseIds}) are not
|
|
512
|
+
* orphans: they are left intact so the provider executes the search on this
|
|
513
|
+
* request instead of seeing a synthetic failure.
|
|
528
514
|
*/
|
|
529
515
|
function repairOrphanedServerToolBlocks(
|
|
530
516
|
messages: Anthropic.MessageParam[],
|
|
517
|
+
pairing: ServerToolPairing,
|
|
531
518
|
): Anthropic.MessageParam[] {
|
|
519
|
+
if (pairing.deferredUseIds.size > 0) {
|
|
520
|
+
log.info(
|
|
521
|
+
{ deferredIds: Array.from(pairing.deferredUseIds) },
|
|
522
|
+
"Preserving deferred server_tool_use blocks for provider-side execution",
|
|
523
|
+
);
|
|
524
|
+
}
|
|
532
525
|
return messages.map((msg) => {
|
|
533
526
|
if (msg.role !== "assistant") {
|
|
534
527
|
return msg;
|
|
535
528
|
}
|
|
536
529
|
const content = Array.isArray(msg.content) ? msg.content : [];
|
|
537
530
|
|
|
538
|
-
const serverToolUseIds = new Set<string>();
|
|
539
|
-
const webSearchResultIds = new Set<string>();
|
|
540
|
-
for (const block of content) {
|
|
541
|
-
if (isServerToolUseBlock(block)) {
|
|
542
|
-
serverToolUseIds.add(block.id);
|
|
543
|
-
}
|
|
544
|
-
if (isWebSearchToolResultBlock(block)) {
|
|
545
|
-
webSearchResultIds.add(block.tool_use_id);
|
|
546
|
-
}
|
|
547
|
-
}
|
|
548
|
-
|
|
549
531
|
const orphanServerToolUseIds = new Set<string>();
|
|
550
|
-
for (const id of serverToolUseIds) {
|
|
551
|
-
if (!webSearchResultIds.has(id)) {
|
|
552
|
-
orphanServerToolUseIds.add(id);
|
|
553
|
-
}
|
|
554
|
-
}
|
|
555
532
|
const orphanWebSearchResultIds = new Set<string>();
|
|
556
|
-
for (const
|
|
557
|
-
if (
|
|
558
|
-
|
|
533
|
+
for (const block of content) {
|
|
534
|
+
if (
|
|
535
|
+
isServerToolUseBlock(block) &&
|
|
536
|
+
!pairing.resolvedPairIds.has(block.id) &&
|
|
537
|
+
!pairing.deferredUseIds.has(block.id)
|
|
538
|
+
) {
|
|
539
|
+
orphanServerToolUseIds.add(block.id);
|
|
540
|
+
}
|
|
541
|
+
if (
|
|
542
|
+
isWebSearchToolResultBlock(block) &&
|
|
543
|
+
!pairing.resolvedPairIds.has(block.tool_use_id)
|
|
544
|
+
) {
|
|
545
|
+
orphanWebSearchResultIds.add(block.tool_use_id);
|
|
559
546
|
}
|
|
560
547
|
}
|
|
561
548
|
|
|
@@ -709,9 +696,18 @@ function findActiveToolUseContinuationStart(
|
|
|
709
696
|
|
|
710
697
|
function ensureToolPairing(
|
|
711
698
|
messages: Anthropic.MessageParam[],
|
|
699
|
+
pairing: ServerToolPairing,
|
|
712
700
|
): Anthropic.MessageParam[] {
|
|
713
701
|
const result: Anthropic.MessageParam[] = [];
|
|
714
702
|
|
|
703
|
+
// Messages carrying a deferred or cross-message-paired server tool block
|
|
704
|
+
// must go out verbatim: the provider pairs and executes these blocks across
|
|
705
|
+
// messages itself, and reordering or splitting them breaks that pairing.
|
|
706
|
+
const verbatimIds = new Set([
|
|
707
|
+
...pairing.deferredUseIds,
|
|
708
|
+
...pairing.crossMessageIds,
|
|
709
|
+
]);
|
|
710
|
+
|
|
715
711
|
let i = 0;
|
|
716
712
|
while (i < messages.length) {
|
|
717
713
|
const msg = messages[i];
|
|
@@ -724,8 +720,23 @@ function ensureToolPairing(
|
|
|
724
720
|
|
|
725
721
|
const content = Array.isArray(msg.content) ? msg.content : [];
|
|
726
722
|
|
|
723
|
+
const hasVerbatimServerBlock =
|
|
724
|
+
verbatimIds.size > 0 &&
|
|
725
|
+
content.some(
|
|
726
|
+
(block) =>
|
|
727
|
+
(isServerToolUseBlock(block) && verbatimIds.has(block.id)) ||
|
|
728
|
+
(isWebSearchToolResultBlock(block) &&
|
|
729
|
+
verbatimIds.has(block.tool_use_id)),
|
|
730
|
+
);
|
|
731
|
+
|
|
727
732
|
const { pairedContent, carryoverContent, toolUseIds } =
|
|
728
|
-
|
|
733
|
+
hasVerbatimServerBlock
|
|
734
|
+
? {
|
|
735
|
+
pairedContent: content,
|
|
736
|
+
carryoverContent: [] as Anthropic.ContentBlockParam[],
|
|
737
|
+
toolUseIds: getOrderedToolUseIds(content),
|
|
738
|
+
}
|
|
739
|
+
: splitAssistantForToolPairing(content);
|
|
729
740
|
|
|
730
741
|
if (toolUseIds.length === 0) {
|
|
731
742
|
result.push(msg);
|
|
@@ -976,7 +987,7 @@ export class AnthropicProvider implements Provider {
|
|
|
976
987
|
// edge LB, NAT idle) — only the latter should be retried.
|
|
977
988
|
let innerTimeoutSignal: AbortSignal | undefined;
|
|
978
989
|
try {
|
|
979
|
-
sentMessages = this.buildSentMessages(messages);
|
|
990
|
+
sentMessages = await this.buildSentMessages(messages);
|
|
980
991
|
const {
|
|
981
992
|
effort,
|
|
982
993
|
speed,
|
|
@@ -1169,7 +1180,10 @@ export class AnthropicProvider implements Provider {
|
|
|
1169
1180
|
}
|
|
1170
1181
|
return -1;
|
|
1171
1182
|
};
|
|
1172
|
-
const applyCacheControlToLastBlock = (
|
|
1183
|
+
const applyCacheControlToLastBlock = (
|
|
1184
|
+
msgIdx: number,
|
|
1185
|
+
control: typeof cacheControl | typeof tailCacheControl = cacheControl,
|
|
1186
|
+
): void => {
|
|
1173
1187
|
const content = msgs[msgIdx].content;
|
|
1174
1188
|
if (!Array.isArray(content) || content.length === 0) {
|
|
1175
1189
|
return;
|
|
@@ -1177,27 +1191,30 @@ export class AnthropicProvider implements Provider {
|
|
|
1177
1191
|
const lastBlock = content[content.length - 1];
|
|
1178
1192
|
if (typeof lastBlock !== "string") {
|
|
1179
1193
|
(lastBlock as unknown as Record<string, unknown>).cache_control =
|
|
1180
|
-
|
|
1194
|
+
control;
|
|
1181
1195
|
}
|
|
1182
1196
|
};
|
|
1183
1197
|
const turnStartIdx = findUserTextMsgIdx(msgs.length - 1);
|
|
1184
|
-
//
|
|
1185
|
-
//
|
|
1186
|
-
//
|
|
1187
|
-
//
|
|
1188
|
-
//
|
|
1189
|
-
//
|
|
1190
|
-
//
|
|
1191
|
-
//
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
) {
|
|
1200
|
-
applyCacheControlToLastBlock(
|
|
1198
|
+
// Turn-start anchor. A volatile turn start (`mutableLatestUserMessage`:
|
|
1199
|
+
// the message carries a per-turn block that will not recur next turn)
|
|
1200
|
+
// takes the SHORT TTL instead of the long one. The long TTL would buy
|
|
1201
|
+
// nothing: the bytes change next turn, so that entry can never be read
|
|
1202
|
+
// across turns, and the only reads it can serve are this turn's tool-loop
|
|
1203
|
+
// iterations, which the short TTL already serves, refreshing on each
|
|
1204
|
+
// hit. Marking the same boundary at two different TTLs across a turn
|
|
1205
|
+
// bills two writes for one reusable prefix, the long one at the higher
|
|
1206
|
+
// write multiplier.
|
|
1207
|
+
//
|
|
1208
|
+
// The signal is turn-scoped, not request-scoped: it describes the
|
|
1209
|
+
// turn-starting user message, so it holds for every request in the turn
|
|
1210
|
+
// and the TTL chosen here stays consistent as the tool loop advances.
|
|
1211
|
+
// `disableTurnStartCache` is independent: it expresses a different
|
|
1212
|
+
// intent (one-shot callers with no future hit).
|
|
1213
|
+
if (turnStartIdx >= 0 && !disableCache && !disableTurnStartCache) {
|
|
1214
|
+
applyCacheControlToLastBlock(
|
|
1215
|
+
turnStartIdx,
|
|
1216
|
+
mutableLatestUserMessage ? tailCacheControl : cacheControl,
|
|
1217
|
+
);
|
|
1201
1218
|
}
|
|
1202
1219
|
|
|
1203
1220
|
// Previous-turn anchor: when this request is the first of a new turn
|
|
@@ -1223,26 +1240,19 @@ export class AnthropicProvider implements Provider {
|
|
|
1223
1240
|
|
|
1224
1241
|
// Advancing tail: place a short-lived 5m cache breakpoint on the last
|
|
1225
1242
|
// block of the last message. This caches the growing tail cheaply
|
|
1226
|
-
// without conflicting with the
|
|
1227
|
-
// tool-use loops
|
|
1228
|
-
//
|
|
1229
|
-
//
|
|
1230
|
-
//
|
|
1231
|
-
//
|
|
1232
|
-
//
|
|
1233
|
-
// re-creation of the prefix. The 5m breakpoint gives the next call an
|
|
1234
|
-
// exact, reachable boundary; cross-turn it expires harmlessly. The
|
|
1235
|
-
// first-of-turn bridge lands on the turn-start block, so it honors
|
|
1236
|
-
// `disableTurnStartCache` like the long-TTL anchor above. Skip
|
|
1243
|
+
// without conflicting with the long-TTL breakpoints above. It fires
|
|
1244
|
+
// during tool-use loops, where the tail falls after the turn-starting
|
|
1245
|
+
// user message: without it the next iteration's anchor can land far
|
|
1246
|
+
// ahead of the last written boundary and Anthropic's ~20-block cache
|
|
1247
|
+
// lookback can't bridge the gap, forcing a full re-creation of the
|
|
1248
|
+
// prefix. On a first-of-turn request the tail IS the turn-start message,
|
|
1249
|
+
// which the anchor above already marks, so no bridge is needed. Skip
|
|
1237
1250
|
// thinking/redacted_thinking blocks — Anthropic doesn't allow
|
|
1238
1251
|
// cache_control on those types.
|
|
1239
1252
|
if (
|
|
1240
1253
|
!disableCache &&
|
|
1241
1254
|
turnStartIdx >= 0 &&
|
|
1242
|
-
|
|
1243
|
-
(skipVolatileTurnStartAnchor &&
|
|
1244
|
-
turnStartIdx > 0 &&
|
|
1245
|
-
!disableTurnStartCache))
|
|
1255
|
+
turnStartIdx < sentMessages.length - 1
|
|
1246
1256
|
) {
|
|
1247
1257
|
const lastMsg = sentMessages[sentMessages.length - 1];
|
|
1248
1258
|
if (Array.isArray(lastMsg.content) && lastMsg.content.length > 0) {
|
|
@@ -1272,10 +1282,11 @@ export class AnthropicProvider implements Provider {
|
|
|
1272
1282
|
// system is a single block or absent) + at most two message anchors
|
|
1273
1283
|
// ≤ 4 — Anthropic's per-request cap. The two message anchors are
|
|
1274
1284
|
// turn-start + prev-turn-anchor (first-of-turn), turn-start + tail
|
|
1275
|
-
// (tool-use loop),
|
|
1285
|
+
// (tool-use loop), prev-turn-anchor + tail (first-of-turn with the
|
|
1276
1286
|
// volatile turn-start anchor skipped — the freed turn-start slot covers
|
|
1277
|
-
// the tail)
|
|
1278
|
-
//
|
|
1287
|
+
// the tail), or the tail alone (volatile first turn, where no
|
|
1288
|
+
// previous turn exists to anchor). At most two message-level
|
|
1289
|
+
// breakpoints are placed, so the total can't drift past 4.
|
|
1279
1290
|
|
|
1280
1291
|
// Strip orphaned UTF-16 surrogates so the Anthropic JSON parser never
|
|
1281
1292
|
// sees invalid strings produced by upstream surrogate-splitting `.slice()` calls.
|
|
@@ -1801,7 +1812,7 @@ export class AnthropicProvider implements Provider {
|
|
|
1801
1812
|
systemPrompt: string,
|
|
1802
1813
|
tools?: ToolDefinition[],
|
|
1803
1814
|
): Promise<number> {
|
|
1804
|
-
const sentMessages = this.buildSentMessages(messages);
|
|
1815
|
+
const sentMessages = await this.buildSentMessages(messages);
|
|
1805
1816
|
|
|
1806
1817
|
const system = systemPrompt
|
|
1807
1818
|
? systemPrompt
|
|
@@ -1837,10 +1848,12 @@ export class AnthropicProvider implements Provider {
|
|
|
1837
1848
|
* `cache_control` breakpoints (which don't affect token counts) are the
|
|
1838
1849
|
* only thing layered on top in `sendMessage`.
|
|
1839
1850
|
*/
|
|
1840
|
-
private buildSentMessages(
|
|
1851
|
+
private async buildSentMessages(
|
|
1852
|
+
messages: Message[],
|
|
1853
|
+
): Promise<Anthropic.MessageParam[]> {
|
|
1841
1854
|
// Swap any persisted attachment references back to inline base64 before
|
|
1842
1855
|
// serializing, so the block transforms below can read `source.data`.
|
|
1843
|
-
messages = resolveMediaReferences(messages);
|
|
1856
|
+
messages = await resolveMediaReferences(messages);
|
|
1844
1857
|
const formatted = messages
|
|
1845
1858
|
.map((m) => {
|
|
1846
1859
|
// Track whether an unknown block was dropped during filtering
|
|
@@ -2014,7 +2027,11 @@ export class AnthropicProvider implements Provider {
|
|
|
2014
2027
|
formatted[i] = { ...msg, content: stripped };
|
|
2015
2028
|
}
|
|
2016
2029
|
|
|
2017
|
-
|
|
2030
|
+
const serverToolPairing = analyzeServerToolPairing(formatted);
|
|
2031
|
+
return ensureToolPairing(
|
|
2032
|
+
repairOrphanedServerToolBlocks(formatted, serverToolPairing),
|
|
2033
|
+
serverToolPairing,
|
|
2034
|
+
);
|
|
2018
2035
|
}
|
|
2019
2036
|
|
|
2020
2037
|
/**
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
* a conversation offline.
|
|
28
28
|
*/
|
|
29
29
|
|
|
30
|
+
import { getIsPlatform } from "../config/env-registry.js";
|
|
30
31
|
import {
|
|
31
32
|
resolveCallSiteConfig,
|
|
32
33
|
selectWinningProfile,
|
|
@@ -468,7 +469,40 @@ export async function preflightResolvedConfig(
|
|
|
468
469
|
errorOptions,
|
|
469
470
|
);
|
|
470
471
|
}
|
|
471
|
-
|
|
472
|
+
const presence = await platformLoginPresence();
|
|
473
|
+
if (presence === "ok") {
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
if (getIsPlatform()) {
|
|
477
|
+
// A platform-managed assistant cannot present a login screen or switch
|
|
478
|
+
// providers, so the login-or-switch wording never fits. An unreachable
|
|
479
|
+
// store is transient and recovers on its own, so it reads as a retry. A
|
|
480
|
+
// reachable but empty store can only be fixed by re-provisioning the
|
|
481
|
+
// credential platform-side.
|
|
482
|
+
if (presence === "indeterminate") {
|
|
483
|
+
throw new ConnectionResolutionError(
|
|
484
|
+
connectionName,
|
|
485
|
+
"platform_unauthenticated",
|
|
486
|
+
"The assistant's platform credentials are temporarily unavailable; retrying automatically.",
|
|
487
|
+
errorOptions,
|
|
488
|
+
);
|
|
489
|
+
}
|
|
490
|
+
log.error(
|
|
491
|
+
{
|
|
492
|
+
connectionName,
|
|
493
|
+
model: resolved.model,
|
|
494
|
+
profileName: attribution.profileName,
|
|
495
|
+
},
|
|
496
|
+
"Managed platform credential is missing and must be re-provisioned",
|
|
497
|
+
);
|
|
498
|
+
throw new ConnectionResolutionError(
|
|
499
|
+
connectionName,
|
|
500
|
+
"platform_unauthenticated",
|
|
501
|
+
"This assistant's platform credential is missing and must be re-provisioned on the Vellum platform.",
|
|
502
|
+
errorOptions,
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
if (presence === "unauthenticated") {
|
|
472
506
|
throw new ConnectionResolutionError(
|
|
473
507
|
connectionName,
|
|
474
508
|
"platform_unauthenticated",
|
|
@@ -434,7 +434,7 @@ export class GeminiProvider implements Provider {
|
|
|
434
434
|
|
|
435
435
|
try {
|
|
436
436
|
recordProviderRequestDiagnostics({ model_id: activeModel });
|
|
437
|
-
const geminiContents = this.toGeminiContents(messages, activeModel);
|
|
437
|
+
const geminiContents = await this.toGeminiContents(messages, activeModel);
|
|
438
438
|
|
|
439
439
|
const geminiConfig: genai.GenerateContentConfig = {};
|
|
440
440
|
|
|
@@ -658,7 +658,7 @@ export class GeminiProvider implements Provider {
|
|
|
658
658
|
systemPrompt: string,
|
|
659
659
|
tools?: ToolDefinition[],
|
|
660
660
|
): Promise<number> {
|
|
661
|
-
const contents = this.toGeminiContents(messages, this.model);
|
|
661
|
+
const contents = await this.toGeminiContents(messages, this.model);
|
|
662
662
|
const config: genai.CountTokensConfig = {};
|
|
663
663
|
if (systemPrompt) {
|
|
664
664
|
config.systemInstruction = systemPrompt.replaceAll(
|
|
@@ -689,13 +689,13 @@ export class GeminiProvider implements Provider {
|
|
|
689
689
|
}
|
|
690
690
|
|
|
691
691
|
/** Convert neutral messages to Gemini Content[] format. */
|
|
692
|
-
private toGeminiContents(
|
|
692
|
+
private async toGeminiContents(
|
|
693
693
|
messages: Message[],
|
|
694
694
|
model: string,
|
|
695
|
-
): genai.Content[] {
|
|
695
|
+
): Promise<genai.Content[]> {
|
|
696
696
|
// Swap any persisted attachment references back to inline base64 before
|
|
697
697
|
// building parts, so the transforms below can read `source.data`.
|
|
698
|
-
messages = resolveMediaReferences(messages);
|
|
698
|
+
messages = await resolveMediaReferences(messages);
|
|
699
699
|
const result: genai.Content[] = [];
|
|
700
700
|
|
|
701
701
|
// Build a map from tool_use id → function name so tool_result blocks
|
|
@@ -34,9 +34,11 @@ import { RetryProvider } from "../retry.js";
|
|
|
34
34
|
import { TogetherProvider } from "../together/client.js";
|
|
35
35
|
import type { Provider } from "../types.js";
|
|
36
36
|
import { UsageTrackingProvider } from "../usage-tracking.js";
|
|
37
|
+
import { isVellumManagedConnection } from "../vellum-model-routing.js";
|
|
37
38
|
import { VercelAIGatewayProvider } from "../vercel-ai-gateway/client.js";
|
|
38
39
|
import type { ResolvedAuth } from "./auth.js";
|
|
39
40
|
import type { ProviderConnection } from "./auth.js";
|
|
41
|
+
import { effectiveConnectionAuth } from "./auth.js";
|
|
40
42
|
import { resolveAuth } from "./resolve-auth.js";
|
|
41
43
|
|
|
42
44
|
/** Unified construction opts. Adapters ignore fields they don't consume. */
|
|
@@ -244,9 +246,11 @@ export function createAdapterFromConnection(
|
|
|
244
246
|
function makeCredentialRefresher(): () => Promise<Provider | null> {
|
|
245
247
|
let lastAuth = JSON.stringify(resolvedAuth);
|
|
246
248
|
return async (): Promise<Provider | null> => {
|
|
247
|
-
const refreshedAuth = await resolveAuth(
|
|
248
|
-
|
|
249
|
-
|
|
249
|
+
const refreshedAuth = await resolveAuth(
|
|
250
|
+
effectiveConnectionAuth(connection),
|
|
251
|
+
provider,
|
|
252
|
+
{ baseUrl: connection.baseUrl },
|
|
253
|
+
);
|
|
250
254
|
if (!refreshedAuth.ok) {
|
|
251
255
|
return null;
|
|
252
256
|
}
|
|
@@ -262,19 +266,20 @@ export function createAdapterFromConnection(
|
|
|
262
266
|
// Usage-attribution headers (`X-Vellum-*`) are only meaningful when the
|
|
263
267
|
// request is routed through the Vellum-managed proxy. They carry billing
|
|
264
268
|
// metadata for our own backend. Forwarding them to a third-party endpoint
|
|
265
|
-
// would leak internal Vellum metadata, so gate on the
|
|
266
|
-
//
|
|
267
|
-
const isManagedProxy = connection
|
|
269
|
+
// would leak internal Vellum metadata, so gate on the managed connection
|
|
270
|
+
// identity, the only route that flows through our proxy.
|
|
271
|
+
const isManagedProxy = isVellumManagedConnection(connection);
|
|
272
|
+
const effectiveAuth = effectiveConnectionAuth(connection);
|
|
268
273
|
return new UsageTrackingProvider(
|
|
269
274
|
new RetryProvider(adapter, {
|
|
270
275
|
forwardUsageAttributionHeaders: isManagedProxy,
|
|
271
276
|
credentialSource: isManagedProxy
|
|
272
277
|
? "vellum-managed"
|
|
273
|
-
:
|
|
278
|
+
: effectiveAuth.type === "api_key"
|
|
274
279
|
? "byok"
|
|
275
|
-
:
|
|
280
|
+
: effectiveAuth.type === "oauth_subscription"
|
|
276
281
|
? "oauth-subscription"
|
|
277
|
-
:
|
|
282
|
+
: effectiveAuth.type === "none"
|
|
278
283
|
? "no-auth"
|
|
279
284
|
: undefined,
|
|
280
285
|
connectionName: connection.name,
|
|
@@ -320,7 +325,8 @@ function buildConnectionAdapter(
|
|
|
320
325
|
: undefined;
|
|
321
326
|
|
|
322
327
|
const codexSubscription =
|
|
323
|
-
connection.
|
|
328
|
+
effectiveConnectionAuth(connection).type === "oauth_subscription" &&
|
|
329
|
+
provider === "openai";
|
|
324
330
|
|
|
325
331
|
const adapter = buildProviderAdapter(provider, {
|
|
326
332
|
apiKey,
|
|
@@ -72,6 +72,22 @@ export function deriveAuthForProvider(
|
|
|
72
72
|
return credential ? { type: "api_key", credential } : null;
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
/**
|
|
76
|
+
* The auth a connection dispatches with. The stored auth object is
|
|
77
|
+
* authoritative only where it carries a payload (an api_key credential ref,
|
|
78
|
+
* the oauth_subscription marker, a deliberately keyed keyless provider);
|
|
79
|
+
* the vellum provider IS the managed route, so its auth derives from the
|
|
80
|
+
* provider and the stored value can never mislead dispatch.
|
|
81
|
+
*/
|
|
82
|
+
export function effectiveConnectionAuth(connection: {
|
|
83
|
+
provider: string;
|
|
84
|
+
auth: Auth;
|
|
85
|
+
}): Auth {
|
|
86
|
+
return connection.provider === VELLUM_MANAGED_PROVIDER
|
|
87
|
+
? { type: "platform" }
|
|
88
|
+
: connection.auth;
|
|
89
|
+
}
|
|
90
|
+
|
|
75
91
|
// ---------------------------------------------------------------------------
|
|
76
92
|
// ResolvedAuth — what the dispatcher hands to each adapter
|
|
77
93
|
// ---------------------------------------------------------------------------
|