@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
|
@@ -1,24 +1,26 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
import { setOverridesForTesting } from "./feature-flag-test-helpers.js";
|
|
4
|
-
|
|
5
|
-
// This suite pins the LEGACY merge-cascade semantics — the kill-switch
|
|
6
|
-
// (flag-off) path. The override-or-default (flag-on, shipped default)
|
|
7
|
-
// semantics are pinned by llm-resolver-override-or-default.test.ts.
|
|
8
|
-
beforeAll(() => {
|
|
9
|
-
setOverridesForTesting({ "override-or-default-resolution": false });
|
|
10
|
-
});
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
11
2
|
|
|
12
3
|
import { z } from "zod";
|
|
13
4
|
|
|
5
|
+
import { CODE_DEFAULT_PROFILE_ENTRIES } from "../config/default-profile-catalog.js";
|
|
14
6
|
import {
|
|
7
|
+
type ResolutionFallbackReason,
|
|
15
8
|
resolveCallSiteConfig,
|
|
16
9
|
resolveDefaultProfileKey,
|
|
17
10
|
resolveEffectiveProfileKey,
|
|
18
11
|
} from "../config/llm-resolver.js";
|
|
19
12
|
import { type LLMCallSite, LLMSchema } from "../config/schemas/llm.js";
|
|
13
|
+
import { resolveModelIntent } from "../providers/model-intents.js";
|
|
20
14
|
|
|
21
|
-
|
|
15
|
+
// Pins the single-winner call-site resolution semantics. The core selection
|
|
16
|
+
// chain (override → active → call-site profile → default intent → anchor) is
|
|
17
|
+
// also pinned by llm-resolver-override-or-default.test.ts; this suite covers
|
|
18
|
+
// composition, fixtures with user profile shadows, mixes, and provenance.
|
|
19
|
+
|
|
20
|
+
// Fully-specified call-site fragment. The call-site tweak is applied last in
|
|
21
|
+
// the base + winner + tweak composition, so this fragment pins every knob of
|
|
22
|
+
// the resolved config regardless of the winning profile.
|
|
23
|
+
const fullTweak = {
|
|
22
24
|
provider: "anthropic" as const,
|
|
23
25
|
model: "claude-opus-4-7",
|
|
24
26
|
maxTokens: 64000,
|
|
@@ -45,44 +47,51 @@ const fullDefault = {
|
|
|
45
47
|
openrouter: { only: [] as string[] },
|
|
46
48
|
};
|
|
47
49
|
|
|
50
|
+
type Fallback = {
|
|
51
|
+
callSite: string;
|
|
52
|
+
requested: string;
|
|
53
|
+
reason: ResolutionFallbackReason;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const collect = () => {
|
|
57
|
+
const fallbacks: Fallback[] = [];
|
|
58
|
+
return {
|
|
59
|
+
fallbacks,
|
|
60
|
+
opts: {
|
|
61
|
+
onResolutionFallback: (info: Fallback) => fallbacks.push(info),
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
};
|
|
65
|
+
|
|
48
66
|
describe("resolveCallSiteConfig", () => {
|
|
49
|
-
test("
|
|
50
|
-
// mainAgent's catalog default (`balanced`) always resolves from the code
|
|
51
|
-
// catalog, so the pure fall-through-to-default path requires a disabled
|
|
52
|
-
// stub (the BYOK hatch state) with no `custom-balanced` present.
|
|
67
|
+
test("a full call-site tweak determines every field of the resolved config", () => {
|
|
53
68
|
const llm = LLMSchema.parse({
|
|
54
|
-
|
|
55
|
-
profiles: { balanced: { source: "managed", status: "disabled" } },
|
|
69
|
+
callSites: { mainAgent: fullTweak },
|
|
56
70
|
});
|
|
57
71
|
const resolved = resolveCallSiteConfig("mainAgent", llm);
|
|
58
|
-
|
|
72
|
+
// The tweak is the last composition layer, so it wins every field it sets
|
|
73
|
+
// over the winning profile's fragment.
|
|
74
|
+
expect(resolved).toMatchObject(fullTweak);
|
|
59
75
|
});
|
|
60
76
|
|
|
61
|
-
test("site
|
|
77
|
+
test("a single call-site tweak field overrides the winner while siblings survive", () => {
|
|
62
78
|
const llm = LLMSchema.parse({
|
|
63
|
-
default: fullDefault,
|
|
64
79
|
callSites: {
|
|
65
|
-
mainAgent: { model: "claude-sonnet-4-7" },
|
|
80
|
+
mainAgent: { ...fullTweak, model: "claude-sonnet-4-7" },
|
|
66
81
|
},
|
|
67
82
|
});
|
|
68
83
|
const resolved = resolveCallSiteConfig("mainAgent", llm);
|
|
69
84
|
expect(resolved.model).toBe("claude-sonnet-4-7");
|
|
70
|
-
// Sibling fields are preserved.
|
|
85
|
+
// Sibling tweak fields are preserved.
|
|
71
86
|
expect(resolved.provider).toBe("anthropic");
|
|
72
87
|
expect(resolved.maxTokens).toBe(64000);
|
|
73
88
|
});
|
|
74
89
|
|
|
75
90
|
test("model-only call-site override infers provider from known model owner", () => {
|
|
91
|
+
// The winner resolves through the openai default provider; the tweak's
|
|
92
|
+
// model belongs to anthropic's catalog, so the catalog owner is implied.
|
|
76
93
|
const llm = LLMSchema.parse({
|
|
77
|
-
|
|
78
|
-
...fullDefault,
|
|
79
|
-
provider: "openai",
|
|
80
|
-
model: "gpt-5.5",
|
|
81
|
-
},
|
|
82
|
-
profiles: {
|
|
83
|
-
active: { provider: "openai", model: "gpt-5.5" },
|
|
84
|
-
},
|
|
85
|
-
activeProfile: "active",
|
|
94
|
+
defaultProvider: { provider: "openai" },
|
|
86
95
|
callSites: {
|
|
87
96
|
conversationStarters: {
|
|
88
97
|
model: "claude-haiku-4-5-20251001",
|
|
@@ -98,18 +107,19 @@ describe("resolveCallSiteConfig", () => {
|
|
|
98
107
|
expect(resolved.effort).toBe("low");
|
|
99
108
|
});
|
|
100
109
|
|
|
101
|
-
test("model-only override of a shared gateway model keeps a vercel-ai-gateway
|
|
110
|
+
test("model-only override of a shared gateway model keeps a vercel-ai-gateway winner", () => {
|
|
102
111
|
// `anthropic/claude-opus-4.8` is listed by both openrouter and
|
|
103
|
-
// vercel-ai-gateway; the
|
|
104
|
-
//
|
|
112
|
+
// vercel-ai-gateway; the winner's provider serves it, so no provider is
|
|
113
|
+
// implied and the winner's provider stands.
|
|
105
114
|
const llm = LLMSchema.parse({
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
115
|
+
profiles: {
|
|
116
|
+
gw: {
|
|
117
|
+
provider: "vercel-ai-gateway",
|
|
118
|
+
model: "anthropic/claude-sonnet-4.6",
|
|
119
|
+
},
|
|
110
120
|
},
|
|
111
121
|
callSites: {
|
|
112
|
-
memoryExtraction: { model: "anthropic/claude-opus-4.8" },
|
|
122
|
+
memoryExtraction: { profile: "gw", model: "anthropic/claude-opus-4.8" },
|
|
113
123
|
},
|
|
114
124
|
});
|
|
115
125
|
|
|
@@ -119,15 +129,13 @@ describe("resolveCallSiteConfig", () => {
|
|
|
119
129
|
expect(resolved.model).toBe("anthropic/claude-opus-4.8");
|
|
120
130
|
});
|
|
121
131
|
|
|
122
|
-
test("model-only override of a shared gateway model keeps an openrouter
|
|
132
|
+
test("model-only override of a shared gateway model keeps an openrouter winner", () => {
|
|
123
133
|
const llm = LLMSchema.parse({
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
provider: "openrouter",
|
|
127
|
-
model: "anthropic/claude-sonnet-4.6",
|
|
134
|
+
profiles: {
|
|
135
|
+
gw: { provider: "openrouter", model: "anthropic/claude-sonnet-4.6" },
|
|
128
136
|
},
|
|
129
137
|
callSites: {
|
|
130
|
-
memoryExtraction: { model: "anthropic/claude-opus-4.8" },
|
|
138
|
+
memoryExtraction: { profile: "gw", model: "anthropic/claude-opus-4.8" },
|
|
131
139
|
},
|
|
132
140
|
});
|
|
133
141
|
|
|
@@ -137,12 +145,12 @@ describe("resolveCallSiteConfig", () => {
|
|
|
137
145
|
expect(resolved.model).toBe("anthropic/claude-opus-4.8");
|
|
138
146
|
});
|
|
139
147
|
|
|
140
|
-
test("model-only override of a gateway model with a non-serving
|
|
148
|
+
test("model-only override of a gateway model with a non-serving winner implies the catalog owner", () => {
|
|
141
149
|
// Anthropic's own catalog uses bare slugs, so it does not serve
|
|
142
150
|
// `anthropic/claude-sonnet-4.6` — the catalog owner (openrouter, the
|
|
143
151
|
// earliest entry listing it) is implied.
|
|
144
152
|
const llm = LLMSchema.parse({
|
|
145
|
-
|
|
153
|
+
defaultProvider: { provider: "anthropic" },
|
|
146
154
|
callSites: {
|
|
147
155
|
memoryExtraction: { model: "anthropic/claude-sonnet-4.6" },
|
|
148
156
|
},
|
|
@@ -156,7 +164,7 @@ describe("resolveCallSiteConfig", () => {
|
|
|
156
164
|
|
|
157
165
|
test("model unique to vercel-ai-gateway implies vercel-ai-gateway", () => {
|
|
158
166
|
const llm = LLMSchema.parse({
|
|
159
|
-
|
|
167
|
+
defaultProvider: { provider: "anthropic" },
|
|
160
168
|
callSites: {
|
|
161
169
|
memoryExtraction: { model: "openai/gpt-5.5-pro" },
|
|
162
170
|
},
|
|
@@ -168,13 +176,9 @@ describe("resolveCallSiteConfig", () => {
|
|
|
168
176
|
expect(resolved.model).toBe("openai/gpt-5.5-pro");
|
|
169
177
|
});
|
|
170
178
|
|
|
171
|
-
test("unknown model-only override preserves
|
|
179
|
+
test("unknown model-only override preserves the winner's provider", () => {
|
|
172
180
|
const llm = LLMSchema.parse({
|
|
173
|
-
|
|
174
|
-
...fullDefault,
|
|
175
|
-
provider: "openai",
|
|
176
|
-
model: "gpt-5.5",
|
|
177
|
-
},
|
|
181
|
+
defaultProvider: { provider: "openai" },
|
|
178
182
|
callSites: {
|
|
179
183
|
memoryExtraction: { model: "local-custom-model" },
|
|
180
184
|
},
|
|
@@ -186,11 +190,15 @@ describe("resolveCallSiteConfig", () => {
|
|
|
186
190
|
expect(resolved.model).toBe("local-custom-model");
|
|
187
191
|
});
|
|
188
192
|
|
|
189
|
-
test("profile
|
|
193
|
+
test("a call-site profile supplies the config; untouched fields fall to schema defaults", () => {
|
|
190
194
|
const llm = LLMSchema.parse({
|
|
191
|
-
default: fullDefault,
|
|
192
195
|
profiles: {
|
|
193
|
-
fast: {
|
|
196
|
+
fast: {
|
|
197
|
+
provider: "anthropic",
|
|
198
|
+
model: "claude-opus-4-7",
|
|
199
|
+
speed: "fast",
|
|
200
|
+
effort: "low",
|
|
201
|
+
},
|
|
194
202
|
},
|
|
195
203
|
callSites: {
|
|
196
204
|
memoryExtraction: { profile: "fast" },
|
|
@@ -199,16 +207,22 @@ describe("resolveCallSiteConfig", () => {
|
|
|
199
207
|
const resolved = resolveCallSiteConfig("memoryExtraction", llm);
|
|
200
208
|
expect(resolved.speed).toBe("fast");
|
|
201
209
|
expect(resolved.effort).toBe("low");
|
|
202
|
-
// Untouched defaults persist.
|
|
203
210
|
expect(resolved.provider).toBe("anthropic");
|
|
204
211
|
expect(resolved.model).toBe("claude-opus-4-7");
|
|
212
|
+
// Fields nobody set fall to the code-owned schema defaults.
|
|
213
|
+
expect(resolved.maxTokens).toBe(64000);
|
|
214
|
+
expect(resolved.verbosity).toBe("medium");
|
|
205
215
|
});
|
|
206
216
|
|
|
207
|
-
test("site field beats
|
|
217
|
+
test("site field beats the winning profile (precedence test)", () => {
|
|
208
218
|
const llm = LLMSchema.parse({
|
|
209
|
-
default: fullDefault,
|
|
210
219
|
profiles: {
|
|
211
|
-
fast: {
|
|
220
|
+
fast: {
|
|
221
|
+
provider: "anthropic",
|
|
222
|
+
model: "profile-model",
|
|
223
|
+
speed: "fast",
|
|
224
|
+
effort: "low",
|
|
225
|
+
},
|
|
212
226
|
},
|
|
213
227
|
callSites: {
|
|
214
228
|
memoryExtraction: {
|
|
@@ -222,15 +236,13 @@ describe("resolveCallSiteConfig", () => {
|
|
|
222
236
|
// Site-level wins where it sets a value.
|
|
223
237
|
expect(resolved.model).toBe("site-model");
|
|
224
238
|
expect(resolved.effort).toBe("high");
|
|
225
|
-
//
|
|
239
|
+
// The winning profile wins where the site is silent.
|
|
226
240
|
expect(resolved.speed).toBe("fast");
|
|
227
|
-
// Default wins where neither overrides.
|
|
228
241
|
expect(resolved.provider).toBe("anthropic");
|
|
229
242
|
});
|
|
230
243
|
|
|
231
244
|
test("thinking.enabled override does not nuke thinking.streamThinking (deep merge)", () => {
|
|
232
245
|
const llm = LLMSchema.parse({
|
|
233
|
-
default: fullDefault,
|
|
234
246
|
callSites: {
|
|
235
247
|
mainAgent: { thinking: { enabled: false } },
|
|
236
248
|
},
|
|
@@ -242,7 +254,6 @@ describe("resolveCallSiteConfig", () => {
|
|
|
242
254
|
|
|
243
255
|
test("contextWindow.overflowRecovery.maxAttempts override preserves siblings (depth 2 deep merge)", () => {
|
|
244
256
|
const llm = LLMSchema.parse({
|
|
245
|
-
default: fullDefault,
|
|
246
257
|
callSites: {
|
|
247
258
|
mainAgent: {
|
|
248
259
|
contextWindow: {
|
|
@@ -254,7 +265,7 @@ describe("resolveCallSiteConfig", () => {
|
|
|
254
265
|
const resolved = resolveCallSiteConfig("mainAgent", llm);
|
|
255
266
|
// Overridden leaf at depth 2.
|
|
256
267
|
expect(resolved.contextWindow.overflowRecovery.maxAttempts).toBe(7);
|
|
257
|
-
// Sibling leaves of overflowRecovery survive.
|
|
268
|
+
// Sibling leaves of overflowRecovery survive from the schema-default base.
|
|
258
269
|
expect(resolved.contextWindow.overflowRecovery.enabled).toBe(true);
|
|
259
270
|
expect(resolved.contextWindow.overflowRecovery.safetyMarginRatio).toBe(
|
|
260
271
|
0.05,
|
|
@@ -272,9 +283,9 @@ describe("resolveCallSiteConfig", () => {
|
|
|
272
283
|
expect(resolved.contextWindow.targetBudgetRatio).toBe(0.3);
|
|
273
284
|
});
|
|
274
285
|
|
|
275
|
-
test("
|
|
286
|
+
test("a defined-but-unreferenced profile never leaks into the resolved config", () => {
|
|
276
287
|
const llm = LLMSchema.parse({
|
|
277
|
-
|
|
288
|
+
defaultProvider: { provider: "anthropic" },
|
|
278
289
|
profiles: {
|
|
279
290
|
// Defined but unused — must not leak into the resolved config.
|
|
280
291
|
fast: { speed: "fast", effort: "low" },
|
|
@@ -285,22 +296,22 @@ describe("resolveCallSiteConfig", () => {
|
|
|
285
296
|
});
|
|
286
297
|
const resolved = resolveCallSiteConfig("mainAgent", llm);
|
|
287
298
|
expect(resolved.temperature).toBe(0.5);
|
|
288
|
-
//
|
|
299
|
+
// The unused profile's fields must not appear: `speed` falls to the base
|
|
300
|
+
// and `effort` comes from the winning balanced-intent profile.
|
|
289
301
|
expect(resolved.speed).toBe("standard");
|
|
290
|
-
expect(resolved.effort).toBe("
|
|
302
|
+
expect(resolved.effort).toBe("high");
|
|
291
303
|
});
|
|
292
304
|
|
|
293
305
|
test("topP defaults to null when no profile or override sets it", () => {
|
|
294
|
-
const llm = LLMSchema.parse({
|
|
306
|
+
const llm = LLMSchema.parse({});
|
|
295
307
|
const resolved = resolveCallSiteConfig("mainAgent", llm);
|
|
296
308
|
expect(resolved.topP).toBeNull();
|
|
297
309
|
});
|
|
298
310
|
|
|
299
|
-
test("profile
|
|
311
|
+
test("winning-profile topP resolves onto the merged config", () => {
|
|
300
312
|
const llm = LLMSchema.parse({
|
|
301
|
-
default: fullDefault,
|
|
302
313
|
profiles: {
|
|
303
|
-
nucleus: { topP: 0.9 },
|
|
314
|
+
nucleus: { provider: "anthropic", model: "claude-opus-4-7", topP: 0.9 },
|
|
304
315
|
},
|
|
305
316
|
callSites: {
|
|
306
317
|
memoryExtraction: { profile: "nucleus" },
|
|
@@ -310,30 +321,42 @@ describe("resolveCallSiteConfig", () => {
|
|
|
310
321
|
expect(resolved.topP).toBe(0.9);
|
|
311
322
|
});
|
|
312
323
|
|
|
313
|
-
test("returns isolated nested objects (not aliased to
|
|
314
|
-
// Resolve a call site
|
|
315
|
-
// `contextWindow`
|
|
316
|
-
// nested objects aliased
|
|
317
|
-
// mutate the returned config's nested objects, then
|
|
318
|
-
// verify the second call sees the original
|
|
319
|
-
// (i.e. the source was never corrupted).
|
|
320
|
-
const llm = LLMSchema.parse({
|
|
324
|
+
test("returns isolated nested objects (not aliased to the winning profile)", () => {
|
|
325
|
+
// Resolve a call site whose winner supplies nested `thinking` and
|
|
326
|
+
// `contextWindow` fragments. The bug being guarded against would have
|
|
327
|
+
// those nested objects aliased to the profile entry in `llm.profiles`.
|
|
328
|
+
// We resolve once, mutate the returned config's nested objects, then
|
|
329
|
+
// resolve again and verify the second call sees the original values
|
|
330
|
+
// (i.e. the source config was never corrupted).
|
|
331
|
+
const llm = LLMSchema.parse({
|
|
332
|
+
profiles: {
|
|
333
|
+
mine: {
|
|
334
|
+
provider: "anthropic",
|
|
335
|
+
model: "claude-opus-4-7",
|
|
336
|
+
thinking: { enabled: true, streamThinking: true },
|
|
337
|
+
contextWindow: { overflowRecovery: { maxAttempts: 3 } },
|
|
338
|
+
},
|
|
339
|
+
},
|
|
340
|
+
activeProfile: "mine",
|
|
341
|
+
});
|
|
321
342
|
|
|
322
343
|
const first = resolveCallSiteConfig("mainAgent", llm);
|
|
323
344
|
expect(first.thinking.enabled).toBe(true);
|
|
324
345
|
expect(first.contextWindow.overflowRecovery.maxAttempts).toBe(3);
|
|
325
346
|
|
|
326
|
-
// Mutate the result. If nested objects were aliased into
|
|
347
|
+
// Mutate the result. If nested objects were aliased into the profile,
|
|
327
348
|
// these writes would silently corrupt the source config.
|
|
328
349
|
first.thinking.enabled = false;
|
|
329
350
|
first.contextWindow.overflowRecovery.maxAttempts = 999;
|
|
330
351
|
|
|
331
|
-
// Defensive: the source
|
|
332
|
-
expect(
|
|
333
|
-
expect(
|
|
352
|
+
// Defensive: the source profile entry should be untouched.
|
|
353
|
+
expect(llm.profiles["mine"]?.thinking?.enabled).toBe(true);
|
|
354
|
+
expect(
|
|
355
|
+
llm.profiles["mine"]?.contextWindow?.overflowRecovery?.maxAttempts,
|
|
356
|
+
).toBe(3);
|
|
334
357
|
|
|
335
358
|
// The real test: resolving the same call site again must see the
|
|
336
|
-
// original
|
|
359
|
+
// original profile values, not the mutations applied to `first`.
|
|
337
360
|
const second = resolveCallSiteConfig("mainAgent", llm);
|
|
338
361
|
expect(second.thinking.enabled).toBe(true);
|
|
339
362
|
expect(second.contextWindow.overflowRecovery.maxAttempts).toBe(3);
|
|
@@ -349,13 +372,13 @@ describe("resolveCallSiteConfig", () => {
|
|
|
349
372
|
);
|
|
350
373
|
});
|
|
351
374
|
|
|
352
|
-
test("
|
|
375
|
+
test("an unknown call-site profile reference falls through with a report (bypassing superRefine)", () => {
|
|
353
376
|
// Hand-craft an `LLMSchema`-typed object that bypasses validation by
|
|
354
377
|
// referencing a profile that doesn't exist in `profiles`. The schema's
|
|
355
378
|
// `superRefine` would reject this at parse time, so we construct it
|
|
356
|
-
// manually to exercise the
|
|
379
|
+
// manually to exercise the resolver's silent fall-through: the missing
|
|
380
|
+
// rung is reported and resolution lands on the code-owned anchor.
|
|
357
381
|
const llm: z.infer<typeof LLMSchema> = {
|
|
358
|
-
default: fullDefault,
|
|
359
382
|
profiles: {},
|
|
360
383
|
profileOrder: [],
|
|
361
384
|
callSites: {
|
|
@@ -364,73 +387,53 @@ describe("resolveCallSiteConfig", () => {
|
|
|
364
387
|
profileSession: { defaultTtlSeconds: 1800, maxTtlSeconds: 43200 },
|
|
365
388
|
pricingOverrides: [],
|
|
366
389
|
};
|
|
367
|
-
|
|
368
|
-
|
|
390
|
+
const { fallbacks, opts } = collect();
|
|
391
|
+
const resolved = resolveCallSiteConfig("mainAgent", llm, opts);
|
|
392
|
+
expect(resolved.model).toBe(
|
|
393
|
+
CODE_DEFAULT_PROFILE_ENTRIES.balanced.model as string,
|
|
369
394
|
);
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
// can verify each layer's contribution and that higher layers win.
|
|
375
|
-
//
|
|
376
|
-
// Layer order (low → high):
|
|
377
|
-
// 1. default → model=claude-opus-4-7, effort=max
|
|
378
|
-
// 2. activeProfile → effort=medium (everything else falls through)
|
|
379
|
-
// 3. overrideProfile → effort=low, speed=fast
|
|
380
|
-
// 4. callSite.profile → effort=high, verbosity=high
|
|
381
|
-
// 5. callSite frag → effort=none (top dog)
|
|
382
|
-
const llm = LLMSchema.parse({
|
|
383
|
-
default: fullDefault,
|
|
384
|
-
profiles: {
|
|
385
|
-
active: { effort: "medium" },
|
|
386
|
-
override: { effort: "low", speed: "fast" },
|
|
387
|
-
siteProfile: { effort: "high", verbosity: "high" },
|
|
388
|
-
},
|
|
389
|
-
callSites: {
|
|
390
|
-
memoryExtraction: { profile: "siteProfile", effort: "none" },
|
|
391
|
-
},
|
|
392
|
-
activeProfile: "active",
|
|
393
|
-
});
|
|
394
|
-
|
|
395
|
-
const resolved = resolveCallSiteConfig("memoryExtraction", llm, {
|
|
396
|
-
overrideProfile: "override",
|
|
395
|
+
expect(fallbacks).toContainEqual({
|
|
396
|
+
callSite: "mainAgent",
|
|
397
|
+
requested: "nonexistent",
|
|
398
|
+
reason: "missing",
|
|
397
399
|
});
|
|
398
|
-
|
|
399
|
-
// Top layer (callSite fragment) wins for `effort` over every other
|
|
400
|
-
// layer's contribution (max → medium → low → high → none).
|
|
401
|
-
expect(resolved.effort).toBe("none");
|
|
402
|
-
// siteProfile contributes verbosity (no higher layer touches it).
|
|
403
|
-
expect(resolved.verbosity).toBe("high");
|
|
404
|
-
// overrideProfile contributes speed (no higher layer touches it).
|
|
405
|
-
expect(resolved.speed).toBe("fast");
|
|
406
|
-
// default wins for everything no higher layer touches.
|
|
407
|
-
expect(resolved.provider).toBe("anthropic");
|
|
408
|
-
expect(resolved.model).toBe("claude-opus-4-7");
|
|
409
|
-
expect(resolved.maxTokens).toBe(64000);
|
|
410
400
|
});
|
|
411
401
|
|
|
412
|
-
test("activeProfile applies when set with no overrideProfile and no callsite", () => {
|
|
402
|
+
test("activeProfile applies for mainAgent when set with no overrideProfile and no callsite", () => {
|
|
413
403
|
const llm = LLMSchema.parse({
|
|
414
|
-
default: fullDefault,
|
|
415
404
|
profiles: {
|
|
416
|
-
|
|
405
|
+
mine: {
|
|
406
|
+
provider: "anthropic",
|
|
407
|
+
model: "claude-sonnet-4-7",
|
|
408
|
+
effort: "medium",
|
|
409
|
+
verbosity: "low",
|
|
410
|
+
},
|
|
417
411
|
},
|
|
418
|
-
activeProfile: "
|
|
412
|
+
activeProfile: "mine",
|
|
419
413
|
});
|
|
420
414
|
const resolved = resolveCallSiteConfig("mainAgent", llm);
|
|
421
415
|
expect(resolved.effort).toBe("medium");
|
|
422
416
|
expect(resolved.verbosity).toBe("low");
|
|
423
|
-
|
|
424
|
-
|
|
417
|
+
expect(resolved.model).toBe("claude-sonnet-4-7");
|
|
418
|
+
// The base still shines through where the winner is silent.
|
|
425
419
|
expect(resolved.speed).toBe("standard");
|
|
426
420
|
});
|
|
427
421
|
|
|
428
|
-
test("
|
|
422
|
+
test("call-site tweak fields apply over the override winner; shadowed profiles contribute nothing", () => {
|
|
429
423
|
const llm = LLMSchema.parse({
|
|
430
|
-
default: fullDefault,
|
|
431
424
|
profiles: {
|
|
432
|
-
active: {
|
|
433
|
-
|
|
425
|
+
active: {
|
|
426
|
+
provider: "anthropic",
|
|
427
|
+
model: "active-model",
|
|
428
|
+
effort: "low",
|
|
429
|
+
verbosity: "low",
|
|
430
|
+
},
|
|
431
|
+
override: {
|
|
432
|
+
provider: "anthropic",
|
|
433
|
+
model: "override-model",
|
|
434
|
+
effort: "high",
|
|
435
|
+
speed: "fast",
|
|
436
|
+
},
|
|
434
437
|
},
|
|
435
438
|
callSites: {
|
|
436
439
|
memoryExtraction: { effort: "none" },
|
|
@@ -440,68 +443,50 @@ describe("resolveCallSiteConfig", () => {
|
|
|
440
443
|
const resolved = resolveCallSiteConfig("memoryExtraction", llm, {
|
|
441
444
|
overrideProfile: "override",
|
|
442
445
|
});
|
|
443
|
-
//
|
|
446
|
+
// The call-site tweak is the last composition layer.
|
|
444
447
|
expect(resolved.effort).toBe("none");
|
|
445
|
-
//
|
|
448
|
+
// The override profile is the single winner.
|
|
449
|
+
expect(resolved.model).toBe("override-model");
|
|
446
450
|
expect(resolved.speed).toBe("fast");
|
|
447
|
-
//
|
|
448
|
-
|
|
451
|
+
// The active profile is not the winner, so its fields never contribute —
|
|
452
|
+
// verbosity falls to the schema default.
|
|
453
|
+
expect(resolved.verbosity).toBe("medium");
|
|
449
454
|
});
|
|
450
455
|
|
|
451
|
-
test("
|
|
456
|
+
test("call-site tweak fields apply on top of the override winner regardless of forceOverrideProfile", () => {
|
|
452
457
|
const llm = LLMSchema.parse({
|
|
453
|
-
default: fullDefault,
|
|
454
458
|
profiles: {
|
|
455
|
-
active: { verbosity: "low" },
|
|
456
|
-
sitep: { effort: "none", speed: "fast" },
|
|
457
459
|
forced: {
|
|
458
|
-
|
|
460
|
+
provider: "anthropic",
|
|
461
|
+
model: "claude-opus-4-7",
|
|
459
462
|
effort: "high",
|
|
460
|
-
thinking: { enabled: false },
|
|
461
463
|
},
|
|
462
464
|
},
|
|
463
465
|
callSites: {
|
|
464
|
-
memoryExtraction: {
|
|
466
|
+
memoryExtraction: { effort: "none" },
|
|
465
467
|
},
|
|
466
|
-
activeProfile: "active",
|
|
467
468
|
});
|
|
468
|
-
const
|
|
469
|
+
const plain = resolveCallSiteConfig("memoryExtraction", llm, {
|
|
469
470
|
overrideProfile: "forced",
|
|
470
|
-
forceOverrideProfile: true,
|
|
471
471
|
});
|
|
472
|
-
|
|
473
|
-
// override fields it touches.
|
|
474
|
-
expect(resolved.model).toBe("claude-haiku-4-5");
|
|
475
|
-
expect(resolved.effort).toBe("high");
|
|
476
|
-
expect(resolved.thinking.enabled).toBe(false);
|
|
477
|
-
// Call-site layers still win where the forced profile is silent.
|
|
478
|
-
expect(resolved.maxTokens).toBe(1000);
|
|
479
|
-
expect(resolved.speed).toBe("fast");
|
|
480
|
-
// Active profile still applies under everything.
|
|
481
|
-
expect(resolved.verbosity).toBe("low");
|
|
482
|
-
});
|
|
483
|
-
|
|
484
|
-
test("forceOverrideProfile absent leaves the override below callsite fields (unchanged precedence)", () => {
|
|
485
|
-
const llm = LLMSchema.parse({
|
|
486
|
-
default: fullDefault,
|
|
487
|
-
profiles: {
|
|
488
|
-
forced: { effort: "high" },
|
|
489
|
-
},
|
|
490
|
-
callSites: {
|
|
491
|
-
memoryExtraction: { effort: "none" },
|
|
492
|
-
},
|
|
493
|
-
});
|
|
494
|
-
const resolved = resolveCallSiteConfig("memoryExtraction", llm, {
|
|
472
|
+
const forced = resolveCallSiteConfig("memoryExtraction", llm, {
|
|
495
473
|
overrideProfile: "forced",
|
|
474
|
+
forceOverrideProfile: true,
|
|
496
475
|
});
|
|
497
|
-
|
|
476
|
+
// The tweak is the last layer in both cases; force is a no-op.
|
|
477
|
+
expect(plain.effort).toBe("none");
|
|
478
|
+
expect(plain.model).toBe("claude-opus-4-7");
|
|
479
|
+
expect(forced).toEqual(plain);
|
|
498
480
|
});
|
|
499
481
|
|
|
500
|
-
test("forceOverrideProfile with a missing profile reference falls through to
|
|
482
|
+
test("forceOverrideProfile with a missing profile reference falls through to the call-site profile", () => {
|
|
501
483
|
const llm = LLMSchema.parse({
|
|
502
|
-
default: fullDefault,
|
|
503
484
|
profiles: {
|
|
504
|
-
sitep: {
|
|
485
|
+
sitep: {
|
|
486
|
+
provider: "anthropic",
|
|
487
|
+
effort: "low",
|
|
488
|
+
model: "claude-haiku-4-5",
|
|
489
|
+
},
|
|
505
490
|
},
|
|
506
491
|
callSites: {
|
|
507
492
|
memoryExtraction: { profile: "sitep" },
|
|
@@ -511,20 +496,24 @@ describe("resolveCallSiteConfig", () => {
|
|
|
511
496
|
overrideProfile: "nonexistent",
|
|
512
497
|
forceOverrideProfile: true,
|
|
513
498
|
});
|
|
514
|
-
// The missing reference is inert: site profile still wins.
|
|
499
|
+
// The missing reference is inert: the site profile still wins.
|
|
515
500
|
expect(resolved.effort).toBe("low");
|
|
516
501
|
expect(resolved.model).toBe("claude-haiku-4-5");
|
|
517
502
|
});
|
|
518
503
|
|
|
519
504
|
test("forceOverrideProfile is a no-op for mainAgent (override already resolves on top)", () => {
|
|
520
505
|
const llm = LLMSchema.parse({
|
|
521
|
-
default: fullDefault,
|
|
522
506
|
profiles: {
|
|
523
|
-
active: {
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
507
|
+
active: {
|
|
508
|
+
provider: "anthropic",
|
|
509
|
+
model: "claude-sonnet-4-7",
|
|
510
|
+
effort: "low",
|
|
511
|
+
},
|
|
512
|
+
override: {
|
|
513
|
+
provider: "anthropic",
|
|
514
|
+
model: "claude-opus-4-7",
|
|
515
|
+
effort: "high",
|
|
516
|
+
},
|
|
528
517
|
},
|
|
529
518
|
activeProfile: "active",
|
|
530
519
|
});
|
|
@@ -539,13 +528,16 @@ describe("resolveCallSiteConfig", () => {
|
|
|
539
528
|
expect(withForce.effort).toBe("high");
|
|
540
529
|
});
|
|
541
530
|
|
|
542
|
-
test("overrideProfile absent leaves
|
|
543
|
-
// No `opts` argument at all — the
|
|
544
|
-
// before this PR for configs without activeProfile/overrideProfile.
|
|
531
|
+
test("overrideProfile absent leaves the call-site profile as the winner", () => {
|
|
532
|
+
// No `opts` argument at all — the call-site profile wins the chain.
|
|
545
533
|
const llm = LLMSchema.parse({
|
|
546
|
-
default: fullDefault,
|
|
547
534
|
profiles: {
|
|
548
|
-
fast: {
|
|
535
|
+
fast: {
|
|
536
|
+
provider: "anthropic",
|
|
537
|
+
model: "claude-opus-4-7",
|
|
538
|
+
speed: "fast",
|
|
539
|
+
effort: "low",
|
|
540
|
+
},
|
|
549
541
|
},
|
|
550
542
|
callSites: {
|
|
551
543
|
memoryExtraction: { profile: "fast" },
|
|
@@ -558,33 +550,13 @@ describe("resolveCallSiteConfig", () => {
|
|
|
558
550
|
expect(resolved.model).toBe("claude-opus-4-7");
|
|
559
551
|
});
|
|
560
552
|
|
|
561
|
-
test("overrideProfile referencing a missing key falls through silently", () => {
|
|
562
|
-
const llm = LLMSchema.parse({
|
|
563
|
-
default: fullDefault,
|
|
564
|
-
profiles: {
|
|
565
|
-
balanced: { effort: "medium" },
|
|
566
|
-
},
|
|
567
|
-
});
|
|
568
|
-
// The schema's superRefine doesn't validate `overrideProfile` (it's a
|
|
569
|
-
// runtime parameter), so a missing key must silently fall through.
|
|
570
|
-
const resolved = resolveCallSiteConfig("mainAgent", llm, {
|
|
571
|
-
overrideProfile: "nonexistent",
|
|
572
|
-
});
|
|
573
|
-
// overrideProfile is set so the shipped default's profile is stripped.
|
|
574
|
-
// The nonexistent overrideProfile also adds nothing. Falls through to default.
|
|
575
|
-
expect(resolved.effort).toBe("max");
|
|
576
|
-
expect(resolved.model).toBe("claude-opus-4-7");
|
|
577
|
-
});
|
|
578
|
-
|
|
579
553
|
test("activeProfile referencing a missing key falls through silently", () => {
|
|
580
554
|
// Hand-craft an `LLMSchema`-typed object that bypasses superRefine —
|
|
581
555
|
// schema validation rejects an unknown `activeProfile` at parse, but the
|
|
582
|
-
// resolver itself must not throw (parity with `overrideProfile`)
|
|
556
|
+
// resolver itself must not throw (parity with `overrideProfile`): the
|
|
557
|
+
// missing rung is skipped and resolution lands on the balanced anchor.
|
|
583
558
|
const llm: z.infer<typeof LLMSchema> = {
|
|
584
|
-
|
|
585
|
-
// Disable the catalog default so the missing activeProfile's silent
|
|
586
|
-
// fall-through lands on `llm.default` rather than catalog `balanced`.
|
|
587
|
-
profiles: { balanced: { source: "managed", status: "disabled" } },
|
|
559
|
+
profiles: {},
|
|
588
560
|
profileOrder: [],
|
|
589
561
|
callSites: {},
|
|
590
562
|
activeProfile: "nonexistent",
|
|
@@ -592,113 +564,22 @@ describe("resolveCallSiteConfig", () => {
|
|
|
592
564
|
pricingOverrides: [],
|
|
593
565
|
};
|
|
594
566
|
const resolved = resolveCallSiteConfig("mainAgent", llm);
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
});
|
|
599
|
-
|
|
600
|
-
test("thinking and contextWindow deep-merge across the contributing layers for non-main call sites", () => {
|
|
601
|
-
// Each layer touches a different leaf inside `thinking` and
|
|
602
|
-
// `contextWindow.overflowRecovery` so we can verify deep merge composes
|
|
603
|
-
// every contribution rather than wholesale-replacing the nested objects.
|
|
604
|
-
// The call site pins `siteProfile`, so the active profile is excluded — its
|
|
605
|
-
// leaves fall through to default while override, site profile, and the
|
|
606
|
-
// call-site fragment still compose.
|
|
607
|
-
const llm = LLMSchema.parse({
|
|
608
|
-
default: fullDefault,
|
|
609
|
-
profiles: {
|
|
610
|
-
active: {
|
|
611
|
-
thinking: { enabled: false },
|
|
612
|
-
contextWindow: { overflowRecovery: { maxAttempts: 7 } },
|
|
613
|
-
},
|
|
614
|
-
override: {
|
|
615
|
-
thinking: { streamThinking: false },
|
|
616
|
-
contextWindow: { overflowRecovery: { safetyMarginRatio: 0.1 } },
|
|
617
|
-
},
|
|
618
|
-
siteProfile: {
|
|
619
|
-
contextWindow: { targetBudgetRatio: 0.5 },
|
|
620
|
-
},
|
|
621
|
-
},
|
|
622
|
-
callSites: {
|
|
623
|
-
memoryExtraction: {
|
|
624
|
-
profile: "siteProfile",
|
|
625
|
-
contextWindow: { compactThreshold: 0.9 },
|
|
626
|
-
},
|
|
627
|
-
},
|
|
628
|
-
activeProfile: "active",
|
|
629
|
-
});
|
|
630
|
-
const resolved = resolveCallSiteConfig("memoryExtraction", llm, {
|
|
631
|
-
overrideProfile: "override",
|
|
632
|
-
});
|
|
633
|
-
// Override, site profile, and the call-site fragment each contribute a leaf.
|
|
634
|
-
expect(resolved.thinking.streamThinking).toBe(false); // override
|
|
635
|
-
expect(resolved.contextWindow.overflowRecovery.safetyMarginRatio).toBe(0.1); // override
|
|
636
|
-
expect(resolved.contextWindow.targetBudgetRatio).toBe(0.5); // siteProfile
|
|
637
|
-
expect(resolved.contextWindow.compactThreshold).toBe(0.9); // callsite
|
|
638
|
-
// The active profile is excluded (the call site pins its own profile), so
|
|
639
|
-
// its leaves fall through to default instead of contributing.
|
|
640
|
-
expect(resolved.thinking.enabled).toBe(true); // default, NOT active's false
|
|
641
|
-
expect(resolved.contextWindow.overflowRecovery.maxAttempts).toBe(3); // default, NOT active's 7
|
|
642
|
-
// Untouched leaves at depth 2 fall through to default.
|
|
643
|
-
expect(resolved.contextWindow.overflowRecovery.enabled).toBe(true);
|
|
644
|
-
expect(
|
|
645
|
-
resolved.contextWindow.overflowRecovery.interactiveLatestTurnCompression,
|
|
646
|
-
).toBe("summarize");
|
|
647
|
-
// Untouched leaves at depth 1 fall through to default.
|
|
648
|
-
expect(resolved.contextWindow.maxInputTokens).toBe(200000);
|
|
649
|
-
expect(resolved.contextWindow.summaryBudgetRatio).toBe(0.05);
|
|
650
|
-
});
|
|
651
|
-
|
|
652
|
-
test("callSite fragment fields still win at the top for non-main call sites", () => {
|
|
653
|
-
const llm = LLMSchema.parse({
|
|
654
|
-
default: fullDefault,
|
|
655
|
-
profiles: {
|
|
656
|
-
active: { model: "active-model", effort: "low" },
|
|
657
|
-
override: { model: "override-model", speed: "fast" },
|
|
658
|
-
siteProfile: { model: "siteProfile-model", verbosity: "high" },
|
|
659
|
-
},
|
|
660
|
-
callSites: {
|
|
661
|
-
memoryExtraction: {
|
|
662
|
-
profile: "siteProfile",
|
|
663
|
-
model: "site-model",
|
|
664
|
-
maxTokens: 12345,
|
|
665
|
-
},
|
|
666
|
-
},
|
|
667
|
-
activeProfile: "active",
|
|
668
|
-
});
|
|
669
|
-
const resolved = resolveCallSiteConfig("memoryExtraction", llm, {
|
|
670
|
-
overrideProfile: "override",
|
|
671
|
-
});
|
|
672
|
-
// Site fragment wins for fields it sets.
|
|
673
|
-
expect(resolved.model).toBe("site-model");
|
|
674
|
-
expect(resolved.maxTokens).toBe(12345);
|
|
675
|
-
// Lower layers contribute fields the site fragment does not touch.
|
|
676
|
-
expect(resolved.verbosity).toBe("high"); // from siteProfile
|
|
677
|
-
expect(resolved.speed).toBe("fast"); // from override
|
|
678
|
-
// The active profile is excluded when the call site pins its own profile,
|
|
679
|
-
// so `effort` falls through to default rather than active's "low".
|
|
680
|
-
expect(resolved.effort).toBe("max"); // default, NOT active's "low"
|
|
567
|
+
expect(resolved.model).toBe(
|
|
568
|
+
CODE_DEFAULT_PROFILE_ENTRIES.balanced.model as string,
|
|
569
|
+
);
|
|
681
570
|
});
|
|
682
571
|
|
|
683
|
-
test("mainAgent activeProfile
|
|
572
|
+
test("mainAgent activeProfile determines identity when no explicit call-site tweak exists", () => {
|
|
684
573
|
const llm = LLMSchema.parse({
|
|
685
|
-
default: fullDefault,
|
|
686
574
|
profiles: {
|
|
687
575
|
balanced: {
|
|
576
|
+
source: "user",
|
|
688
577
|
provider: "openai",
|
|
689
578
|
model: "gpt-5.4",
|
|
690
579
|
maxTokens: 16000,
|
|
691
580
|
contextWindow: { maxInputTokens: 400000 },
|
|
692
581
|
},
|
|
693
582
|
},
|
|
694
|
-
callSites: {
|
|
695
|
-
mainAgent: {
|
|
696
|
-
provider: "anthropic",
|
|
697
|
-
model: "claude-opus-4-7",
|
|
698
|
-
maxTokens: 32000,
|
|
699
|
-
contextWindow: { maxInputTokens: 200000 },
|
|
700
|
-
},
|
|
701
|
-
},
|
|
702
583
|
activeProfile: "balanced",
|
|
703
584
|
});
|
|
704
585
|
|
|
@@ -710,9 +591,8 @@ describe("resolveCallSiteConfig", () => {
|
|
|
710
591
|
expect(resolved.contextWindow.maxInputTokens).toBe(400000);
|
|
711
592
|
});
|
|
712
593
|
|
|
713
|
-
test("mainAgent overrideProfile beats activeProfile
|
|
594
|
+
test("mainAgent overrideProfile beats activeProfile", () => {
|
|
714
595
|
const llm = LLMSchema.parse({
|
|
715
|
-
default: fullDefault,
|
|
716
596
|
profiles: {
|
|
717
597
|
active: {
|
|
718
598
|
provider: "openai",
|
|
@@ -727,14 +607,6 @@ describe("resolveCallSiteConfig", () => {
|
|
|
727
607
|
contextWindow: { maxInputTokens: 1048576 },
|
|
728
608
|
},
|
|
729
609
|
},
|
|
730
|
-
callSites: {
|
|
731
|
-
mainAgent: {
|
|
732
|
-
provider: "anthropic",
|
|
733
|
-
model: "claude-opus-4-7",
|
|
734
|
-
maxTokens: 32000,
|
|
735
|
-
contextWindow: { maxInputTokens: 200000 },
|
|
736
|
-
},
|
|
737
|
-
},
|
|
738
610
|
activeProfile: "active",
|
|
739
611
|
});
|
|
740
612
|
|
|
@@ -750,9 +622,10 @@ describe("resolveCallSiteConfig", () => {
|
|
|
750
622
|
|
|
751
623
|
test("call site with no explicit config falls back to CALL_SITE_DEFAULTS", () => {
|
|
752
624
|
const llm = LLMSchema.parse({
|
|
753
|
-
default: fullDefault,
|
|
754
625
|
profiles: {
|
|
755
626
|
"cost-optimized": {
|
|
627
|
+
source: "user",
|
|
628
|
+
provider: "anthropic",
|
|
756
629
|
model: "claude-haiku-4-5-20251001",
|
|
757
630
|
effort: "low",
|
|
758
631
|
},
|
|
@@ -765,13 +638,16 @@ describe("resolveCallSiteConfig", () => {
|
|
|
765
638
|
|
|
766
639
|
test("empty-state greeting defaults to the balanced profile", () => {
|
|
767
640
|
const llm = LLMSchema.parse({
|
|
768
|
-
default: fullDefault,
|
|
769
641
|
profiles: {
|
|
770
642
|
balanced: {
|
|
643
|
+
source: "user",
|
|
644
|
+
provider: "anthropic",
|
|
771
645
|
model: "claude-sonnet-4-7",
|
|
772
646
|
effort: "medium",
|
|
773
647
|
},
|
|
774
648
|
"cost-optimized": {
|
|
649
|
+
source: "user",
|
|
650
|
+
provider: "anthropic",
|
|
775
651
|
model: "claude-haiku-4-5-20251001",
|
|
776
652
|
effort: "low",
|
|
777
653
|
},
|
|
@@ -788,13 +664,19 @@ describe("resolveCallSiteConfig", () => {
|
|
|
788
664
|
|
|
789
665
|
test("explicit callSites config overrides CALL_SITE_DEFAULTS", () => {
|
|
790
666
|
const llm = LLMSchema.parse({
|
|
791
|
-
default: fullDefault,
|
|
792
667
|
profiles: {
|
|
793
668
|
"cost-optimized": {
|
|
669
|
+
source: "user",
|
|
670
|
+
provider: "anthropic",
|
|
794
671
|
model: "claude-haiku-4-5-20251001",
|
|
795
672
|
effort: "low",
|
|
796
673
|
},
|
|
797
|
-
"quality-optimized": {
|
|
674
|
+
"quality-optimized": {
|
|
675
|
+
source: "user",
|
|
676
|
+
provider: "anthropic",
|
|
677
|
+
model: "claude-opus-4-7",
|
|
678
|
+
effort: "max",
|
|
679
|
+
},
|
|
798
680
|
},
|
|
799
681
|
callSites: {
|
|
800
682
|
memoryExtraction: { profile: "quality-optimized" },
|
|
@@ -805,121 +687,36 @@ describe("resolveCallSiteConfig", () => {
|
|
|
805
687
|
expect(resolved.effort).toBe("max");
|
|
806
688
|
});
|
|
807
689
|
|
|
808
|
-
test("BYOK: disabled managed
|
|
690
|
+
test("BYOK: a disabled managed stub does not block resolution — the default-provider intent wins", () => {
|
|
809
691
|
const llm = LLMSchema.parse({
|
|
810
|
-
default: {
|
|
811
|
-
...fullDefault,
|
|
812
|
-
provider: "openai",
|
|
813
|
-
model: "gpt-5.5",
|
|
814
|
-
provider_connection: "openai-personal",
|
|
815
|
-
},
|
|
816
692
|
profiles: {
|
|
817
|
-
"cost-optimized": {
|
|
818
|
-
status: "disabled",
|
|
819
|
-
model: "claude-haiku-4-5-20251001",
|
|
820
|
-
provider: "anthropic",
|
|
821
|
-
provider_connection: "anthropic-managed",
|
|
822
|
-
},
|
|
823
|
-
"custom-cost-optimized": {
|
|
824
|
-
source: "user",
|
|
825
|
-
model: "gpt-5.4-nano",
|
|
826
|
-
provider: "openai",
|
|
827
|
-
provider_connection: "openai-personal",
|
|
828
|
-
},
|
|
829
|
-
"custom-balanced": {
|
|
830
|
-
source: "user",
|
|
831
|
-
model: "gpt-5.5",
|
|
832
|
-
provider: "openai",
|
|
833
|
-
provider_connection: "openai-personal",
|
|
834
|
-
},
|
|
835
|
-
},
|
|
836
|
-
activeProfile: "custom-balanced",
|
|
837
|
-
});
|
|
838
|
-
const resolved = resolveCallSiteConfig("memoryExtraction", llm);
|
|
839
|
-
expect(resolved.provider).toBe("openai");
|
|
840
|
-
expect(resolved.model).toBe("gpt-5.4-nano");
|
|
841
|
-
expect(resolved.provider_connection).toBe("openai-personal");
|
|
842
|
-
});
|
|
843
|
-
|
|
844
|
-
test("BYOK: strips profile when neither managed nor custom-* is available", () => {
|
|
845
|
-
const llm = LLMSchema.parse({
|
|
846
|
-
default: {
|
|
847
|
-
...fullDefault,
|
|
848
|
-
provider: "openai",
|
|
849
|
-
model: "gpt-5.5",
|
|
850
|
-
provider_connection: "openai-personal",
|
|
851
|
-
},
|
|
852
|
-
profiles: {
|
|
853
|
-
"cost-optimized": {
|
|
854
|
-
status: "disabled",
|
|
855
|
-
model: "claude-haiku-4-5-20251001",
|
|
856
|
-
provider: "anthropic",
|
|
857
|
-
provider_connection: "anthropic-managed",
|
|
858
|
-
},
|
|
859
|
-
"custom-balanced": {
|
|
860
|
-
model: "gpt-5.5",
|
|
861
|
-
provider: "openai",
|
|
862
|
-
provider_connection: "openai-personal",
|
|
863
|
-
},
|
|
693
|
+
"cost-optimized": { source: "managed", status: "disabled" },
|
|
864
694
|
},
|
|
865
|
-
|
|
695
|
+
defaultProvider: { provider: "openai" },
|
|
866
696
|
});
|
|
867
697
|
const resolved = resolveCallSiteConfig("memoryExtraction", llm);
|
|
868
698
|
expect(resolved.provider).toBe("openai");
|
|
869
|
-
expect(resolved.model).toBe("gpt-5.5");
|
|
870
699
|
expect(resolved.provider_connection).toBe("openai-personal");
|
|
700
|
+
expect(resolved.model).toBe(
|
|
701
|
+
resolveModelIntent("openai", "latency-optimized"),
|
|
702
|
+
);
|
|
871
703
|
});
|
|
872
704
|
|
|
873
|
-
test("BYOK full-workspace:
|
|
705
|
+
test("BYOK full-workspace: every call site resolves through the default provider, never the managed connection", () => {
|
|
874
706
|
const byokConfig = LLMSchema.parse({
|
|
875
|
-
default: {
|
|
876
|
-
...fullDefault,
|
|
877
|
-
provider: "openai",
|
|
878
|
-
model: "gpt-5.5",
|
|
879
|
-
provider_connection: "openai-personal",
|
|
880
|
-
},
|
|
881
707
|
profiles: {
|
|
882
|
-
balanced: {
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
provider: "anthropic",
|
|
886
|
-
model: "claude-sonnet-4-6",
|
|
887
|
-
provider_connection: "anthropic-managed",
|
|
888
|
-
},
|
|
889
|
-
"cost-optimized": {
|
|
890
|
-
status: "disabled",
|
|
891
|
-
source: "managed",
|
|
892
|
-
provider: "anthropic",
|
|
893
|
-
model: "claude-haiku-4-5-20251001",
|
|
894
|
-
provider_connection: "anthropic-managed",
|
|
895
|
-
},
|
|
896
|
-
"quality-optimized": {
|
|
897
|
-
status: "disabled",
|
|
898
|
-
source: "managed",
|
|
899
|
-
provider: "anthropic",
|
|
900
|
-
model: "claude-opus-4-7",
|
|
901
|
-
provider_connection: "anthropic-managed",
|
|
902
|
-
},
|
|
708
|
+
balanced: { source: "managed", status: "disabled" },
|
|
709
|
+
"cost-optimized": { source: "managed", status: "disabled" },
|
|
710
|
+
"quality-optimized": { source: "managed", status: "disabled" },
|
|
903
711
|
"custom-balanced": {
|
|
904
712
|
source: "user",
|
|
905
713
|
provider: "openai",
|
|
906
714
|
model: "gpt-5.5",
|
|
907
715
|
provider_connection: "openai-personal",
|
|
908
716
|
},
|
|
909
|
-
"custom-cost-optimized": {
|
|
910
|
-
source: "user",
|
|
911
|
-
provider: "openai",
|
|
912
|
-
model: "gpt-5.4-nano",
|
|
913
|
-
provider_connection: "openai-personal",
|
|
914
|
-
},
|
|
915
|
-
"custom-quality-optimized": {
|
|
916
|
-
source: "user",
|
|
917
|
-
provider: "openai",
|
|
918
|
-
model: "gpt-5.5-pro",
|
|
919
|
-
provider_connection: "openai-personal",
|
|
920
|
-
},
|
|
921
717
|
},
|
|
922
718
|
activeProfile: "custom-balanced",
|
|
719
|
+
defaultProvider: { provider: "openai" },
|
|
923
720
|
});
|
|
924
721
|
|
|
925
722
|
const callSites: LLMCallSite[] = [
|
|
@@ -952,48 +749,30 @@ describe("resolveCallSiteConfig", () => {
|
|
|
952
749
|
expect(resolved.provider).toBe("openai");
|
|
953
750
|
}
|
|
954
751
|
|
|
955
|
-
// Cost-optimized call sites
|
|
752
|
+
// Cost-optimized call sites resolve the intent through the BYOK provider.
|
|
956
753
|
const costSite = resolveCallSiteConfig("heartbeatAgent", byokConfig);
|
|
957
|
-
expect(costSite.model).toBe(
|
|
754
|
+
expect(costSite.model).toBe(
|
|
755
|
+
resolveModelIntent("openai", "latency-optimized"),
|
|
756
|
+
);
|
|
958
757
|
|
|
959
|
-
//
|
|
758
|
+
// mainAgent uses the user's active profile.
|
|
960
759
|
const balancedSite = resolveCallSiteConfig("mainAgent", byokConfig);
|
|
961
760
|
expect(balancedSite.model).toBe("gpt-5.5");
|
|
962
761
|
});
|
|
963
762
|
|
|
964
|
-
test("BYOK: tuning overrides from
|
|
763
|
+
test("BYOK: tuning overrides from CALL_SITE_DEFAULTS apply on top of the default-provider winner", () => {
|
|
965
764
|
const byokConfig = LLMSchema.parse({
|
|
966
|
-
default: {
|
|
967
|
-
...fullDefault,
|
|
968
|
-
provider: "openai",
|
|
969
|
-
model: "gpt-5.5",
|
|
970
|
-
provider_connection: "openai-personal",
|
|
971
|
-
},
|
|
972
765
|
profiles: {
|
|
973
|
-
"cost-optimized": {
|
|
974
|
-
status: "disabled",
|
|
975
|
-
provider: "anthropic",
|
|
976
|
-
model: "claude-haiku-4-5-20251001",
|
|
977
|
-
provider_connection: "anthropic-managed",
|
|
978
|
-
},
|
|
979
|
-
"custom-cost-optimized": {
|
|
980
|
-
source: "user",
|
|
981
|
-
provider: "openai",
|
|
982
|
-
model: "gpt-5.4-nano",
|
|
983
|
-
provider_connection: "openai-personal",
|
|
984
|
-
},
|
|
985
|
-
"custom-balanced": {
|
|
986
|
-
provider: "openai",
|
|
987
|
-
model: "gpt-5.5",
|
|
988
|
-
provider_connection: "openai-personal",
|
|
989
|
-
},
|
|
766
|
+
"cost-optimized": { source: "managed", status: "disabled" },
|
|
990
767
|
},
|
|
991
|
-
|
|
768
|
+
defaultProvider: { provider: "openai" },
|
|
992
769
|
});
|
|
993
770
|
|
|
994
771
|
const resolved = resolveCallSiteConfig("commitMessage", byokConfig);
|
|
995
772
|
expect(resolved.provider).toBe("openai");
|
|
996
|
-
expect(resolved.model).toBe(
|
|
773
|
+
expect(resolved.model).toBe(
|
|
774
|
+
resolveModelIntent("openai", "latency-optimized"),
|
|
775
|
+
);
|
|
997
776
|
expect(resolved.maxTokens).toBe(120);
|
|
998
777
|
expect(resolved.effort).toBe("low");
|
|
999
778
|
expect(resolved.thinking.enabled).toBe(false);
|
|
@@ -1001,10 +780,19 @@ describe("resolveCallSiteConfig", () => {
|
|
|
1001
780
|
|
|
1002
781
|
test("overrideProfile wins over CALL_SITE_DEFAULTS profile for non-main call sites", () => {
|
|
1003
782
|
const llm = LLMSchema.parse({
|
|
1004
|
-
default: fullDefault,
|
|
1005
783
|
profiles: {
|
|
1006
|
-
"cost-optimized": {
|
|
1007
|
-
|
|
784
|
+
"cost-optimized": {
|
|
785
|
+
source: "user",
|
|
786
|
+
provider: "anthropic",
|
|
787
|
+
model: "claude-haiku-4-5-20251001",
|
|
788
|
+
effort: "low",
|
|
789
|
+
},
|
|
790
|
+
"quality-optimized": {
|
|
791
|
+
source: "user",
|
|
792
|
+
provider: "anthropic",
|
|
793
|
+
model: "claude-opus-4-7",
|
|
794
|
+
effort: "max",
|
|
795
|
+
},
|
|
1008
796
|
},
|
|
1009
797
|
});
|
|
1010
798
|
const resolved = resolveCallSiteConfig("inference", llm, {
|
|
@@ -1014,20 +802,12 @@ describe("resolveCallSiteConfig", () => {
|
|
|
1014
802
|
expect(resolved.effort).toBe("max");
|
|
1015
803
|
});
|
|
1016
804
|
|
|
1017
|
-
test("profile
|
|
1018
|
-
//
|
|
1019
|
-
//
|
|
1020
|
-
//
|
|
1021
|
-
// dispatch layer (connection-resolution auto-resolves the mismatch).
|
|
805
|
+
test("a winning profile without provider_connection resolves without one (no stale connection inheritance)", () => {
|
|
806
|
+
// Single-winner selection means nothing outside the winner can supply a
|
|
807
|
+
// provider connection: a profile that omits it resolves without one, and
|
|
808
|
+
// dispatch auto-resolves the connection by provider (JARVIS-861).
|
|
1022
809
|
const llm = LLMSchema.parse({
|
|
1023
|
-
default: {
|
|
1024
|
-
...fullDefault,
|
|
1025
|
-
provider_connection: "anthropic-managed",
|
|
1026
|
-
},
|
|
1027
810
|
profiles: {
|
|
1028
|
-
// Disable the catalog default so the stale connection under test
|
|
1029
|
-
// comes from `llm.default`, not the catalog `balanced` layer.
|
|
1030
|
-
balanced: { source: "managed", status: "disabled" },
|
|
1031
811
|
fireworks: {
|
|
1032
812
|
provider: "fireworks",
|
|
1033
813
|
model: "accounts/fireworks/models/kimi-k2p5",
|
|
@@ -1039,18 +819,16 @@ describe("resolveCallSiteConfig", () => {
|
|
|
1039
819
|
const resolved = resolveCallSiteConfig("mainAgent", llm);
|
|
1040
820
|
|
|
1041
821
|
expect(resolved.provider).toBe("fireworks");
|
|
1042
|
-
|
|
1043
|
-
expect(resolved.provider_connection).toBe("anthropic-managed");
|
|
822
|
+
expect(resolved.provider_connection).toBeUndefined();
|
|
1044
823
|
});
|
|
1045
824
|
});
|
|
1046
825
|
|
|
1047
826
|
describe("mix profiles", () => {
|
|
1048
827
|
// A mix that routes 80% to `a` (model-a) and 20% to `b` (model-b).
|
|
1049
828
|
const mixLlm = LLMSchema.parse({
|
|
1050
|
-
default: fullDefault,
|
|
1051
829
|
profiles: {
|
|
1052
|
-
a: { model: "model-a", effort: "low" },
|
|
1053
|
-
b: { model: "model-b", effort: "high" },
|
|
830
|
+
a: { provider: "anthropic", model: "model-a", effort: "low" },
|
|
831
|
+
b: { provider: "anthropic", model: "model-b", effort: "high" },
|
|
1054
832
|
ab: {
|
|
1055
833
|
mix: [
|
|
1056
834
|
{ profile: "a", weight: 80 },
|
|
@@ -1074,15 +852,18 @@ describe("mix profiles", () => {
|
|
|
1074
852
|
expect(first.model).toBe(second.model);
|
|
1075
853
|
expect(["model-a", "model-b"]).toContain(first.model);
|
|
1076
854
|
// The chosen arm's other fields flow through; the other arm's don't.
|
|
1077
|
-
if (first.model === "model-a")
|
|
1078
|
-
|
|
855
|
+
if (first.model === "model-a") {
|
|
856
|
+
expect(first.effort).toBe("low");
|
|
857
|
+
} else {
|
|
858
|
+
expect(first.effort).toBe("high");
|
|
859
|
+
}
|
|
1079
860
|
});
|
|
1080
861
|
|
|
1081
862
|
test("all dereference spots in a turn agree for the same seed", () => {
|
|
1082
|
-
// mainAgent (mix
|
|
1083
|
-
//
|
|
1084
|
-
//
|
|
1085
|
-
//
|
|
863
|
+
// mainAgent (mix as activeProfile) and a non-main call site resolving the
|
|
864
|
+
// same mix as its call-site profile must pick the same arm when given the
|
|
865
|
+
// same conversation seed — guards the invariant that every resolver call
|
|
866
|
+
// within a conversation lands on one arm.
|
|
1086
867
|
const main = resolveCallSiteConfig("mainAgent", mixLlm, {
|
|
1087
868
|
selectionSeed: "conv-xyz",
|
|
1088
869
|
});
|
|
@@ -1099,8 +880,11 @@ describe("mix profiles", () => {
|
|
|
1099
880
|
const resolved = resolveCallSiteConfig("mainAgent", mixLlm, {
|
|
1100
881
|
selectionSeed: `conv-${i}`,
|
|
1101
882
|
});
|
|
1102
|
-
if (resolved.model === "model-a")
|
|
1103
|
-
|
|
883
|
+
if (resolved.model === "model-a") {
|
|
884
|
+
aCount++;
|
|
885
|
+
} else if (resolved.model === "model-b") {
|
|
886
|
+
bCount++;
|
|
887
|
+
}
|
|
1104
888
|
}
|
|
1105
889
|
// Both arms must be reachable, and the 80/20 weighting must skew toward
|
|
1106
890
|
// `a`. Wide band so the assertion locks weighting without coupling to the
|
|
@@ -1113,10 +897,9 @@ describe("mix profiles", () => {
|
|
|
1113
897
|
|
|
1114
898
|
test("relative weights are normalized by their sum ([80,20] ≡ [4,1])", () => {
|
|
1115
899
|
const llm2 = LLMSchema.parse({
|
|
1116
|
-
default: fullDefault,
|
|
1117
900
|
profiles: {
|
|
1118
|
-
a: { model: "model-a" },
|
|
1119
|
-
b: { model: "model-b" },
|
|
901
|
+
a: { provider: "anthropic", model: "model-a" },
|
|
902
|
+
b: { provider: "anthropic", model: "model-b" },
|
|
1120
903
|
ab: {
|
|
1121
904
|
mix: [
|
|
1122
905
|
{ profile: "a", weight: 4 },
|
|
@@ -1139,10 +922,9 @@ describe("mix profiles", () => {
|
|
|
1139
922
|
|
|
1140
923
|
test("mix works as overrideProfile", () => {
|
|
1141
924
|
const llm = LLMSchema.parse({
|
|
1142
|
-
default: fullDefault,
|
|
1143
925
|
profiles: {
|
|
1144
|
-
a: { model: "model-a" },
|
|
1145
|
-
b: { model: "model-b" },
|
|
926
|
+
a: { provider: "anthropic", model: "model-a" },
|
|
927
|
+
b: { provider: "anthropic", model: "model-b" },
|
|
1146
928
|
ab: {
|
|
1147
929
|
mix: [
|
|
1148
930
|
{ profile: "a", weight: 50 },
|
|
@@ -1160,10 +942,9 @@ describe("mix profiles", () => {
|
|
|
1160
942
|
|
|
1161
943
|
test("mix works as a call-site profile (non-mainAgent and mainAgent)", () => {
|
|
1162
944
|
const llm = LLMSchema.parse({
|
|
1163
|
-
default: fullDefault,
|
|
1164
945
|
profiles: {
|
|
1165
|
-
a: { model: "model-a" },
|
|
1166
|
-
b: { model: "model-b" },
|
|
946
|
+
a: { provider: "anthropic", model: "model-a" },
|
|
947
|
+
b: { provider: "anthropic", model: "model-b" },
|
|
1167
948
|
ab: {
|
|
1168
949
|
mix: [
|
|
1169
950
|
{ profile: "a", weight: 50 },
|
|
@@ -1211,7 +992,6 @@ describe("mix profiles", () => {
|
|
|
1211
992
|
|
|
1212
993
|
describe("mix validation (LLMSchema.superRefine)", () => {
|
|
1213
994
|
const base = {
|
|
1214
|
-
default: fullDefault,
|
|
1215
995
|
profiles: {
|
|
1216
996
|
a: { model: "model-a" },
|
|
1217
997
|
b: { model: "model-b" },
|
|
@@ -1343,7 +1123,6 @@ describe("mix validation (LLMSchema.superRefine)", () => {
|
|
|
1343
1123
|
describe("resolveDefaultProfileKey", () => {
|
|
1344
1124
|
test("mainAgent returns activeProfile when set and enabled", () => {
|
|
1345
1125
|
const llm = LLMSchema.parse({
|
|
1346
|
-
default: fullDefault,
|
|
1347
1126
|
profiles: {
|
|
1348
1127
|
balanced: { provider: "anthropic", model: "claude-sonnet-4-7" },
|
|
1349
1128
|
gemini: { provider: "gemini", model: "gemini-2.5-pro" },
|
|
@@ -1353,9 +1132,8 @@ describe("resolveDefaultProfileKey", () => {
|
|
|
1353
1132
|
expect(resolveDefaultProfileKey("mainAgent", llm)).toBe("gemini");
|
|
1354
1133
|
});
|
|
1355
1134
|
|
|
1356
|
-
test("mainAgent falls back to
|
|
1135
|
+
test("mainAgent falls back to the call-site intent when activeProfile is unset", () => {
|
|
1357
1136
|
const llm = LLMSchema.parse({
|
|
1358
|
-
default: fullDefault,
|
|
1359
1137
|
profiles: {
|
|
1360
1138
|
balanced: { provider: "anthropic", model: "claude-sonnet-4-7" },
|
|
1361
1139
|
},
|
|
@@ -1364,9 +1142,8 @@ describe("resolveDefaultProfileKey", () => {
|
|
|
1364
1142
|
expect(resolveDefaultProfileKey("mainAgent", llm)).toBe("balanced");
|
|
1365
1143
|
});
|
|
1366
1144
|
|
|
1367
|
-
test("mainAgent falls back to
|
|
1145
|
+
test("mainAgent falls back to the call-site intent when activeProfile points to a missing profile", () => {
|
|
1368
1146
|
const llm = LLMSchema.parse({
|
|
1369
|
-
default: fullDefault,
|
|
1370
1147
|
profiles: {
|
|
1371
1148
|
balanced: { provider: "anthropic", model: "claude-sonnet-4-7" },
|
|
1372
1149
|
},
|
|
@@ -1378,9 +1155,8 @@ describe("resolveDefaultProfileKey", () => {
|
|
|
1378
1155
|
expect(resolveDefaultProfileKey("mainAgent", mutated)).toBe("balanced");
|
|
1379
1156
|
});
|
|
1380
1157
|
|
|
1381
|
-
test("mainAgent falls back to
|
|
1158
|
+
test("mainAgent falls back to the call-site intent when activeProfile is disabled", () => {
|
|
1382
1159
|
const llm = LLMSchema.parse({
|
|
1383
|
-
default: fullDefault,
|
|
1384
1160
|
profiles: {
|
|
1385
1161
|
balanced: { provider: "anthropic", model: "claude-sonnet-4-7" },
|
|
1386
1162
|
gemini: {
|
|
@@ -1394,9 +1170,8 @@ describe("resolveDefaultProfileKey", () => {
|
|
|
1394
1170
|
expect(resolveDefaultProfileKey("mainAgent", llm)).toBe("balanced");
|
|
1395
1171
|
});
|
|
1396
1172
|
|
|
1397
|
-
test("non-mainAgent ignores activeProfile and returns
|
|
1173
|
+
test("non-mainAgent ignores activeProfile and returns the call-site intent", () => {
|
|
1398
1174
|
const llm = LLMSchema.parse({
|
|
1399
|
-
default: fullDefault,
|
|
1400
1175
|
profiles: {
|
|
1401
1176
|
balanced: { provider: "anthropic", model: "claude-sonnet-4-7" },
|
|
1402
1177
|
"cost-optimized": { provider: "openai", model: "gpt-5-mini" },
|
|
@@ -1408,9 +1183,11 @@ describe("resolveDefaultProfileKey", () => {
|
|
|
1408
1183
|
expect(resolveDefaultProfileKey("filingAgent", llm)).toBe("cost-optimized");
|
|
1409
1184
|
});
|
|
1410
1185
|
|
|
1411
|
-
test("
|
|
1186
|
+
test("a disabled managed default stub does not divert the key to custom-*", () => {
|
|
1187
|
+
// The default intent is code-owned: a legacy disabled stub is overridden
|
|
1188
|
+
// by the catalog body, and the user-mutable custom-* clone never captures
|
|
1189
|
+
// the call site.
|
|
1412
1190
|
const llm = LLMSchema.parse({
|
|
1413
|
-
default: fullDefault,
|
|
1414
1191
|
profiles: {
|
|
1415
1192
|
"cost-optimized": { source: "managed", status: "disabled" },
|
|
1416
1193
|
"custom-cost-optimized": {
|
|
@@ -1419,17 +1196,14 @@ describe("resolveDefaultProfileKey", () => {
|
|
|
1419
1196
|
},
|
|
1420
1197
|
},
|
|
1421
1198
|
});
|
|
1422
|
-
expect(resolveDefaultProfileKey("filingAgent", llm)).toBe(
|
|
1423
|
-
"custom-cost-optimized",
|
|
1424
|
-
);
|
|
1199
|
+
expect(resolveDefaultProfileKey("filingAgent", llm)).toBe("cost-optimized");
|
|
1425
1200
|
});
|
|
1426
1201
|
|
|
1427
1202
|
test("mainAgent returns the mix key (not an arm) when activeProfile is a mix", () => {
|
|
1428
1203
|
const llm = LLMSchema.parse({
|
|
1429
|
-
default: fullDefault,
|
|
1430
1204
|
profiles: {
|
|
1431
|
-
a: { model: "model-a" },
|
|
1432
|
-
b: { model: "model-b" },
|
|
1205
|
+
a: { provider: "anthropic", model: "model-a" },
|
|
1206
|
+
b: { provider: "anthropic", model: "model-b" },
|
|
1433
1207
|
ab: {
|
|
1434
1208
|
mix: [
|
|
1435
1209
|
{ profile: "a", weight: 1 },
|
|
@@ -1442,13 +1216,12 @@ describe("resolveDefaultProfileKey", () => {
|
|
|
1442
1216
|
expect(resolveDefaultProfileKey("mainAgent", llm)).toBe("ab");
|
|
1443
1217
|
});
|
|
1444
1218
|
|
|
1445
|
-
test("mainAgent falls back to
|
|
1219
|
+
test("mainAgent falls back to the call-site intent when the mix activeProfile is disabled", () => {
|
|
1446
1220
|
const llm = LLMSchema.parse({
|
|
1447
|
-
default: fullDefault,
|
|
1448
1221
|
profiles: {
|
|
1449
1222
|
balanced: { provider: "anthropic", model: "claude-sonnet-4-7" },
|
|
1450
|
-
a: { model: "model-a" },
|
|
1451
|
-
b: { model: "model-b" },
|
|
1223
|
+
a: { provider: "anthropic", model: "model-a" },
|
|
1224
|
+
b: { provider: "anthropic", model: "model-b" },
|
|
1452
1225
|
ab: {
|
|
1453
1226
|
status: "disabled",
|
|
1454
1227
|
mix: [
|
|
@@ -1465,7 +1238,6 @@ describe("resolveDefaultProfileKey", () => {
|
|
|
1465
1238
|
|
|
1466
1239
|
describe("resolveEffectiveProfileKey", () => {
|
|
1467
1240
|
const llm = LLMSchema.parse({
|
|
1468
|
-
default: fullDefault,
|
|
1469
1241
|
profiles: {
|
|
1470
1242
|
balanced: { provider: "anthropic", model: "claude-sonnet-4-7" },
|
|
1471
1243
|
"cost-optimized": { provider: "openai", model: "gpt-5-mini" },
|
|
@@ -1486,10 +1258,7 @@ describe("resolveEffectiveProfileKey", () => {
|
|
|
1486
1258
|
expect(resolveEffectiveProfileKey("mainAgent", llm)).toBe("balanced");
|
|
1487
1259
|
});
|
|
1488
1260
|
|
|
1489
|
-
|
|
1490
|
-
// the override — `effectiveDefault` strips the catalog default when an
|
|
1491
|
-
// override is present, so the override is the profile that supplies the config.
|
|
1492
|
-
test("non-mainAgent: pinned override wins over stripped catalog default", () => {
|
|
1261
|
+
test("non-mainAgent: pinned override wins over the call-site intent", () => {
|
|
1493
1262
|
expect(
|
|
1494
1263
|
resolveEffectiveProfileKey("filingAgent", llm, {
|
|
1495
1264
|
overrideProfile: "pinned",
|
|
@@ -1497,14 +1266,16 @@ describe("resolveEffectiveProfileKey", () => {
|
|
|
1497
1266
|
).toBe("pinned");
|
|
1498
1267
|
});
|
|
1499
1268
|
|
|
1500
|
-
test("non-mainAgent:
|
|
1269
|
+
test("non-mainAgent: call-site intent when no override", () => {
|
|
1501
1270
|
// filingAgent's CALL_SITE_DEFAULTS profile is `cost-optimized`.
|
|
1502
1271
|
expect(resolveEffectiveProfileKey("filingAgent", llm)).toBe(
|
|
1503
1272
|
"cost-optimized",
|
|
1504
1273
|
);
|
|
1505
1274
|
});
|
|
1506
1275
|
|
|
1507
|
-
test("non-mainAgent: explicit call-site profile
|
|
1276
|
+
test("non-mainAgent: the override outranks an explicit call-site profile (forced or not)", () => {
|
|
1277
|
+
// The override is the first rung of the selection chain on every call
|
|
1278
|
+
// site; `forceOverrideProfile` is a no-op.
|
|
1508
1279
|
const withSite = LLMSchema.parse({
|
|
1509
1280
|
...llm,
|
|
1510
1281
|
callSites: { filingAgent: { profile: "cost-optimized" } },
|
|
@@ -1513,14 +1284,7 @@ describe("resolveEffectiveProfileKey", () => {
|
|
|
1513
1284
|
resolveEffectiveProfileKey("filingAgent", withSite, {
|
|
1514
1285
|
overrideProfile: "pinned",
|
|
1515
1286
|
}),
|
|
1516
|
-
).toBe("
|
|
1517
|
-
});
|
|
1518
|
-
|
|
1519
|
-
test("non-mainAgent: forced override floats above the call-site profile", () => {
|
|
1520
|
-
const withSite = LLMSchema.parse({
|
|
1521
|
-
...llm,
|
|
1522
|
-
callSites: { filingAgent: { profile: "cost-optimized" } },
|
|
1523
|
-
});
|
|
1287
|
+
).toBe("pinned");
|
|
1524
1288
|
expect(
|
|
1525
1289
|
resolveEffectiveProfileKey("filingAgent", withSite, {
|
|
1526
1290
|
overrideProfile: "pinned",
|
|
@@ -1535,7 +1299,6 @@ describe("resolveCallSiteConfig logitBias provenance", () => {
|
|
|
1535
1299
|
|
|
1536
1300
|
test("forwards logitBias from the active profile that opted in", () => {
|
|
1537
1301
|
const llm = LLMSchema.parse({
|
|
1538
|
-
default: fullDefault,
|
|
1539
1302
|
profiles: {
|
|
1540
1303
|
"balanced-economy": {
|
|
1541
1304
|
provider: "fireworks",
|
|
@@ -1550,12 +1313,11 @@ describe("resolveCallSiteConfig logitBias provenance", () => {
|
|
|
1550
1313
|
);
|
|
1551
1314
|
});
|
|
1552
1315
|
|
|
1553
|
-
test("
|
|
1316
|
+
test("an override profile that omits logitBias clears it", () => {
|
|
1554
1317
|
// Active profile opts in, but a pinned (override) Kimi profile did not —
|
|
1555
1318
|
// the override must not inherit suppress-cjk just because it resolves to
|
|
1556
1319
|
// Fireworks.
|
|
1557
1320
|
const llm = LLMSchema.parse({
|
|
1558
|
-
default: fullDefault,
|
|
1559
1321
|
profiles: {
|
|
1560
1322
|
"balanced-economy": {
|
|
1561
1323
|
provider: "fireworks",
|
|
@@ -1576,7 +1338,6 @@ describe("resolveCallSiteConfig logitBias provenance", () => {
|
|
|
1576
1338
|
// For non-main call sites the call-site profile wins; since it didn't opt
|
|
1577
1339
|
// in, the active profile's preset must not bleed through.
|
|
1578
1340
|
const llm = LLMSchema.parse({
|
|
1579
|
-
default: fullDefault,
|
|
1580
1341
|
profiles: {
|
|
1581
1342
|
"balanced-economy": {
|
|
1582
1343
|
provider: "fireworks",
|
|
@@ -1592,24 +1353,14 @@ describe("resolveCallSiteConfig logitBias provenance", () => {
|
|
|
1592
1353
|
resolveCallSiteConfig("memoryExtraction", llm).logitBias,
|
|
1593
1354
|
).toBeUndefined();
|
|
1594
1355
|
});
|
|
1595
|
-
|
|
1596
|
-
test("a logitBias on a non-profile layer (llm.default) does not apply when the winning profile omits it", () => {
|
|
1597
|
-
const llm = LLMSchema.parse({
|
|
1598
|
-
default: { ...fullDefault, logitBias: "suppress-cjk" },
|
|
1599
|
-
profiles: { plain: { provider: "anthropic", model: "claude-opus-4-7" } },
|
|
1600
|
-
activeProfile: "plain",
|
|
1601
|
-
});
|
|
1602
|
-
expect(resolveCallSiteConfig("mainAgent", llm).logitBias).toBeUndefined();
|
|
1603
|
-
});
|
|
1604
1356
|
});
|
|
1605
1357
|
|
|
1606
1358
|
describe("resolveCallSiteConfig sampling-param provenance (temperature / top_p)", () => {
|
|
1607
|
-
// Mirrors production: the
|
|
1359
|
+
// Mirrors production: the user's `balanced` profile carries `topP: 0.95` (a
|
|
1608
1360
|
// MiniMax tuning), while background call sites resolve to the Anthropic
|
|
1609
|
-
// `cost-optimized` profile. A
|
|
1361
|
+
// `cost-optimized` profile. A cross-profile leak would put the balanced
|
|
1610
1362
|
// profile's `top_p` onto those Anthropic requests.
|
|
1611
1363
|
const balancedActive = LLMSchema.parse({
|
|
1612
|
-
default: fullDefault,
|
|
1613
1364
|
profiles: {
|
|
1614
1365
|
balanced: {
|
|
1615
1366
|
provider: "together",
|
|
@@ -1626,9 +1377,8 @@ describe("resolveCallSiteConfig sampling-param provenance (temperature / top_p)"
|
|
|
1626
1377
|
activeProfile: "balanced",
|
|
1627
1378
|
});
|
|
1628
1379
|
|
|
1629
|
-
test("active profile's top_p does not leak into a profile-pinned call site
|
|
1380
|
+
test("active profile's top_p does not leak into a profile-pinned call site", () => {
|
|
1630
1381
|
const llm = LLMSchema.parse({
|
|
1631
|
-
default: fullDefault,
|
|
1632
1382
|
profiles: {
|
|
1633
1383
|
balanced: {
|
|
1634
1384
|
provider: "together",
|
|
@@ -1646,8 +1396,8 @@ describe("resolveCallSiteConfig sampling-param provenance (temperature / top_p)"
|
|
|
1646
1396
|
const resolved = resolveCallSiteConfig("memoryExtraction", llm);
|
|
1647
1397
|
expect(resolved.provider).toBe("anthropic");
|
|
1648
1398
|
expect(resolved.model).toBe("claude-haiku-4-5-20251001");
|
|
1649
|
-
// balanced
|
|
1650
|
-
//
|
|
1399
|
+
// balanced is not the winner here, so its top_p must not ride along onto
|
|
1400
|
+
// the Anthropic request.
|
|
1651
1401
|
expect(resolved.topP).toBeNull();
|
|
1652
1402
|
});
|
|
1653
1403
|
|
|
@@ -1656,7 +1406,7 @@ describe("resolveCallSiteConfig sampling-param provenance (temperature / top_p)"
|
|
|
1656
1406
|
expect(greeting.model).toBe("claude-haiku-4-5-20251001");
|
|
1657
1407
|
// Per-call-site temperature from CALL_SITE_DEFAULTS survives.
|
|
1658
1408
|
expect(greeting.temperature).toBe(0.7);
|
|
1659
|
-
// The
|
|
1409
|
+
// The balanced profile's top_p does NOT — both together would trip
|
|
1660
1410
|
// Anthropic's "temperature and top_p cannot both be specified".
|
|
1661
1411
|
expect(greeting.topP).toBeNull();
|
|
1662
1412
|
|
|
@@ -1665,10 +1415,10 @@ describe("resolveCallSiteConfig sampling-param provenance (temperature / top_p)"
|
|
|
1665
1415
|
expect(commit.topP).toBeNull();
|
|
1666
1416
|
});
|
|
1667
1417
|
|
|
1668
|
-
test("profile-less call site
|
|
1669
|
-
// `workflowLeaf` pins no profile, so
|
|
1670
|
-
//
|
|
1671
|
-
// (coherent, same-provider) sampling.
|
|
1418
|
+
test("a profile-less call site anchors on the balanced intent, which the user's shadow implements (provider AND sampling)", () => {
|
|
1419
|
+
// `workflowLeaf` pins no profile, so it anchors on the balanced intent —
|
|
1420
|
+
// here implemented by the user's own `balanced` shadow, which supplies
|
|
1421
|
+
// provider/model and its own (coherent, same-provider) sampling.
|
|
1672
1422
|
const resolved = resolveCallSiteConfig("workflowLeaf", balancedActive);
|
|
1673
1423
|
expect(resolved.provider).toBe("together");
|
|
1674
1424
|
expect(resolved.model).toBe("MiniMaxAI/MiniMax-M3");
|
|
@@ -1683,8 +1433,14 @@ describe("resolveCallSiteConfig sampling-param provenance (temperature / top_p)"
|
|
|
1683
1433
|
|
|
1684
1434
|
test("an explicit call-site temperature override still wins over the winning profile", () => {
|
|
1685
1435
|
const llm = LLMSchema.parse({
|
|
1686
|
-
|
|
1687
|
-
|
|
1436
|
+
profiles: {
|
|
1437
|
+
nucleus: {
|
|
1438
|
+
provider: "anthropic",
|
|
1439
|
+
model: "claude-opus-4-7",
|
|
1440
|
+
topP: 0.9,
|
|
1441
|
+
temperature: 0.1,
|
|
1442
|
+
},
|
|
1443
|
+
},
|
|
1688
1444
|
callSites: { memoryExtraction: { profile: "nucleus", temperature: 0.5 } },
|
|
1689
1445
|
});
|
|
1690
1446
|
const resolved = resolveCallSiteConfig("memoryExtraction", llm);
|
|
@@ -1694,12 +1450,10 @@ describe("resolveCallSiteConfig sampling-param provenance (temperature / top_p)"
|
|
|
1694
1450
|
expect(resolved.topP).toBe(0.9);
|
|
1695
1451
|
});
|
|
1696
1452
|
|
|
1697
|
-
test("
|
|
1698
|
-
//
|
|
1699
|
-
//
|
|
1700
|
-
// balanced's 0.95 must be cleared rather than surviving the merge.
|
|
1453
|
+
test("an override winner that omits top_p clears a shadowed profile's top_p", () => {
|
|
1454
|
+
// The override profile wins and omits top_p, so balanced's 0.95 must not
|
|
1455
|
+
// survive — only the single winner contributes sampling.
|
|
1701
1456
|
const llm = LLMSchema.parse({
|
|
1702
|
-
default: fullDefault,
|
|
1703
1457
|
profiles: {
|
|
1704
1458
|
balanced: {
|
|
1705
1459
|
provider: "together",
|
|
@@ -1717,13 +1471,15 @@ describe("resolveCallSiteConfig sampling-param provenance (temperature / top_p)"
|
|
|
1717
1471
|
expect(resolved.topP).toBeNull();
|
|
1718
1472
|
});
|
|
1719
1473
|
|
|
1720
|
-
test("
|
|
1474
|
+
test("an explicit call-site temperature survives an override winner silent on sampling", () => {
|
|
1721
1475
|
const llm = LLMSchema.parse({
|
|
1722
|
-
default: fullDefault,
|
|
1723
1476
|
profiles: {
|
|
1724
|
-
active: { verbosity: "low" },
|
|
1725
1477
|
sitep: { provider: "anthropic", model: "claude-haiku-4-5-20251001" },
|
|
1726
|
-
forced: {
|
|
1478
|
+
forced: {
|
|
1479
|
+
provider: "anthropic",
|
|
1480
|
+
model: "claude-opus-4-7",
|
|
1481
|
+
effort: "high",
|
|
1482
|
+
},
|
|
1727
1483
|
},
|
|
1728
1484
|
callSites: {
|
|
1729
1485
|
memoryExtraction: {
|
|
@@ -1732,85 +1488,71 @@ describe("resolveCallSiteConfig sampling-param provenance (temperature / top_p)"
|
|
|
1732
1488
|
maxTokens: 1000,
|
|
1733
1489
|
},
|
|
1734
1490
|
},
|
|
1735
|
-
activeProfile: "active",
|
|
1736
1491
|
});
|
|
1737
1492
|
const resolved = resolveCallSiteConfig("memoryExtraction", llm, {
|
|
1738
1493
|
overrideProfile: "forced",
|
|
1739
1494
|
forceOverrideProfile: true,
|
|
1740
1495
|
});
|
|
1741
|
-
// The
|
|
1496
|
+
// The override profile is the winner for the fields it sets.
|
|
1742
1497
|
expect(resolved.model).toBe("claude-opus-4-7");
|
|
1743
1498
|
expect(resolved.effort).toBe("high");
|
|
1744
1499
|
// It is silent on temperature, so the deliberate call-site value survives —
|
|
1745
|
-
// consistent with sibling call-site fields like maxTokens
|
|
1746
|
-
// through the deep-merge).
|
|
1500
|
+
// consistent with sibling call-site fields like maxTokens.
|
|
1747
1501
|
expect(resolved.temperature).toBe(0.7);
|
|
1748
1502
|
expect(resolved.maxTokens).toBe(1000);
|
|
1749
1503
|
});
|
|
1750
1504
|
|
|
1751
|
-
test("
|
|
1505
|
+
test("mainAgent: an explicit call-site temperature survives an active profile silent on sampling", () => {
|
|
1752
1506
|
const llm = LLMSchema.parse({
|
|
1753
|
-
default: fullDefault,
|
|
1754
1507
|
profiles: {
|
|
1755
|
-
|
|
1756
|
-
forced: { model: "claude-opus-4-7", temperature: 0.1 },
|
|
1757
|
-
},
|
|
1758
|
-
callSites: {
|
|
1759
|
-
memoryExtraction: { profile: "sitep", temperature: 0.7 },
|
|
1508
|
+
active: { provider: "anthropic", model: "claude-sonnet-4-7" },
|
|
1760
1509
|
},
|
|
1761
|
-
});
|
|
1762
|
-
const resolved = resolveCallSiteConfig("memoryExtraction", llm, {
|
|
1763
|
-
overrideProfile: "forced",
|
|
1764
|
-
forceOverrideProfile: true,
|
|
1765
|
-
});
|
|
1766
|
-
// The forced profile explicitly sets temperature, so it floats above the
|
|
1767
|
-
// call-site override.
|
|
1768
|
-
expect(resolved.temperature).toBe(0.1);
|
|
1769
|
-
});
|
|
1770
|
-
|
|
1771
|
-
test("mainAgent: an explicit call-site temperature survives an active profile silent on sampling", () => {
|
|
1772
|
-
const llm = LLMSchema.parse({
|
|
1773
|
-
default: fullDefault,
|
|
1774
|
-
profiles: { active: { model: "claude-sonnet-4-7" } },
|
|
1775
1510
|
callSites: { mainAgent: { temperature: 0.5 } },
|
|
1776
1511
|
activeProfile: "active",
|
|
1777
1512
|
});
|
|
1778
1513
|
const resolved = resolveCallSiteConfig("mainAgent", llm);
|
|
1779
|
-
// The active profile
|
|
1780
|
-
//
|
|
1514
|
+
// The active profile wins the chain but is silent on temperature, so the
|
|
1515
|
+
// deliberate call-site value survives.
|
|
1781
1516
|
expect(resolved.model).toBe("claude-sonnet-4-7");
|
|
1782
1517
|
expect(resolved.temperature).toBe(0.5);
|
|
1783
1518
|
});
|
|
1784
1519
|
|
|
1785
|
-
test("mainAgent:
|
|
1520
|
+
test("mainAgent: an explicit call-site temperature tweak applies over the active profile's", () => {
|
|
1786
1521
|
const llm = LLMSchema.parse({
|
|
1787
|
-
|
|
1788
|
-
|
|
1522
|
+
profiles: {
|
|
1523
|
+
active: {
|
|
1524
|
+
provider: "anthropic",
|
|
1525
|
+
model: "claude-sonnet-4-7",
|
|
1526
|
+
temperature: 0.2,
|
|
1527
|
+
},
|
|
1528
|
+
},
|
|
1789
1529
|
callSites: { mainAgent: { temperature: 0.5 } },
|
|
1790
1530
|
activeProfile: "active",
|
|
1791
1531
|
});
|
|
1792
1532
|
const resolved = resolveCallSiteConfig("mainAgent", llm);
|
|
1793
|
-
//
|
|
1794
|
-
// its explicit temperature wins.
|
|
1795
|
-
expect(resolved.temperature).toBe(0.
|
|
1533
|
+
// The call-site tweak is the last composition layer on every call site,
|
|
1534
|
+
// so its explicit temperature wins over the winner's.
|
|
1535
|
+
expect(resolved.temperature).toBe(0.5);
|
|
1796
1536
|
});
|
|
1797
1537
|
});
|
|
1798
1538
|
|
|
1799
1539
|
describe("resolveCallSiteConfig — workflowLeaf default", () => {
|
|
1800
|
-
test("
|
|
1540
|
+
test("anchors on the balanced intent through the default provider rather than pinning cost-optimized", () => {
|
|
1801
1541
|
const llm = LLMSchema.parse({
|
|
1802
|
-
default: fullDefault,
|
|
1803
1542
|
profiles: {
|
|
1804
1543
|
"cost-optimized": {
|
|
1544
|
+
source: "user",
|
|
1805
1545
|
provider: "anthropic",
|
|
1806
1546
|
model: "claude-haiku-4-5-20251001",
|
|
1807
1547
|
},
|
|
1808
1548
|
},
|
|
1549
|
+
defaultProvider: { provider: "anthropic" },
|
|
1809
1550
|
});
|
|
1810
1551
|
const resolved = resolveCallSiteConfig("workflowLeaf", llm);
|
|
1811
|
-
// No pinned profile → the model comes from
|
|
1812
|
-
// `cost-optimized` profile
|
|
1813
|
-
expect(resolved.model).toBe("
|
|
1552
|
+
// No pinned profile → the model comes from the balanced-intent anchor
|
|
1553
|
+
// through the default provider, NOT the `cost-optimized` profile.
|
|
1554
|
+
expect(resolved.model).toBe(resolveModelIntent("anthropic", "balanced"));
|
|
1555
|
+
expect(resolved.model).not.toBe("claude-haiku-4-5-20251001");
|
|
1814
1556
|
// Call-site tuning still applies.
|
|
1815
1557
|
expect(resolved.effort).toBe("low");
|
|
1816
1558
|
expect(resolved.thinking?.enabled).toBe(false);
|
|
@@ -1820,7 +1562,6 @@ describe("resolveCallSiteConfig — workflowLeaf default", () => {
|
|
|
1820
1562
|
|
|
1821
1563
|
test("honors an explicit workflowLeaf call-site override", () => {
|
|
1822
1564
|
const llm = LLMSchema.parse({
|
|
1823
|
-
default: fullDefault,
|
|
1824
1565
|
profiles: {
|
|
1825
1566
|
cheap: { provider: "anthropic", model: "claude-haiku-4-5-20251001" },
|
|
1826
1567
|
},
|
|
@@ -1833,7 +1574,6 @@ describe("resolveCallSiteConfig — workflowLeaf default", () => {
|
|
|
1833
1574
|
|
|
1834
1575
|
test("honors a per-call override profile (an explicit per-leaf profile)", () => {
|
|
1835
1576
|
const llm = LLMSchema.parse({
|
|
1836
|
-
default: fullDefault,
|
|
1837
1577
|
profiles: {
|
|
1838
1578
|
fancy: { provider: "anthropic", model: "claude-sonnet-4-7" },
|
|
1839
1579
|
},
|