@vellumai/assistant 0.10.9 → 0.10.10-dev.202607162206.d08e98e
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 +1 -1
- package/Dockerfile +8 -0
- package/docs/activation-funnel-telemetry.md +13 -7
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/redacted-credential.test.ts +200 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/redacted-credential.ts +226 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/redacted-credential.test.ts +200 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/redacted-credential.ts +226 -0
- package/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/redacted-credential.test.ts +200 -0
- package/node_modules/@vellumai/service-contracts/src/redacted-credential.ts +226 -0
- package/openapi.yaml +530 -107
- package/package.json +1 -1
- package/scripts/generate-openapi.ts +8 -0
- package/src/__tests__/activation-early-marking.test.ts +6 -5
- package/src/__tests__/agent-loop-override-profile.test.ts +22 -25
- package/src/__tests__/agent-wake-override-profile.test.ts +21 -48
- package/src/__tests__/app-builder-tool-scripts.test.ts +0 -1
- package/src/__tests__/app-bundler.test.ts +4 -12
- package/src/__tests__/app-executors.test.ts +2 -49
- package/src/__tests__/app-routes-csp.test.ts +114 -146
- package/src/__tests__/auth-fallback-events-store.test.ts +8 -1
- package/src/__tests__/build-persisted-content.test.ts +96 -0
- package/src/__tests__/bundle-scanner.test.ts +27 -1
- package/src/__tests__/call-controller.test.ts +291 -0
- package/src/__tests__/call-site-routing-connection-auto-resolve.test.ts +165 -0
- package/src/__tests__/chat-credential-redaction.test.ts +1395 -0
- package/src/__tests__/chat-reveal-guard-priming.test.ts +791 -0
- package/src/__tests__/compaction.benchmark.test.ts +2 -1
- package/src/__tests__/compactor-image-manifest-trust.test.ts +50 -0
- package/src/__tests__/config-loader-backfill.test.ts +9 -4
- package/src/__tests__/config-schema-cmd.test.ts +10 -11
- package/src/__tests__/config-schema.test.ts +190 -257
- package/src/__tests__/conversation-agent-loop-fatal-cleanup.test.ts +208 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +5 -19
- package/src/__tests__/conversation-agent-loop.test.ts +22 -9
- package/src/__tests__/conversation-error.test.ts +31 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +110 -0
- package/src/__tests__/conversation-process-callsite.test.ts +12 -19
- package/src/__tests__/conversation-routes-slash-commands.test.ts +7 -21
- package/src/__tests__/conversation-summarize-route.test.ts +36 -44
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +7 -7
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +0 -1
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +0 -1
- package/src/__tests__/conversation-usage.test.ts +4 -12
- package/src/__tests__/credential-routes.test.ts +250 -0
- package/src/__tests__/credential-security-invariants.test.ts +3 -0
- package/src/__tests__/db-migration-rollback.test.ts +22 -0
- package/src/__tests__/empty-response-hook.test.ts +186 -1
- package/src/__tests__/external-plugin-loader.test.ts +11 -5
- package/src/__tests__/heartbeat-service.test.ts +0 -28
- package/src/__tests__/host-shell-tool.test.ts +2 -0
- package/src/__tests__/inactive-tool-error-messages.test.ts +2 -2
- package/src/__tests__/inference-no-mode-boot-e2e.test.ts +52 -8
- package/src/__tests__/internal-telemetry-routes.test.ts +23 -4
- package/src/__tests__/invite-routes-http.test.ts +12 -16
- package/src/__tests__/list-all-apps.test.ts +0 -4
- package/src/__tests__/llm-context-resolution.test.ts +32 -56
- package/src/__tests__/llm-request-log-turn-query.test.ts +109 -0
- package/src/__tests__/llm-resolver-override-or-default.test.ts +3 -52
- package/src/__tests__/llm-resolver.test.ts +342 -602
- package/src/__tests__/llm-schema.test.ts +79 -37
- package/src/__tests__/max-tokens-continue-hook.test.ts +19 -0
- package/src/__tests__/media-stream-output.test.ts +259 -3
- package/src/__tests__/media-stream-server-integration.test.ts +22 -1
- package/src/__tests__/media-stream-stt-session.test.ts +47 -0
- package/src/__tests__/memory-jobs-worker-cleanup-cadence.test.ts +33 -0
- package/src/__tests__/memory-recall-log-store.test.ts +47 -13
- package/src/__tests__/mock-gateway-ipc.ts +46 -1
- package/src/__tests__/mtime-cache.test.ts +61 -0
- package/src/__tests__/navigate-settings-tab.test.ts +2 -0
- package/src/__tests__/normalize-onboarding.test.ts +33 -0
- package/src/__tests__/onboarding-persona-write.test.ts +26 -0
- package/src/__tests__/plugin-api-resolve-credential.test.ts +140 -0
- package/src/__tests__/plugin-app-serve-routes.test.ts +166 -14
- package/src/__tests__/plugin-import-boundary-reverse-guard.test.ts +2 -0
- package/src/__tests__/post-turn-tool-result-truncation.test.ts +38 -0
- package/src/__tests__/provider-commit-message-generator.test.ts +27 -20
- package/src/__tests__/provider-connections-backfill.test.ts +138 -0
- package/src/__tests__/provider-platform-proxy-integration.test.ts +10 -31
- package/src/__tests__/provider-registry-ollama.test.ts +8 -18
- package/src/__tests__/provider-send-message-override-profile.test.ts +23 -23
- package/src/__tests__/provider-usage-tracking.test.ts +9 -19
- package/src/__tests__/prune-old-conversations-job.test.ts +12 -0
- package/src/__tests__/published-app-updater.test.ts +22 -16
- package/src/__tests__/registry.test.ts +5 -16
- package/src/__tests__/retry-openrouter-only-normalization.test.ts +22 -23
- package/src/__tests__/retry-thinking-adaptive-only.test.ts +43 -48
- package/src/__tests__/retry-thinking-tool-choice.test.ts +57 -66
- package/src/__tests__/retry-verbosity-normalization.test.ts +24 -23
- package/src/__tests__/reveal-success-registry.test.ts +123 -0
- package/src/__tests__/run-conversation-turn-persistence.test.ts +130 -0
- package/src/__tests__/secret-fixtures.ts +9 -0
- package/src/__tests__/server-history-render.test.ts +28 -0
- package/src/__tests__/skills.test.ts +9 -4
- package/src/__tests__/slack-share-routes.test.ts +0 -1
- package/src/__tests__/stt-stream-session.test.ts +6 -5
- package/src/__tests__/subagent-call-site-routing.test.ts +69 -95
- package/src/__tests__/subagent-disposal.test.ts +2 -0
- package/src/__tests__/subagent-fork-notifications.test.ts +2 -0
- package/src/__tests__/subagent-fork-spawn.test.ts +2 -0
- package/src/__tests__/subagent-manager-notify.test.ts +2 -0
- package/src/__tests__/subagent-role-registry.test.ts +37 -0
- package/src/__tests__/subagent-spawn-and-await.test.ts +1 -0
- package/src/__tests__/subagent-terminal-message.test.ts +50 -0
- package/src/__tests__/subagent-tool-gate-mode.test.ts +78 -5
- package/src/__tests__/surface-completion-nudge-hook.test.ts +19 -0
- package/src/__tests__/telemetry-routes.test.ts +99 -19
- package/src/__tests__/tool-audit.test.ts +34 -4
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
- package/src/__tests__/tool-profiler.test.ts +72 -1
- package/src/__tests__/tool-result-spool.test.ts +49 -4
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +0 -1
- package/src/__tests__/ui-channel-variants.test.ts +108 -0
- package/src/__tests__/ui-shape-teaching.test.ts +255 -0
- package/src/__tests__/usage-attribution.test.ts +18 -41
- package/src/__tests__/user-plugin-loader.test.ts +4 -4
- package/src/__tests__/voice-config-update.test.ts +46 -0
- package/src/__tests__/voice-session-bridge.test.ts +216 -84
- package/src/__tests__/workspace-migration-131-drop-web-fetch-mode.test.ts +120 -0
- package/src/agent/loop.ts +4 -3
- package/src/api/events/open-conversation.test.ts +64 -0
- package/src/api/events/open-conversation.ts +33 -0
- package/src/api/index.ts +6 -0
- package/src/api/responses/conversation-message.ts +5 -0
- package/src/apps/app-store.ts +25 -35
- package/src/bundler/app-bundler.ts +34 -48
- package/src/bundler/app-compiler.ts +39 -4
- package/src/bundler/bundle-scanner.ts +13 -0
- package/src/bundler/manifest.ts +1 -1
- package/src/calls/__tests__/voice-session-bridge.test.ts +47 -0
- package/src/calls/call-constants.ts +5 -0
- package/src/calls/call-controller.ts +100 -32
- package/src/calls/call-transport.ts +9 -0
- package/src/calls/media-stream-output.ts +107 -4
- package/src/calls/media-stream-server.ts +29 -9
- package/src/calls/media-stream-stt-session.ts +7 -1
- package/src/calls/media-turn-detector.ts +11 -1
- package/src/calls/voice-session-bridge.ts +84 -63
- package/src/cli/commands/__tests__/inference-providers.test.ts +270 -33
- package/src/cli/commands/__tests__/notifications.test.ts +24 -3
- package/src/cli/commands/config.help.ts +6 -6
- package/src/cli/commands/credentials.help.ts +13 -0
- package/src/cli/commands/credentials.ts +6 -1
- package/src/cli/commands/email.help.ts +7 -0
- package/src/cli/commands/email.ts +35 -1
- package/src/cli/commands/inference-providers.ts +168 -107
- package/src/cli/commands/inference.help.ts +118 -46
- package/src/cli/commands/memory/index.help.ts +23 -0
- package/src/cli/commands/memory/nodes.ts +146 -0
- package/src/cli/commands/notifications.help.ts +10 -10
- package/src/cli/commands/oauth/connect-surface-guidance.test.ts +40 -0
- package/src/cli/commands/oauth/connect-surface-guidance.ts +54 -0
- package/src/cli/commands/oauth/connect.test.ts +126 -0
- package/src/cli/commands/oauth/connect.ts +29 -6
- package/src/cli/commands/oauth/index.help.ts +7 -1
- package/src/cli/commands/oauth/status.test.ts +69 -3
- package/src/cli/commands/oauth/status.ts +50 -12
- package/src/cli/commands/plugins.help.ts +13 -2
- package/src/cli/commands/plugins.ts +61 -7
- package/src/cli/commands/telemetry.help.ts +13 -0
- package/src/cli/commands/telemetry.ts +45 -5
- package/src/cli/lib/__tests__/plugin-catalog-local.test.ts +8 -2
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +213 -9
- package/src/cli/lib/bundled-marketplace.json +93 -36
- package/src/cli/lib/inspect-plugin.ts +5 -1
- package/src/cli/lib/install-from-github.ts +68 -4
- package/src/cli/lib/plugin-catalog-local.ts +6 -2
- package/src/cli/lib/plugin-fingerprint.ts +3 -3
- package/src/cli/lib/upgrade-plugin.ts +236 -35
- package/src/config/__tests__/default-profile-catalog.test.ts +8 -12
- package/src/config/__tests__/plugin-resident-skill-discovery.test.ts +137 -0
- package/src/config/__tests__/profile-materialization.test.ts +1 -88
- package/src/config/bundled-skills/AGENTS.md +3 -30
- package/src/config/bundled-skills/app-builder/SKILL.md +5 -3
- package/src/config/bundled-skills/app-builder/TOOLS.json +23 -0
- package/src/config/bundled-skills/app-builder/tools/app-open.ts +32 -0
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +1 -1
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +7 -7
- package/src/config/bundled-skills/schedule/SKILL.md +1 -1
- package/src/config/bundled-skills/schedule/TOOLS.json +1 -1
- package/src/config/bundled-skills/settings/TOOLS.json +3 -1
- package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +2 -0
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +18 -10
- package/src/config/bundled-skills/subagent/SKILL.md +2 -0
- package/src/config/bundled-skills/subagent/TOOLS.json +1 -1
- package/src/config/call-site-defaults.ts +3 -3
- package/src/config/feature-flag-registry.json +24 -39
- package/src/config/llm-resolver.ts +88 -475
- package/src/config/profile-materialization.ts +11 -11
- package/src/config/schema.ts +93 -127
- package/src/config/schemas/__tests__/live-voice.test.ts +24 -6
- package/src/config/schemas/__tests__/stt.test.ts +31 -3
- package/src/config/schemas/live-voice.ts +10 -4
- package/src/config/schemas/llm.ts +52 -15
- package/src/config/schemas/memory-lifecycle.ts +1 -1
- package/src/config/schemas/memory-retrospective.ts +8 -0
- package/src/config/schemas/memory-v2.ts +2 -2
- package/src/config/schemas/memory-v3.ts +1 -1
- package/src/config/schemas/services.ts +6 -3
- package/src/config/schemas/stt.ts +38 -21
- package/src/config/schemas/tts.ts +13 -18
- package/src/config/skills.ts +31 -21
- package/src/context/compactor.ts +44 -7
- package/src/context/post-turn-tool-result-truncation.ts +4 -2
- package/src/context/tool-result-spool.ts +26 -5
- package/src/conversations/__tests__/message-consolidation.test.ts +48 -0
- package/src/conversations/message-consolidation.ts +22 -2
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +5 -12
- package/src/daemon/app-source-watcher.ts +17 -23
- package/src/daemon/chat-credential-redaction.ts +1365 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +627 -34
- package/src/daemon/conversation-agent-loop.ts +71 -31
- package/src/daemon/conversation-error.ts +36 -14
- package/src/daemon/conversation-process.ts +22 -0
- package/src/daemon/conversation-store.ts +35 -0
- package/src/daemon/conversation-surfaces.ts +25 -25
- package/src/daemon/conversation-tool-setup.ts +33 -7
- package/src/daemon/conversation.ts +55 -5
- package/src/daemon/handlers/shared.ts +33 -2
- package/src/daemon/lifecycle.ts +4 -4
- package/src/daemon/message-types/conversations.ts +6 -17
- package/src/daemon/providers-setup.ts +8 -0
- package/src/daemon/tool-setup-types.ts +7 -1
- package/src/daemon/wake-conversation-ops.ts +10 -1
- package/src/hooks/types.ts +9 -0
- package/src/ipc/__tests__/email-ipc.test.ts +90 -0
- package/src/ipc/gateway-client.test.ts +59 -0
- package/src/ipc/gateway-client.ts +70 -27
- package/src/live-voice/__tests__/live-voice-events.test.ts +14 -2
- package/src/live-voice/__tests__/live-voice-integration.test.ts +116 -2
- package/src/live-voice/__tests__/live-voice-vad.test.ts +804 -13
- package/src/live-voice/__tests__/protocol.test.ts +122 -0
- package/src/live-voice/live-voice-session.ts +443 -40
- package/src/live-voice/protocol.ts +143 -1
- package/src/monitoring/__tests__/plugin-source-watch.test.ts +3 -1
- package/src/monitoring/plugin-source-watch.ts +3 -62
- package/src/notifications/README.md +1 -1
- package/src/permissions/checker.ts +8 -4
- package/src/persistence/__tests__/db-init-migrations-ok.test.ts +26 -0
- package/src/persistence/conversation-crud.ts +104 -2
- package/src/persistence/db-init.ts +14 -3
- package/src/persistence/job-handlers/cleanup.ts +15 -7
- package/src/persistence/llm-request-log-store.ts +88 -52
- package/src/persistence/migrations/298-move-memory-jobs-to-memory-db.ts +7 -31
- package/src/persistence/migrations/305-drop-contact-acl-columns.ts +3 -2
- package/src/persistence/migrations/326-move-injection-events-to-memory-db.ts +8 -34
- package/src/persistence/migrations/336-move-memory-v2-activation-logs-to-memory-db.ts +90 -0
- package/src/persistence/migrations/337-move-memory-recall-logs-to-memory-db.ts +114 -0
- package/src/persistence/migrations/338-move-memory-v3-selections-to-memory-db.ts +84 -0
- package/src/persistence/migrations/339-move-activation-sessions-to-memory-db.ts +52 -0
- package/src/persistence/migrations/__tests__/run-migrations.test.ts +155 -0
- package/src/persistence/migrations/helpers/relocation.ts +44 -1
- package/src/persistence/migrations/run-migrations.ts +25 -1
- package/src/persistence/schema/infrastructure.ts +9 -0
- package/src/persistence/schema/memory-core.ts +3 -0
- package/src/persistence/schema/memory-injection.ts +2 -0
- package/src/persistence/steps.ts +36 -0
- package/src/platform/client.test.ts +1 -44
- package/src/platform/client.ts +10 -20
- package/src/platform/consent-cache.test.ts +89 -23
- package/src/platform/consent-cache.ts +71 -33
- package/src/plugin-api/constants.ts +12 -0
- package/src/plugin-api/conversation-turn.ts +37 -14
- package/src/plugin-api/index.ts +11 -1
- package/src/plugin-api/resolve-credential.ts +75 -0
- package/src/plugin-api/vision-support.test.ts +8 -19
- package/src/plugin-api/vision-support.ts +26 -17
- package/src/plugins/collect-source-versions.ts +77 -0
- package/src/plugins/defaults/compaction/compact.ts +6 -0
- package/src/plugins/defaults/compaction/window-manager.ts +9 -0
- package/src/plugins/defaults/empty-response/hooks/post-model-call.ts +18 -24
- package/src/plugins/defaults/empty-response/hooks/user-prompt-submit.ts +38 -0
- package/src/plugins/defaults/empty-response/refusal-quarantine.ts +99 -0
- package/src/plugins/defaults/image-fallback/__tests__/caption-cache-persistence.test.ts +7 -3
- package/src/plugins/defaults/index.ts +8 -1
- package/src/plugins/defaults/max-tokens-continue/hooks/post-model-call.ts +4 -1
- package/src/plugins/defaults/memory/__tests__/activation-session-store.test.ts +48 -6
- package/src/plugins/defaults/memory/__tests__/db-memory-attach.test.ts +28 -22
- package/src/plugins/defaults/memory/__tests__/memory-log-stores-degraded.test.ts +148 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +80 -8
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +202 -0
- package/src/plugins/defaults/memory/__tests__/memory-v2-activation-log-store.test.ts +64 -25
- package/src/plugins/defaults/memory/__tests__/memory-v2-concept-frequency.test.ts +24 -11
- package/src/plugins/defaults/memory/__tests__/prompt-override.test.ts +70 -6
- package/src/plugins/defaults/memory/__tests__/table-relocation.test.ts +278 -0
- package/src/plugins/defaults/memory/activation-session-store.ts +27 -20
- package/src/plugins/defaults/memory/context-search/sources/memory-v2.ts +2 -9
- package/src/plugins/defaults/memory/context-search/sources/workspace.ts +1 -8
- package/src/plugins/defaults/memory/graph/retriever.test.ts +6 -6
- package/src/plugins/defaults/memory/graph/store.ts +114 -0
- package/src/plugins/defaults/memory/graph/tool-handlers.ts +36 -1
- package/src/plugins/defaults/memory/graph/tools.ts +47 -13
- package/src/plugins/defaults/memory/graph-topology/build-memory-graph.ts +16 -35
- package/src/plugins/defaults/memory/jobs-worker.ts +10 -1
- package/src/plugins/defaults/memory/memory-db.ts +3 -2
- package/src/plugins/defaults/memory/memory-recall-log-store.ts +129 -66
- package/src/plugins/defaults/memory/memory-retrospective-constants.ts +8 -0
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +11 -122
- package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +216 -0
- package/src/plugins/defaults/memory/memory-v2-activation-log-store.ts +84 -46
- package/src/plugins/defaults/memory/memory-v2-concept-frequency.ts +42 -32
- package/src/plugins/defaults/memory/path-containment.ts +21 -0
- package/src/plugins/defaults/memory/prompt-override.ts +51 -13
- package/src/plugins/defaults/memory/tools.test.ts +34 -0
- package/src/plugins/defaults/memory/tools.ts +12 -2
- package/src/plugins/defaults/memory/v2/__tests__/harness-compare.test.ts +19 -15
- package/src/plugins/defaults/memory/v2/__tests__/harness-oracle.test.ts +24 -19
- package/src/plugins/defaults/memory/v2/__tests__/harness-replay-input.test.ts +19 -15
- package/src/plugins/defaults/memory/v2/__tests__/injection.test.ts +22 -2
- package/src/plugins/defaults/memory/v2/__tests__/prompts-consolidation.test.ts +5 -3
- package/src/plugins/defaults/memory/v2/harness/oracle.ts +59 -41
- package/src/plugins/defaults/memory/v2/harness/replay-input.ts +29 -25
- package/src/plugins/defaults/memory/v2/migration.ts +46 -16
- package/src/plugins/defaults/memory/v2/prompts/consolidation.ts +4 -0
- package/src/plugins/defaults/memory/v3/__tests__/carry-integration.test.ts +17 -15
- package/src/plugins/defaults/memory/v3/__tests__/gate.test.ts +24 -22
- package/src/plugins/defaults/memory/v3/__tests__/injection.test.ts +9 -5
- package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +277 -10
- package/src/plugins/defaults/memory/v3/__tests__/selection-log-store.test.ts +57 -5
- package/src/plugins/defaults/memory/v3/__tests__/shadow-integration.test.ts +9 -7
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +38 -7
- package/src/plugins/defaults/memory/v3/hot-set.test.ts +36 -18
- package/src/plugins/defaults/memory/v3/hot-set.ts +12 -14
- package/src/plugins/defaults/memory/v3/learned-edges.test.ts +47 -27
- package/src/plugins/defaults/memory/v3/learned-edges.ts +12 -14
- package/src/plugins/defaults/memory/v3/orchestrate.ts +139 -22
- package/src/plugins/defaults/memory/v3/prune.test.ts +10 -3
- package/src/plugins/defaults/memory/v3/prune.ts +17 -11
- package/src/plugins/defaults/memory/v3/selection-log-store.ts +23 -11
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +70 -53
- package/src/plugins/defaults/surface-completion-nudge/hooks/post-model-call.ts +9 -6
- package/src/plugins/external-plugin-loader.ts +15 -15
- package/src/plugins/mtime-cache.ts +47 -0
- package/src/plugins/pipeline.ts +9 -1
- package/src/plugins/plugin-execution-context.ts +44 -0
- package/src/plugins/plugin-tree-walk.ts +31 -24
- package/src/plugins/source-fingerprint.ts +3 -4
- package/src/prompts/normalize-onboarding.ts +12 -0
- package/src/prompts/persona-resolver.ts +8 -0
- package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +1 -1
- package/src/providers/__tests__/dispatch-connection-routing.test.ts +6 -9
- package/src/providers/__tests__/registry-native-web-search.test.ts +4 -10
- package/src/providers/__tests__/retry-callsite.test.ts +235 -215
- package/src/providers/__tests__/satellite-connection-routing.test.ts +8 -16
- package/src/providers/atlascloud/client.ts +10 -49
- package/src/providers/baseten/client.ts +43 -0
- package/src/providers/call-site-routing.ts +26 -13
- package/src/providers/connection-resolution.ts +9 -11
- package/src/providers/fetch-provider-catalog.ts +4 -2
- package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +29 -4
- package/src/providers/inference/__tests__/connection-availability-keyless.test.ts +78 -0
- package/src/providers/inference/adapter-factory.ts +27 -6
- package/src/providers/inference/auth.ts +29 -1
- package/src/providers/inference/backfill.ts +61 -10
- package/src/providers/inference/connection-availability.ts +3 -2
- package/src/providers/inference/resolve-auth.ts +9 -1
- package/src/providers/model-catalog.ts +37 -0
- package/src/providers/openai/__tests__/api-error-normalization.test.ts +24 -2
- package/src/providers/openai/api-key-validation.ts +70 -0
- package/src/providers/retry.ts +2 -0
- package/src/providers/types.ts +11 -4
- package/src/providers/vellum-model-routing.test.ts +26 -0
- package/src/providers/vellum-model-routing.ts +30 -0
- package/src/providers/voice-error-copy.ts +47 -0
- package/src/runtime/agent-wake.ts +40 -24
- package/src/runtime/for-chat-mint-registry.ts +118 -0
- package/src/runtime/reveal-nonce.ts +49 -0
- package/src/runtime/reveal-success-registry.ts +306 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +88 -3
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +161 -30
- package/src/runtime/routes/__tests__/migration-vellum-metadata-reconcile.test.ts +7 -0
- package/src/runtime/routes/__tests__/schedule-worker-routes.test.ts +15 -0
- package/src/runtime/routes/app-management-routes.ts +152 -45
- package/src/runtime/routes/app-routes.ts +16 -77
- package/src/runtime/routes/canned-message-complete.ts +16 -16
- package/src/runtime/routes/conversation-management-routes.ts +17 -14
- package/src/runtime/routes/conversation-query-routes.ts +54 -6
- package/src/runtime/routes/conversation-routes.ts +48 -2
- package/src/runtime/routes/credential-routes.ts +116 -3
- package/src/runtime/routes/email-routes.ts +17 -1
- package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +33 -5
- package/src/runtime/routes/inbound-stages/transcribe-audio.ts +6 -5
- package/src/runtime/routes/inference-provider-connection-routes.ts +77 -28
- package/src/runtime/routes/inference-send-routes.ts +1 -1
- package/src/runtime/routes/internal-telemetry-routes.ts +7 -6
- package/src/runtime/routes/plugins-routes.ts +37 -6
- package/src/runtime/routes/publish-routes.ts +15 -18
- package/src/runtime/routes/schedule-worker-routes.ts +9 -0
- package/src/runtime/routes/secret-routes.ts +10 -0
- package/src/runtime/routes/telemetry-routes.ts +149 -45
- package/src/schedule/__tests__/schedule-timezone.test.ts +101 -0
- package/src/schedule/__tests__/worker-watchdog.test.ts +209 -0
- package/src/schedule/schedule-store.ts +12 -1
- package/src/schedule/schedule-timezone.ts +63 -0
- package/src/schedule/scheduler.ts +100 -6
- package/src/schedule/worker-control.ts +19 -0
- package/src/security/auth-fallback-events-store.ts +7 -6
- package/src/security/secret-scanner.ts +26 -1
- package/src/services/published-app-updater.ts +6 -11
- package/src/stt/stt-stream-session.ts +36 -16
- package/src/subagent/manager.ts +34 -8
- package/src/telemetry/AGENTS.md +30 -1
- package/src/telemetry/__tests__/config-setting-snapshot.test.ts +18 -0
- package/src/telemetry/__tests__/outbox-test-harness.ts +5 -3
- package/src/telemetry/config-setting-snapshot.ts +44 -10
- package/src/telemetry/telemetry-event-sources.test.ts +124 -30
- package/src/telemetry/telemetry-event-sources.ts +137 -83
- package/src/telemetry/telemetry-events-outbox.test.ts +46 -1
- package/src/telemetry/telemetry-events-outbox.ts +60 -9
- package/src/telemetry/telemetry-wire-source.json +1 -1
- package/src/telemetry/telemetry-wire-validation.ts +39 -2
- package/src/telemetry/telemetry-wire.generated.ts +8 -0
- package/src/telemetry/tool-audit.ts +15 -9
- package/src/telemetry/tool-executed-events-store.test.ts +1 -1
- package/src/telemetry/turn-events-store.ts +20 -0
- package/src/telemetry/types.ts +45 -12
- package/src/telemetry/usage-telemetry-reporter.test.ts +294 -25
- package/src/telemetry/usage-telemetry-reporter.ts +117 -18
- package/src/telemetry/watchdog-direct-emit.test.ts +11 -3
- package/src/telemetry/watchdog-direct-emit.ts +11 -6
- package/src/tools/apps/executors.ts +11 -36
- package/src/tools/executor.ts +14 -1
- package/src/tools/host-terminal/host-shell.ts +6 -2
- package/src/tools/network/__tests__/web-fetch-firecrawl.test.ts +1 -1
- package/src/tools/network/__tests__/web-fetch-metadata.test.ts +25 -0
- package/src/tools/network/web-fetch.ts +6 -2
- package/src/tools/skills/sandbox-runner.ts +5 -2
- package/src/tools/subagent/spawn.ts +7 -11
- package/src/tools/terminal/shell.ts +5 -2
- package/src/tools/tool-manifest.ts +0 -2
- package/src/tools/tool-profiler.ts +37 -6
- package/src/tools/ui-surface/channel-variants.ts +101 -0
- package/src/tools/ui-surface/definitions.ts +23 -67
- package/src/tools/ui-surface/surface-shape-docs.ts +229 -0
- package/src/tts/__tests__/provider-adapters.test.ts +18 -0
- package/src/tts/provider-catalog.ts +2 -4
- package/src/tts/providers/deepgram-provider.ts +10 -1
- package/src/types/onboarding-context.ts +8 -0
- package/src/usage/attribution.ts +18 -112
- package/src/{config/bundled-skills/messaging/tools/gmail-mime-helpers.ts → util/mime-type.ts} +4 -1
- package/src/util/provider-error-patterns.ts +7 -1
- package/src/util/worker-process.ts +105 -0
- package/src/watcher/__tests__/telemetry.test.ts +17 -4
- package/src/watcher/telemetry.ts +5 -5
- package/src/workspace/migrations/131-drop-web-fetch-mode.ts +61 -0
- package/src/workspace/migrations/registry.ts +2 -0
- package/src/workspace/provider-commit-message-generator.ts +6 -4
- package/src/__tests__/app-open-proxy.test.ts +0 -67
- package/src/onboarding/onboarding-research-events-store.test.ts +0 -230
- package/src/onboarding/onboarding-research-events-store.ts +0 -104
- package/src/runtime/routes/assets/vellum-design-system.css +0 -2236
- package/src/tools/apps/definitions.ts +0 -73
- package/src/tools/apps/open-proxy.ts +0 -43
|
@@ -10,18 +10,18 @@ import type { LLMConfigBase, ProfileEntry } from "./schemas/llm.js";
|
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Materializes a partial custom profile into a complete, standalone
|
|
13
|
-
* override
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* override by filling absent fields from `dflt` (the workspace's default
|
|
14
|
+
* base config — the legacy raw `llm.default` blob when one is still on
|
|
15
|
+
* disk, otherwise `LLMConfigBase` schema defaults). Single-winner
|
|
16
|
+
* resolution never merges one profile's fields into another, so a custom
|
|
17
|
+
* profile must carry its own provider and model to be a usable selection
|
|
18
|
+
* target — materialization is what completes it. Rules:
|
|
16
19
|
*
|
|
17
|
-
* - Non-null
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* - A model-only profile gets the provider `withImpliedProviders` would
|
|
23
|
-
* stamp: the default provider when it serves the model, else the model's
|
|
24
|
-
* catalog owner.
|
|
20
|
+
* - Non-null base `temperature`/`topP` ARE inherited; null values are
|
|
21
|
+
* skipped (same resolved result, no noise). `logitBias` is NEVER
|
|
22
|
+
* inherited — it is profile-opt-in only.
|
|
23
|
+
* - A model-only profile gets the provider the catalog implies: the base
|
|
24
|
+
* provider when it serves the model, else the model's catalog owner.
|
|
25
25
|
*
|
|
26
26
|
* Mix profiles (no config fields, schema-enforced) and managed profiles
|
|
27
27
|
* (bodies owned by the code catalog) pass through untouched. Idempotent,
|
package/src/config/schema.ts
CHANGED
|
@@ -60,135 +60,101 @@ import { ToolsConfigSchema } from "./schemas/tools.js";
|
|
|
60
60
|
import { WorkflowsConfigSchema } from "./schemas/workflows.js";
|
|
61
61
|
import { WorkspaceGitConfigSchema } from "./schemas/workspace-git.js";
|
|
62
62
|
|
|
63
|
-
export const AssistantConfigSchema = z
|
|
64
|
-
.
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
63
|
+
export const AssistantConfigSchema = z.object({
|
|
64
|
+
services: ServicesSchema.default(ServicesSchema.parse({})),
|
|
65
|
+
memory: MemoryConfigSchema.default(MemoryConfigSchema.parse({})),
|
|
66
|
+
monitoring: MonitoringConfigSchema.default(MonitoringConfigSchema.parse({})),
|
|
67
|
+
migrations: MigrationsConfigSchema.default(MigrationsConfigSchema.parse({})),
|
|
68
|
+
dataDir: z
|
|
69
|
+
.string({ error: "dataDir must be a string" })
|
|
70
|
+
.default(getDataDir())
|
|
71
|
+
.describe("Directory for storing assistant data (database, logs, etc.)"),
|
|
72
|
+
timeouts: TimeoutConfigSchema.default(TimeoutConfigSchema.parse({})),
|
|
73
|
+
rateLimit: RateLimitConfigSchema.default(RateLimitConfigSchema.parse({})),
|
|
74
|
+
secretDetection: SecretDetectionConfigSchema.default(
|
|
75
|
+
SecretDetectionConfigSchema.parse({}),
|
|
76
|
+
),
|
|
77
|
+
auditLog: AuditLogConfigSchema.default(AuditLogConfigSchema.parse({})),
|
|
78
|
+
logFile: LogFileConfigSchema.default(
|
|
79
|
+
LogFileConfigSchema.parse({ dir: getDataDir() + "/logs" }),
|
|
80
|
+
),
|
|
81
|
+
// Unified LLM configuration block. The unique source of truth for
|
|
82
|
+
// provider/model/maxTokens/effort/speed/temperature/thinking/contextWindow
|
|
83
|
+
// and pricing overrides for every call site in the assistant.
|
|
84
|
+
//
|
|
85
|
+
// Default values live on each leaf inside `LLMSchema` (see
|
|
86
|
+
// `schemas/llm.ts`), so `LLMSchema.parse({})` returns a fully-populated
|
|
87
|
+
// object. This matches the pattern used by sibling schemas above and
|
|
88
|
+
// ensures the loader's leaf-deletion recovery path can repair a partially
|
|
89
|
+
// invalid `llm` block without falling back to `cloneDefaultConfig()`.
|
|
90
|
+
llm: LLMSchema.default(LLMSchema.parse({})),
|
|
91
|
+
llmRequestLogs: LlmRequestLogsConfigSchema,
|
|
92
|
+
filing: FilingConfigSchema.default(FilingConfigSchema.parse({})),
|
|
93
|
+
heartbeat: HeartbeatConfigSchema.default(HeartbeatConfigSchema.parse({})),
|
|
94
|
+
hostBrowser: HostBrowserConfigSchema.default(
|
|
95
|
+
HostBrowserConfigSchema.parse({}),
|
|
96
|
+
),
|
|
97
|
+
conversations: ConversationsConfigSchema.default(
|
|
98
|
+
ConversationsConfigSchema.parse({}),
|
|
99
|
+
),
|
|
100
|
+
journal: JournalConfigSchema.default(JournalConfigSchema.parse({})),
|
|
101
|
+
backup: BackupConfigSchema.default(BackupConfigSchema.parse({})),
|
|
102
|
+
mcp: McpConfigSchema.default(McpConfigSchema.parse({})),
|
|
103
|
+
acp: AcpConfigSchema.default(AcpConfigSchema.parse({})),
|
|
104
|
+
skills: SkillsConfigSchema.default(SkillsConfigSchema.parse({})),
|
|
105
|
+
workspaceGit: WorkspaceGitConfigSchema.default(
|
|
106
|
+
WorkspaceGitConfigSchema.parse({}),
|
|
107
|
+
),
|
|
108
|
+
compaction: CompactionConfigSchema.default(CompactionConfigSchema.parse({})),
|
|
109
|
+
compactionLogs: CompactionLogsConfigSchema,
|
|
110
|
+
twilio: TwilioConfigSchema.default(TwilioConfigSchema.parse({})),
|
|
111
|
+
calls: CallsConfigSchema.default(CallsConfigSchema.parse({})),
|
|
112
|
+
liveVoice: LiveVoiceConfigSchema.default(LiveVoiceConfigSchema.parse({})),
|
|
113
|
+
whatsapp: WhatsAppConfigSchema.default(WhatsAppConfigSchema.parse({})),
|
|
114
|
+
telegram: TelegramConfigSchema.default(TelegramConfigSchema.parse({})),
|
|
115
|
+
slack: SlackConfigSchema.default(SlackConfigSchema.parse({})),
|
|
116
|
+
a2a: A2AConfigSchema.default(A2AConfigSchema.parse({})),
|
|
117
|
+
ingress: IngressConfigSchema,
|
|
118
|
+
platform: PlatformConfigSchema.default(PlatformConfigSchema.parse({})),
|
|
119
|
+
daemon: DaemonConfigSchema.default(DaemonConfigSchema.parse({})),
|
|
120
|
+
notifications: NotificationsConfigSchema.default(
|
|
121
|
+
NotificationsConfigSchema.parse({}),
|
|
122
|
+
),
|
|
123
|
+
ui: UiConfigSchema.default(UiConfigSchema.parse({})),
|
|
124
|
+
tools: ToolsConfigSchema.default(ToolsConfigSchema.parse({})),
|
|
125
|
+
workflows: WorkflowsConfigSchema.default(WorkflowsConfigSchema.parse({})),
|
|
126
|
+
// Per-plugin config blocks keyed by plugin name. The schema is intentionally
|
|
127
|
+
// permissive — each plugin's manifest supplies its own validator which the
|
|
128
|
+
// plugin bootstrap (`external-plugins-bootstrap.ts`) runs against the raw
|
|
129
|
+
// block under `plugins.<name>` before handing the parsed result to the
|
|
130
|
+
// plugin's `init()`. Keeping this open here means adding a new plugin does
|
|
131
|
+
// not require a core-schema change, while invalid configs still surface
|
|
132
|
+
// through the plugin's own validator at bootstrap.
|
|
133
|
+
plugins: z
|
|
134
|
+
.record(z.string(), z.unknown())
|
|
135
|
+
.optional()
|
|
136
|
+
.describe(
|
|
137
|
+
"Per-plugin configuration keyed by plugin name. Validated downstream by each plugin's manifest.config validator at bootstrap.",
|
|
69
138
|
),
|
|
70
|
-
|
|
71
|
-
|
|
139
|
+
legacyTelemetryOptOut: z
|
|
140
|
+
.boolean()
|
|
141
|
+
.optional()
|
|
142
|
+
.describe(
|
|
143
|
+
"Fail-closed telemetry marker: set for a workspace that had an explicit local usage-data opt-out before telemetry moved to platform share_analytics consent. While set, usage telemetry stays disabled regardless of platform consent.",
|
|
72
144
|
),
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
rateLimit: RateLimitConfigSchema.default(RateLimitConfigSchema.parse({})),
|
|
79
|
-
secretDetection: SecretDetectionConfigSchema.default(
|
|
80
|
-
SecretDetectionConfigSchema.parse({}),
|
|
145
|
+
legacyDiagnosticsOptOut: z
|
|
146
|
+
.boolean()
|
|
147
|
+
.optional()
|
|
148
|
+
.describe(
|
|
149
|
+
"Fail-closed diagnostics marker: set for a workspace that had an explicit local sendDiagnostics opt-out before crash reporting moved to platform share_diagnostics consent. While set, Sentry stays disabled regardless of platform consent.",
|
|
81
150
|
),
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
)
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
// Default values live on each leaf inside `LLMSchema` (see
|
|
91
|
-
// `schemas/llm.ts`), so `LLMSchema.parse({})` returns a fully-populated
|
|
92
|
-
// object. This matches the pattern used by sibling schemas above and
|
|
93
|
-
// ensures the loader's leaf-deletion recovery path can repair a partially
|
|
94
|
-
// invalid `llm` block without falling back to `cloneDefaultConfig()`.
|
|
95
|
-
llm: LLMSchema.default(LLMSchema.parse({})),
|
|
96
|
-
llmRequestLogs: LlmRequestLogsConfigSchema,
|
|
97
|
-
filing: FilingConfigSchema.default(FilingConfigSchema.parse({})),
|
|
98
|
-
heartbeat: HeartbeatConfigSchema.default(HeartbeatConfigSchema.parse({})),
|
|
99
|
-
hostBrowser: HostBrowserConfigSchema.default(
|
|
100
|
-
HostBrowserConfigSchema.parse({}),
|
|
101
|
-
),
|
|
102
|
-
conversations: ConversationsConfigSchema.default(
|
|
103
|
-
ConversationsConfigSchema.parse({}),
|
|
104
|
-
),
|
|
105
|
-
journal: JournalConfigSchema.default(JournalConfigSchema.parse({})),
|
|
106
|
-
backup: BackupConfigSchema.default(BackupConfigSchema.parse({})),
|
|
107
|
-
mcp: McpConfigSchema.default(McpConfigSchema.parse({})),
|
|
108
|
-
acp: AcpConfigSchema.default(AcpConfigSchema.parse({})),
|
|
109
|
-
skills: SkillsConfigSchema.default(SkillsConfigSchema.parse({})),
|
|
110
|
-
workspaceGit: WorkspaceGitConfigSchema.default(
|
|
111
|
-
WorkspaceGitConfigSchema.parse({}),
|
|
112
|
-
),
|
|
113
|
-
compaction: CompactionConfigSchema.default(
|
|
114
|
-
CompactionConfigSchema.parse({}),
|
|
115
|
-
),
|
|
116
|
-
compactionLogs: CompactionLogsConfigSchema,
|
|
117
|
-
twilio: TwilioConfigSchema.default(TwilioConfigSchema.parse({})),
|
|
118
|
-
calls: CallsConfigSchema.default(CallsConfigSchema.parse({})),
|
|
119
|
-
liveVoice: LiveVoiceConfigSchema.default(LiveVoiceConfigSchema.parse({})),
|
|
120
|
-
whatsapp: WhatsAppConfigSchema.default(WhatsAppConfigSchema.parse({})),
|
|
121
|
-
telegram: TelegramConfigSchema.default(TelegramConfigSchema.parse({})),
|
|
122
|
-
slack: SlackConfigSchema.default(SlackConfigSchema.parse({})),
|
|
123
|
-
a2a: A2AConfigSchema.default(A2AConfigSchema.parse({})),
|
|
124
|
-
ingress: IngressConfigSchema,
|
|
125
|
-
platform: PlatformConfigSchema.default(PlatformConfigSchema.parse({})),
|
|
126
|
-
daemon: DaemonConfigSchema.default(DaemonConfigSchema.parse({})),
|
|
127
|
-
notifications: NotificationsConfigSchema.default(
|
|
128
|
-
NotificationsConfigSchema.parse({}),
|
|
129
|
-
),
|
|
130
|
-
ui: UiConfigSchema.default(UiConfigSchema.parse({})),
|
|
131
|
-
tools: ToolsConfigSchema.default(ToolsConfigSchema.parse({})),
|
|
132
|
-
workflows: WorkflowsConfigSchema.default(WorkflowsConfigSchema.parse({})),
|
|
133
|
-
// Per-plugin config blocks keyed by plugin name. The schema is intentionally
|
|
134
|
-
// permissive — each plugin's manifest supplies its own validator which the
|
|
135
|
-
// plugin bootstrap (`external-plugins-bootstrap.ts`) runs against the raw
|
|
136
|
-
// block under `plugins.<name>` before handing the parsed result to the
|
|
137
|
-
// plugin's `init()`. Keeping this open here means adding a new plugin does
|
|
138
|
-
// not require a core-schema change, while invalid configs still surface
|
|
139
|
-
// through the plugin's own validator at bootstrap.
|
|
140
|
-
plugins: z
|
|
141
|
-
.record(z.string(), z.unknown())
|
|
142
|
-
.optional()
|
|
143
|
-
.describe(
|
|
144
|
-
"Per-plugin configuration keyed by plugin name. Validated downstream by each plugin's manifest.config validator at bootstrap.",
|
|
145
|
-
),
|
|
146
|
-
legacyTelemetryOptOut: z
|
|
147
|
-
.boolean()
|
|
148
|
-
.optional()
|
|
149
|
-
.describe(
|
|
150
|
-
"Fail-closed telemetry marker: set for a workspace that had an explicit local usage-data opt-out before telemetry moved to platform share_analytics consent. While set, usage telemetry stays disabled regardless of platform consent.",
|
|
151
|
-
),
|
|
152
|
-
legacyDiagnosticsOptOut: z
|
|
153
|
-
.boolean()
|
|
154
|
-
.optional()
|
|
155
|
-
.describe(
|
|
156
|
-
"Fail-closed diagnostics marker: set for a workspace that had an explicit local sendDiagnostics opt-out before crash reporting moved to platform share_diagnostics consent. While set, Sentry stays disabled regardless of platform consent.",
|
|
157
|
-
),
|
|
158
|
-
maxStepsPerSession: z
|
|
159
|
-
.number({ error: "maxStepsPerSession must be a number" })
|
|
160
|
-
.int("maxStepsPerSession must be an integer")
|
|
161
|
-
.min(1, "maxStepsPerSession must be >= 1")
|
|
162
|
-
.max(200, "maxStepsPerSession must be <= 200")
|
|
163
|
-
.default(50)
|
|
164
|
-
.describe("Maximum number of computer-use steps per session"),
|
|
165
|
-
})
|
|
166
|
-
.superRefine((config, ctx) => {
|
|
167
|
-
const llmContextWindow = config.llm?.default?.contextWindow;
|
|
168
|
-
if (
|
|
169
|
-
llmContextWindow?.targetBudgetRatio != null &&
|
|
170
|
-
llmContextWindow?.compactThreshold != null &&
|
|
171
|
-
llmContextWindow.targetBudgetRatio >= llmContextWindow.compactThreshold
|
|
172
|
-
) {
|
|
173
|
-
ctx.addIssue({
|
|
174
|
-
code: z.ZodIssueCode.custom,
|
|
175
|
-
path: ["llm", "default", "contextWindow", "targetBudgetRatio"],
|
|
176
|
-
message:
|
|
177
|
-
"llm.default.contextWindow.targetBudgetRatio must be less than llm.default.contextWindow.compactThreshold",
|
|
178
|
-
});
|
|
179
|
-
}
|
|
180
|
-
if (
|
|
181
|
-
llmContextWindow?.targetBudgetRatio != null &&
|
|
182
|
-
llmContextWindow?.summaryBudgetRatio != null &&
|
|
183
|
-
llmContextWindow.targetBudgetRatio <= llmContextWindow.summaryBudgetRatio
|
|
184
|
-
) {
|
|
185
|
-
ctx.addIssue({
|
|
186
|
-
code: z.ZodIssueCode.custom,
|
|
187
|
-
path: ["llm", "default", "contextWindow", "targetBudgetRatio"],
|
|
188
|
-
message:
|
|
189
|
-
"llm.default.contextWindow.targetBudgetRatio must be greater than llm.default.contextWindow.summaryBudgetRatio",
|
|
190
|
-
});
|
|
191
|
-
}
|
|
192
|
-
});
|
|
151
|
+
maxStepsPerSession: z
|
|
152
|
+
.number({ error: "maxStepsPerSession must be a number" })
|
|
153
|
+
.int("maxStepsPerSession must be an integer")
|
|
154
|
+
.min(1, "maxStepsPerSession must be >= 1")
|
|
155
|
+
.max(200, "maxStepsPerSession must be <= 200")
|
|
156
|
+
.default(50)
|
|
157
|
+
.describe("Maximum number of computer-use steps per session"),
|
|
158
|
+
});
|
|
193
159
|
|
|
194
160
|
export type AssistantConfig = z.infer<typeof AssistantConfigSchema>;
|
|
@@ -11,9 +11,9 @@ describe("LiveVoiceVadConfigSchema", () => {
|
|
|
11
11
|
const parsed = LiveVoiceVadConfigSchema.parse({});
|
|
12
12
|
expect(parsed).toEqual({
|
|
13
13
|
speechEnergyThreshold: 800,
|
|
14
|
-
silenceThresholdMs:
|
|
14
|
+
silenceThresholdMs: 1200,
|
|
15
15
|
maxTurnDurationMs: 30_000,
|
|
16
|
-
bargeInMinSpeechMs:
|
|
16
|
+
bargeInMinSpeechMs: 250,
|
|
17
17
|
});
|
|
18
18
|
});
|
|
19
19
|
|
|
@@ -64,22 +64,40 @@ describe("LiveVoiceConfigSchema", () => {
|
|
|
64
64
|
mode: "open-mic",
|
|
65
65
|
vad: {
|
|
66
66
|
speechEnergyThreshold: 800,
|
|
67
|
-
silenceThresholdMs:
|
|
67
|
+
silenceThresholdMs: 1200,
|
|
68
68
|
maxTurnDurationMs: 30_000,
|
|
69
|
-
bargeInMinSpeechMs:
|
|
69
|
+
bargeInMinSpeechMs: 250,
|
|
70
70
|
},
|
|
71
71
|
maxSessionDurationSeconds: 1800,
|
|
72
|
+
// Off by default: voice turns carry only their transcript, no audio
|
|
73
|
+
// artifacts on the conversation messages (JARVIS-1283).
|
|
74
|
+
archiveAudio: false,
|
|
72
75
|
});
|
|
73
76
|
});
|
|
74
77
|
|
|
78
|
+
test("archiveAudio can be enabled", () => {
|
|
79
|
+
expect(
|
|
80
|
+
LiveVoiceConfigSchema.parse({ archiveAudio: true }).archiveAudio,
|
|
81
|
+
).toBe(true);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
test("rejects a non-boolean archiveAudio", () => {
|
|
85
|
+
const result = LiveVoiceConfigSchema.safeParse({ archiveAudio: "yes" });
|
|
86
|
+
expect(result.success).toBe(false);
|
|
87
|
+
if (!result.success) {
|
|
88
|
+
const msgs = result.error.issues.map((i) => i.message);
|
|
89
|
+
expect(msgs.some((m) => m.includes("liveVoice.archiveAudio"))).toBe(true);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
75
93
|
test("accepts overrides", () => {
|
|
76
94
|
const parsed = LiveVoiceConfigSchema.parse({
|
|
77
95
|
mode: "ptt",
|
|
78
|
-
vad: { silenceThresholdMs:
|
|
96
|
+
vad: { silenceThresholdMs: 900 },
|
|
79
97
|
maxSessionDurationSeconds: 600,
|
|
80
98
|
});
|
|
81
99
|
expect(parsed.mode).toBe("ptt");
|
|
82
|
-
expect(parsed.vad.silenceThresholdMs).toBe(
|
|
100
|
+
expect(parsed.vad.silenceThresholdMs).toBe(900);
|
|
83
101
|
// Unspecified vad fields still get defaults
|
|
84
102
|
expect(parsed.vad.speechEnergyThreshold).toBe(800);
|
|
85
103
|
expect(parsed.vad.maxTurnDurationMs).toBe(30_000);
|
|
@@ -41,6 +41,31 @@ describe("SttServiceSchema", () => {
|
|
|
41
41
|
test("VALID_STT_PROVIDERS includes deepgram", () => {
|
|
42
42
|
expect(VALID_STT_PROVIDERS).toContain("deepgram");
|
|
43
43
|
});
|
|
44
|
+
|
|
45
|
+
test("normalizes the openai/whisper aliases to openai-whisper", () => {
|
|
46
|
+
expect(SttServiceSchema.parse({ provider: "openai" }).provider).toBe(
|
|
47
|
+
"openai-whisper",
|
|
48
|
+
);
|
|
49
|
+
expect(SttServiceSchema.parse({ provider: "whisper" }).provider).toBe(
|
|
50
|
+
"openai-whisper",
|
|
51
|
+
);
|
|
52
|
+
// Case- and whitespace-tolerant.
|
|
53
|
+
expect(SttServiceSchema.parse({ provider: " OpenAI " }).provider).toBe(
|
|
54
|
+
"openai-whisper",
|
|
55
|
+
);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("a canonical provider is unchanged by the alias preprocessor", () => {
|
|
59
|
+
expect(
|
|
60
|
+
SttServiceSchema.parse({ provider: "openai-whisper" }).provider,
|
|
61
|
+
).toBe("openai-whisper");
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
test("rejects an unknown provider with a helpful message", () => {
|
|
65
|
+
expect(() => SttServiceSchema.parse({ provider: "nope" })).toThrow(
|
|
66
|
+
/must be one of/,
|
|
67
|
+
);
|
|
68
|
+
});
|
|
44
69
|
});
|
|
45
70
|
|
|
46
71
|
describe("managed mode", () => {
|
|
@@ -61,15 +86,18 @@ describe("managed mode", () => {
|
|
|
61
86
|
expect(parsed.provider).toBe("vellum");
|
|
62
87
|
});
|
|
63
88
|
|
|
64
|
-
test("
|
|
89
|
+
test("accepts provider vellum regardless of mode", () => {
|
|
65
90
|
const result = SttServiceSchema.safeParse({
|
|
66
91
|
mode: "your-own",
|
|
67
92
|
provider: "vellum",
|
|
68
93
|
});
|
|
69
|
-
expect(result.success).toBe(
|
|
94
|
+
expect(result.success).toBe(true);
|
|
70
95
|
});
|
|
71
96
|
|
|
72
|
-
test("effectiveSttProvider routes managed mode to vellum
|
|
97
|
+
test("effectiveSttProvider routes provider vellum and managed mode to vellum, preserves BYOK otherwise", () => {
|
|
98
|
+
expect(effectiveSttProvider({ mode: "your-own", provider: "vellum" })).toBe(
|
|
99
|
+
"vellum",
|
|
100
|
+
);
|
|
73
101
|
expect(
|
|
74
102
|
effectiveSttProvider({ mode: "managed", provider: "deepgram" }),
|
|
75
103
|
).toBe("vellum");
|
|
@@ -20,9 +20,9 @@ export const LiveVoiceVadConfigSchema = z
|
|
|
20
20
|
.number({ error: "liveVoice.vad.silenceThresholdMs must be a number" })
|
|
21
21
|
.int("liveVoice.vad.silenceThresholdMs must be an integer")
|
|
22
22
|
.positive("liveVoice.vad.silenceThresholdMs must be a positive integer")
|
|
23
|
-
.default(
|
|
23
|
+
.default(1200)
|
|
24
24
|
.describe(
|
|
25
|
-
"Trailing silence duration (ms) after speech that ends the user's turn",
|
|
25
|
+
"Trailing silence duration (ms) after speech that ends the user's turn — the default 'pause before reply'. Clients may override it per-session via the start frame.",
|
|
26
26
|
),
|
|
27
27
|
maxTurnDurationMs: z
|
|
28
28
|
.number({ error: "liveVoice.vad.maxTurnDurationMs must be a number" })
|
|
@@ -38,9 +38,9 @@ export const LiveVoiceVadConfigSchema = z
|
|
|
38
38
|
.nonnegative(
|
|
39
39
|
"liveVoice.vad.bargeInMinSpeechMs must be a nonnegative integer",
|
|
40
40
|
)
|
|
41
|
-
.default(
|
|
41
|
+
.default(250)
|
|
42
42
|
.describe(
|
|
43
|
-
"Sustained speech (ms) required before speech during assistant playback interrupts it
|
|
43
|
+
"Sustained speech (ms) required before speech during assistant playback interrupts it — the default 'interrupt sensitivity' (higher = harder to interrupt). 0 disables the guard. Clients may override it per-session via the start frame. Raised from 60 so brief TTS bleed through imperfect echo cancellation no longer self-interrupts the assistant.",
|
|
44
44
|
),
|
|
45
45
|
})
|
|
46
46
|
.describe(
|
|
@@ -68,6 +68,12 @@ export const LiveVoiceConfigSchema = z
|
|
|
68
68
|
)
|
|
69
69
|
.default(1800)
|
|
70
70
|
.describe("Maximum duration of a single live voice session in seconds"),
|
|
71
|
+
archiveAudio: z
|
|
72
|
+
.boolean({ error: "liveVoice.archiveAudio must be a boolean" })
|
|
73
|
+
.default(false)
|
|
74
|
+
.describe(
|
|
75
|
+
"Persist the recorded user + assistant audio of each voice turn as attachments on the conversation messages. Off by default: voice turns carry only their transcribed text, so no audio-file artifacts land in the conversation history. Enable for playback/debugging.",
|
|
76
|
+
),
|
|
71
77
|
})
|
|
72
78
|
.describe(
|
|
73
79
|
"Live voice (in-app duplex audio) configuration — mic mode, VAD tuning, and session limits",
|
|
@@ -31,6 +31,7 @@ export const LLMProvider = z
|
|
|
31
31
|
"minimax",
|
|
32
32
|
"atlascloud",
|
|
33
33
|
"together",
|
|
34
|
+
"baseten",
|
|
34
35
|
])
|
|
35
36
|
.meta({ id: "LLMProvider" });
|
|
36
37
|
type LLMProvider = z.infer<typeof LLMProvider>;
|
|
@@ -261,14 +262,46 @@ export type ContextWindow = z.infer<typeof ContextWindowSchema>;
|
|
|
261
262
|
// injected. Nested `overflowRecovery` likewise uses its fragment view, so a
|
|
262
263
|
// partial override like `{ overflowRecovery: { maxAttempts: 5 } }` produces
|
|
263
264
|
// exactly that and nothing else.
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
265
|
+
//
|
|
266
|
+
// Cross-field ordering (targetBudgetRatio < compactThreshold, and
|
|
267
|
+
// targetBudgetRatio > summaryBudgetRatio) is enforced only when both sides of
|
|
268
|
+
// a pair are present in the same fragment — a partial override merges with
|
|
269
|
+
// lower layers at resolution time, so a lone field can't be judged here.
|
|
270
|
+
const ContextWindowDeepPartialSchema = z
|
|
271
|
+
.object({
|
|
272
|
+
enabled: ContextEnabledSchema.optional(),
|
|
273
|
+
maxInputTokens: ContextMaxInputTokensSchema.optional(),
|
|
274
|
+
targetBudgetRatio: ContextTargetBudgetRatioSchema.optional(),
|
|
275
|
+
compactThreshold: ContextCompactThresholdSchema.optional(),
|
|
276
|
+
summaryBudgetRatio: ContextSummaryBudgetRatioSchema.optional(),
|
|
277
|
+
overflowRecovery: ContextOverflowRecoveryFragmentSchema.optional(),
|
|
278
|
+
})
|
|
279
|
+
.superRefine((cw, ctx) => {
|
|
280
|
+
if (
|
|
281
|
+
cw.targetBudgetRatio != null &&
|
|
282
|
+
cw.compactThreshold != null &&
|
|
283
|
+
cw.targetBudgetRatio >= cw.compactThreshold
|
|
284
|
+
) {
|
|
285
|
+
ctx.addIssue({
|
|
286
|
+
code: z.ZodIssueCode.custom,
|
|
287
|
+
path: ["targetBudgetRatio"],
|
|
288
|
+
message:
|
|
289
|
+
"contextWindow.targetBudgetRatio must be less than contextWindow.compactThreshold",
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
if (
|
|
293
|
+
cw.targetBudgetRatio != null &&
|
|
294
|
+
cw.summaryBudgetRatio != null &&
|
|
295
|
+
cw.targetBudgetRatio <= cw.summaryBudgetRatio
|
|
296
|
+
) {
|
|
297
|
+
ctx.addIssue({
|
|
298
|
+
code: z.ZodIssueCode.custom,
|
|
299
|
+
path: ["targetBudgetRatio"],
|
|
300
|
+
message:
|
|
301
|
+
"contextWindow.targetBudgetRatio must be greater than contextWindow.summaryBudgetRatio",
|
|
302
|
+
});
|
|
303
|
+
}
|
|
304
|
+
});
|
|
272
305
|
|
|
273
306
|
// ---------------------------------------------------------------------------
|
|
274
307
|
// OpenRouter provider-routing preferences
|
|
@@ -318,10 +351,11 @@ const PricingOverrideSchema = z.object({
|
|
|
318
351
|
// ---------------------------------------------------------------------------
|
|
319
352
|
|
|
320
353
|
/**
|
|
321
|
-
* Fully specified LLM config
|
|
322
|
-
*
|
|
323
|
-
*
|
|
324
|
-
*
|
|
354
|
+
* Fully specified LLM config: every knob has a schema-level default, so
|
|
355
|
+
* `LLMConfigBase.parse({})` returns a complete object. The resolver uses it as
|
|
356
|
+
* the code-owned base every resolved call-site config composes over (see
|
|
357
|
+
* `CODE_DEFAULT_BASE` in `llm-resolver.ts`), and profile materialization
|
|
358
|
+
* completes partial custom profiles against it.
|
|
325
359
|
*/
|
|
326
360
|
export const LLMConfigBase = z.object({
|
|
327
361
|
provider: LLMProvider.default("anthropic"),
|
|
@@ -510,7 +544,6 @@ const DefaultProviderField = DefaultProviderSchema.optional().catch(undefined);
|
|
|
510
544
|
|
|
511
545
|
export const LLMSchema = z
|
|
512
546
|
.object({
|
|
513
|
-
default: LLMConfigBase.default(LLMConfigBase.parse({})),
|
|
514
547
|
profiles: z.record(z.string().min(1), ProfileEntry).default({}),
|
|
515
548
|
// Presentation-only order for named profiles. The resolver ignores this;
|
|
516
549
|
// clients use it to render profile pickers consistently.
|
|
@@ -551,7 +584,9 @@ export const LLMSchema = z
|
|
|
551
584
|
...DEFAULT_PROFILE_KEYS,
|
|
552
585
|
]);
|
|
553
586
|
for (const [siteId, siteConfig] of Object.entries(config.callSites ?? {})) {
|
|
554
|
-
if (siteConfig?.profile == null)
|
|
587
|
+
if (siteConfig?.profile == null) {
|
|
588
|
+
continue;
|
|
589
|
+
}
|
|
555
590
|
if (!profileNames.has(siteConfig.profile)) {
|
|
556
591
|
ctx.addIssue({
|
|
557
592
|
code: "custom",
|
|
@@ -596,7 +631,9 @@ export const LLMSchema = z
|
|
|
596
631
|
.map(([name]) => name),
|
|
597
632
|
);
|
|
598
633
|
for (const [name, profile] of Object.entries(config.profiles ?? {})) {
|
|
599
|
-
if (profile?.mix == null)
|
|
634
|
+
if (profile?.mix == null) {
|
|
635
|
+
continue;
|
|
636
|
+
}
|
|
600
637
|
// (d) A mix must not also carry model config — the resolved config comes
|
|
601
638
|
// entirely from the chosen constituent.
|
|
602
639
|
for (const key of MIX_DISALLOWED_CONFIG_KEYS) {
|
|
@@ -137,7 +137,7 @@ export const MemoryCleanupConfigSchema = z
|
|
|
137
137
|
.nullable()
|
|
138
138
|
.default(1 * 60 * 60 * 1000)
|
|
139
139
|
.describe(
|
|
140
|
-
"Retention period for LLM request/response logs in milliseconds (null
|
|
140
|
+
"Retention period for LLM request/response logs in milliseconds (null or 0 disables pruning / keeps forever)",
|
|
141
141
|
),
|
|
142
142
|
})
|
|
143
143
|
.describe("Automatic memory cleanup and garbage collection settings");
|
|
@@ -57,6 +57,14 @@ export const MemoryRetrospectiveConfigSchema = z
|
|
|
57
57
|
.describe(
|
|
58
58
|
"When true, fork-based retrospectives run under the source conversation's inference profile (which forkConversation copies onto the fork) instead of the call site's default. Provider prompt caches are byte-exact prefix matches scoped per model, and a thinking enable/disable mismatch invalidates the messages cache tier — so reusing the source's cached prefix requires the retrospective to resolve the SAME model/thinking/effort as the conversation's own turns. Falls back to the call site's default when the conversation has no profile or the referenced profile no longer exists.",
|
|
59
59
|
),
|
|
60
|
+
|
|
61
|
+
promptPath: z
|
|
62
|
+
.string({ error: "memory.retrospective.promptPath must be a string" })
|
|
63
|
+
.nullable()
|
|
64
|
+
.default(null)
|
|
65
|
+
.describe(
|
|
66
|
+
"Optional path to a file whose contents replace the bundled retrospective fork-instruction prompt. Relative paths resolve under the workspace root; absolute paths and a leading `~/` (expanded to the home directory) are honored only when they still resolve inside the workspace root — a path that lands outside the workspace (including via symlinks) is rejected. The loaded contents may include `{{AVAILABLE_TOOLS_LINE}}`, `{{WINDOW_ANCHOR}}`, `{{ALREADY_REMEMBERED}}`, and `{{SKILL_AUTHORING_SECTION}}`, which are substituted at runtime. If the file is rejected, missing, unreadable, or empty, the bundled prompt is used and a warning is logged.",
|
|
67
|
+
),
|
|
60
68
|
})
|
|
61
69
|
.describe(
|
|
62
70
|
"Controls the memory-retrospective background pass. Model selection lives under llm.callSites.memoryRetrospective.",
|
|
@@ -235,7 +235,7 @@ export const MemoryV2ConfigSchema = z
|
|
|
235
235
|
.nullable()
|
|
236
236
|
.default(null)
|
|
237
237
|
.describe(
|
|
238
|
-
"Optional path to a file whose contents replace the bundled consolidation prompt.
|
|
238
|
+
"Optional path to a file whose contents replace the bundled consolidation prompt. Relative paths resolve under the workspace root; absolute paths and a leading `~/` (expanded to the home directory) are honored only when they still resolve inside the workspace root — a path that lands outside the workspace (including via symlinks) is rejected. The loaded contents may include `{{CUTOFF}}`, which is substituted with the run's ISO-8601 cutoff timestamp. If the file is rejected, missing, unreadable, or empty, the bundled prompt is used and a warning is logged.",
|
|
239
239
|
),
|
|
240
240
|
rerank: z
|
|
241
241
|
.object({
|
|
@@ -306,7 +306,7 @@ export const MemoryV2ConfigSchema = z
|
|
|
306
306
|
.nullable()
|
|
307
307
|
.default(null)
|
|
308
308
|
.describe(
|
|
309
|
-
"Optional path to a file whose contents replace the bundled router prompt.
|
|
309
|
+
"Optional path to a file whose contents replace the bundled router prompt. Relative paths resolve under the workspace root; absolute paths and a leading `~/` (expanded to the home directory) are honored only when they still resolve inside the workspace root — a path that lands outside the workspace (including via symlinks) is rejected. The loaded contents may include `{{ASSISTANT_NAME}}`, `{{USER_NAME}}`, and `{{PAGE_INDEX}}`, which are substituted at runtime. If the file is rejected, missing, unreadable, or empty, the bundled prompt is used and a warning is logged.",
|
|
310
310
|
),
|
|
311
311
|
batch_size: z
|
|
312
312
|
.number()
|
|
@@ -394,7 +394,7 @@ export const MemoryV3ConfigSchema = z
|
|
|
394
394
|
.nullable()
|
|
395
395
|
.default(null)
|
|
396
396
|
.describe(
|
|
397
|
-
"Optional path to a file whose contents replace the bundled per-turn selector system prompt (the instructions that tell the selector which candidate pages to keep).
|
|
397
|
+
"Optional path to a file whose contents replace the bundled per-turn selector system prompt (the instructions that tell the selector which candidate pages to keep). Relative paths resolve under the workspace root; absolute paths and a leading `~/` (expanded to the home directory) are honored only when they still resolve inside the workspace root — a path that lands outside the workspace (including via symlinks) is rejected. The selector prompt takes no placeholders — the candidate pool is supplied separately as the user message — so the file is used verbatim. If the file is rejected, missing, unreadable, empty, or over 1 MiB, the bundled prompt is used and a warning is logged.",
|
|
398
398
|
),
|
|
399
399
|
edge: MemoryV3EdgeSchema.default(MemoryV3EdgeSchema.parse({})),
|
|
400
400
|
entity: MemoryV3EntitySchema.default(MemoryV3EntitySchema.parse({})),
|
|
@@ -66,12 +66,15 @@ const WebSearchServiceSchema = BaseServiceSchema.extend({
|
|
|
66
66
|
.default("inference-provider-native"),
|
|
67
67
|
});
|
|
68
68
|
|
|
69
|
-
|
|
69
|
+
/**
|
|
70
|
+
* Web-fetch carries no `mode`: there is no managed proxy for it, so the only
|
|
71
|
+
* axis is which provider backs the tool.
|
|
72
|
+
*/
|
|
73
|
+
const WebFetchServiceSchema = z.object({
|
|
70
74
|
// Provider that backs the `web_fetch` tool. `default` is the daemon's
|
|
71
75
|
// built-in HTTP fetch + extract path (no key). BYOK providers (e.g.
|
|
72
76
|
// `firecrawl`) scrape via their hosted API and reuse the same stored key as
|
|
73
|
-
// their web-search counterpart.
|
|
74
|
-
// `BaseServiceSchema` for symmetry; web-fetch has no managed proxy today.
|
|
77
|
+
// their web-search counterpart.
|
|
75
78
|
provider: z.enum(VALID_WEB_FETCH_PROVIDERS).default("default"),
|
|
76
79
|
});
|
|
77
80
|
|