@vellumai/assistant 0.6.4 → 0.6.5
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/.prettierignore +5 -0
- package/ARCHITECTURE.md +32 -36
- package/Dockerfile +12 -0
- package/README.md +3 -4
- package/bun.lock +8 -3
- package/docs/architecture/integrations.md +1 -20
- package/docs/architecture/security.md +16 -16
- package/docs/error-handling.md +111 -0
- package/docs/skills.md +10 -10
- package/docs/stt-provider-onboarding.md +2 -1
- package/knip.json +9 -2
- package/node_modules/@vellumai/ces-contracts/package.json +2 -1
- package/node_modules/@vellumai/ces-contracts/src/__tests__/trust-rules.test.ts +471 -0
- package/node_modules/@vellumai/ces-contracts/src/trust-rules.ts +398 -4
- package/node_modules/@vellumai/credential-storage/bun.lock +2 -2
- package/node_modules/@vellumai/credential-storage/package.json +2 -2
- package/node_modules/@vellumai/credential-storage/src/oauth-runtime.ts +20 -2
- package/node_modules/@vellumai/egress-proxy/bun.lock +2 -2
- package/node_modules/@vellumai/egress-proxy/package.json +2 -2
- package/openapi.yaml +123 -11
- package/package.json +6 -3
- package/scripts/generate-openapi.ts +50 -11
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +318 -0
- package/src/__tests__/agent-loop-sentry-hygiene.test.ts +137 -0
- package/src/__tests__/agent-loop.test.ts +112 -1
- package/src/__tests__/anthropic-error-formatting.test.ts +98 -0
- package/src/__tests__/anthropic-provider.test.ts +171 -2
- package/src/__tests__/approval-cascade.test.ts +31 -10
- package/src/__tests__/approval-routes-http.test.ts +134 -10
- package/src/__tests__/assistant-attachments.test.ts +44 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +29 -0
- package/src/__tests__/browser-fill-credential.test.ts +1 -1
- package/src/__tests__/browser-identifier-parity-guard.test.ts +53 -0
- package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +23 -33
- package/src/__tests__/browser-skill-endstate.test.ts +51 -182
- package/src/__tests__/btw-routes.test.ts +47 -1
- package/src/__tests__/call-controller.test.ts +1 -2
- package/src/__tests__/call-site-routing-provider.test.ts +214 -0
- package/src/__tests__/catalog-cache.test.ts +27 -4
- package/src/__tests__/channel-approval-routes.test.ts +4 -4
- package/src/__tests__/channel-reply-delivery.test.ts +300 -2
- package/src/__tests__/checker.test.ts +428 -501
- package/src/__tests__/cli-command-risk-guard.test.ts +30 -33
- package/src/__tests__/compaction-circuit-breaker.test.ts +336 -0
- package/src/__tests__/compaction.benchmark.test.ts +1 -1
- package/src/__tests__/config-analysis.test.ts +11 -28
- package/src/__tests__/config-loader-backfill.test.ts +174 -0
- package/src/__tests__/config-loader-corrupt.test.ts +183 -0
- package/src/__tests__/config-loader-quarantine-bulletin.test.ts +202 -0
- package/src/__tests__/config-schema-cmd.test.ts +11 -5
- package/src/__tests__/config-schema.test.ts +427 -114
- package/src/__tests__/config-watcher.test.ts +2 -2
- package/src/__tests__/contact-store-user-file.test.ts +72 -73
- package/src/__tests__/contacts-write.test.ts +4 -4
- package/src/__tests__/context-token-estimator.test.ts +191 -1
- package/src/__tests__/context-window-manager.test.ts +530 -2
- package/src/__tests__/conversation-abort-tool-results.test.ts +30 -16
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +61 -17
- package/src/__tests__/conversation-agent-loop.test.ts +412 -82
- package/src/__tests__/conversation-attachments.test.ts +1 -1
- package/src/__tests__/conversation-confirmation-signals.test.ts +30 -9
- package/src/__tests__/conversation-error.test.ts +37 -6
- package/src/__tests__/conversation-history-web-search.test.ts +6 -0
- package/src/__tests__/conversation-init.benchmark.test.ts +36 -0
- package/src/__tests__/conversation-lifecycle.test.ts +336 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +27 -10
- package/src/__tests__/conversation-pre-run-repair.test.ts +30 -16
- package/src/__tests__/conversation-process-callsite.test.ts +306 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +30 -16
- package/src/__tests__/conversation-queue.test.ts +41 -26
- package/src/__tests__/conversation-routes-disk-view.test.ts +29 -1
- package/src/__tests__/conversation-routes-slash-commands.test.ts +31 -3
- package/src/__tests__/conversation-runtime-assembly.test.ts +2735 -55
- package/src/__tests__/conversation-runtime-workspace.test.ts +12 -12
- package/src/__tests__/conversation-skill-tools.test.ts +12 -146
- package/src/__tests__/conversation-slash-queue.test.ts +34 -19
- package/src/__tests__/conversation-slash-unknown.test.ts +30 -16
- package/src/__tests__/conversation-speed-override.test.ts +30 -11
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +1035 -0
- package/src/__tests__/conversation-surfaces-standalone.test.ts +630 -0
- package/src/__tests__/conversation-title-service.test.ts +2 -2
- package/src/__tests__/conversation-tool-setup-batch-authorized.test.ts +1 -1
- package/src/__tests__/conversation-unread-route.test.ts +2 -2
- package/src/__tests__/conversation-usage.test.ts +3 -1
- package/src/__tests__/conversation-workspace-cache-state.test.ts +31 -10
- package/src/__tests__/conversation-workspace-injection.test.ts +43 -15
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +44 -16
- package/src/__tests__/credential-broker-browser-fill.test.ts +110 -0
- package/src/__tests__/credential-security-invariants.test.ts +3 -0
- package/src/__tests__/credential-storage-oauth-compat.test.ts +18 -0
- package/src/__tests__/credential-storage-static-compat.test.ts +28 -0
- package/src/__tests__/credential-vault-unit.test.ts +135 -19
- package/src/__tests__/credentials-cli.test.ts +1 -9
- package/src/__tests__/cross-provider-web-search.test.ts +84 -0
- package/src/__tests__/daemon-server-persist-and-process-callsite.test.ts +92 -0
- package/src/__tests__/delete-propagation.test.ts +437 -0
- package/src/__tests__/dm-backfill.test.ts +417 -0
- package/src/__tests__/dm-persistence.test.ts +227 -0
- package/src/__tests__/edit-propagation.test.ts +280 -0
- package/src/__tests__/ephemeral-permissions.test.ts +93 -3
- package/src/__tests__/estimator-calibration-integration.test.ts +208 -0
- package/src/__tests__/estimator-calibration.test.ts +213 -0
- package/src/__tests__/extension-id-sync-guard.test.ts +26 -7
- package/src/__tests__/file-write-tool.test.ts +151 -1
- package/src/__tests__/filing-service.test.ts +255 -0
- package/src/__tests__/gemini-provider.test.ts +0 -3
- package/src/__tests__/guardian-grant-minting.test.ts +8 -0
- package/src/__tests__/headless-browser-interactions.test.ts +1 -1
- package/src/__tests__/heartbeat-service.test.ts +96 -15
- package/src/__tests__/host-shell-tool.test.ts +124 -18
- package/src/__tests__/http-user-message-parity.test.ts +29 -1
- package/src/__tests__/inbound-slack-persistence.test.ts +340 -0
- package/src/__tests__/intent-routing.test.ts +1 -40
- package/src/__tests__/llm-catalog-parity.test.ts +174 -0
- package/src/__tests__/llm-context-normalization.test.ts +121 -0
- package/src/__tests__/llm-resolver.test.ts +214 -0
- package/src/__tests__/llm-schema.test.ts +223 -0
- package/src/__tests__/managed-proxy-context.test.ts +6 -2
- package/src/__tests__/messaging-skill-split.test.ts +3 -34
- package/src/__tests__/migration-import-from-url.test.ts +684 -0
- package/src/__tests__/model-intents.test.ts +9 -83
- package/src/__tests__/notification-decision-fallback.test.ts +0 -10
- package/src/__tests__/notification-decision-identity.test.ts +0 -9
- package/src/__tests__/notification-decision-recipient-context.test.ts +0 -9
- package/src/__tests__/oauth-store.test.ts +10 -7
- package/src/__tests__/oauth2-gateway-transport.test.ts +8 -3
- package/src/__tests__/oauth2-refresh-retry.test.ts +279 -0
- package/src/__tests__/openai-provider.test.ts +7 -0
- package/src/__tests__/openai-responses-provider.test.ts +396 -0
- package/src/__tests__/openrouter-provider-only.test.ts +135 -0
- package/src/__tests__/outbound-slack-persistence.test.ts +293 -0
- package/src/__tests__/permission-checker-host-gate.test.ts +1 -1
- package/src/__tests__/permission-mode.test.ts +16 -0
- package/src/__tests__/permission-types.test.ts +0 -1
- package/src/__tests__/persona-resolver.test.ts +13 -13
- package/src/__tests__/pkb-autoinject.test.ts +37 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +1 -1
- package/src/__tests__/pricing.test.ts +50 -3
- package/src/__tests__/profiler-routes.test.ts +1 -1
- package/src/__tests__/provider-commit-message-generator.test.ts +14 -84
- package/src/__tests__/provider-env-vars-scope.test.ts +52 -0
- package/src/__tests__/provider-error-scenarios.test.ts +135 -6
- package/src/__tests__/provider-managed-proxy-integration.test.ts +42 -11
- package/src/__tests__/provider-registry-ollama.test.ts +1 -2
- package/src/__tests__/proxy-approval-callback.test.ts +0 -1
- package/src/__tests__/reaction-persistence.test.ts +560 -0
- package/src/__tests__/relay-server.test.ts +1 -1
- package/src/__tests__/require-fresh-approval.test.ts +1 -1
- package/src/__tests__/retry-openrouter-only-normalization.test.ts +136 -0
- package/src/__tests__/retry-thinking-tool-choice.test.ts +226 -0
- package/src/__tests__/risk-classifier-parity.test.ts +230 -0
- package/src/__tests__/sanitize-config-for-transfer.test.ts +78 -1
- package/src/__tests__/secret-ingress-http.test.ts +28 -0
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +125 -0
- package/src/__tests__/secret-routes-managed-proxy.test.ts +2 -3
- package/src/__tests__/secret-scanner-executor.test.ts +1 -1
- package/src/__tests__/send-endpoint-busy.test.ts +29 -1
- package/src/__tests__/server-history-render.test.ts +31 -0
- package/src/__tests__/shell-parser-property.test.ts +13 -13
- package/src/__tests__/skill-cache-store.test.ts +182 -0
- package/src/__tests__/skills.test.ts +19 -33
- package/src/__tests__/slack-app-setup-skill-regression.test.ts +3 -1
- package/src/__tests__/slack-skill.test.ts +3 -8
- package/src/__tests__/starter-bundle.test.ts +35 -0
- package/src/__tests__/subagent-call-site-routing.test.ts +280 -0
- package/src/__tests__/suggestion-routes.test.ts +160 -3
- package/src/__tests__/system-prompt.test.ts +22 -35
- package/src/__tests__/task-runner.test.ts +3 -1
- package/src/__tests__/tcc-sandbox-deny.test.ts +198 -0
- package/src/__tests__/terminal-tools.test.ts +8 -0
- package/src/__tests__/test-support/browser-skill-harness.ts +2 -52
- package/src/__tests__/thread-backfill.test.ts +941 -0
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -2
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +2 -2
- package/src/__tests__/tool-executor.test.ts +60 -94
- package/src/__tests__/trust-store.test.ts +442 -109
- package/src/__tests__/update-bulletin-job.test.ts +389 -0
- package/src/__tests__/usage-cache-backfill-migration.test.ts +3 -1
- package/src/__tests__/verification-control-plane-policy.test.ts +1 -22
- package/src/__tests__/voice-session-bridge.test.ts +39 -0
- package/src/__tests__/volume-security-guard.test.ts +3 -2
- package/src/__tests__/web-search-history.test.ts +337 -0
- package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +343 -0
- package/src/__tests__/workspace-migration-043-release-notes-latex-rendering.test.ts +202 -0
- package/src/__tests__/workspace-migration-045-release-notes-meet-avatar.test.ts +210 -0
- package/src/__tests__/workspace-migration-drop-user-md.test.ts +11 -11
- package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +841 -0
- package/src/__tests__/workspace-policy.test.ts +1 -13
- package/src/acp/client-handler.ts +1 -2
- package/src/agent/loop.ts +209 -17
- package/src/avatar/resvg-lazy.test.ts +136 -0
- package/src/avatar/resvg-lazy.ts +82 -9
- package/src/avatar/traits-png-sync.ts +21 -1
- package/src/browser/__tests__/operations.test.ts +163 -0
- package/src/browser/identifiers.ts +51 -0
- package/src/browser/operations.ts +660 -0
- package/src/browser/types.ts +81 -0
- package/src/calls/guardian-question-copy.ts +2 -2
- package/src/calls/telephony-stt-routing.ts +1 -1
- package/src/calls/voice-session-bridge.ts +1 -0
- package/src/cli/AGENTS.md +1 -1
- package/src/cli/commands/__tests__/attachment.test.ts +438 -0
- package/src/cli/commands/__tests__/browser.test.ts +554 -0
- package/src/cli/commands/__tests__/cache.test.ts +623 -0
- package/src/cli/commands/__tests__/email-list.test.ts +6 -0
- package/src/cli/commands/__tests__/email-send.test.ts +93 -1
- package/src/cli/commands/__tests__/image-generation.test.ts +666 -0
- package/src/cli/commands/__tests__/inference-send.test.ts +451 -0
- package/src/cli/commands/__tests__/stt-transcribe.test.ts +454 -0
- package/src/cli/commands/__tests__/task.test.ts +913 -0
- package/src/cli/commands/__tests__/tts-synthesize.test.ts +594 -0
- package/src/cli/commands/__tests__/ui-confirm.test.ts +650 -0
- package/src/cli/commands/__tests__/ui.test.ts +1215 -0
- package/src/cli/commands/__tests__/watchers.test.ts +716 -0
- package/src/cli/commands/attachment.ts +182 -0
- package/src/cli/commands/browser.ts +350 -0
- package/src/cli/commands/cache.ts +341 -0
- package/src/cli/commands/completions.ts +0 -3
- package/src/cli/commands/config.ts +6 -6
- package/src/cli/commands/conversations-import.ts +347 -0
- package/src/cli/commands/conversations.ts +14 -1
- package/src/cli/commands/email.ts +234 -194
- package/src/cli/commands/image-generation.ts +300 -0
- package/src/cli/commands/inference.ts +200 -0
- package/src/cli/commands/memory.ts +127 -17
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -1
- package/src/cli/commands/platform/__tests__/connect.test.ts +0 -1
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +0 -1
- package/src/cli/commands/platform/__tests__/status.test.ts +0 -1
- package/src/cli/commands/stt.ts +339 -0
- package/src/cli/commands/task.ts +795 -0
- package/src/cli/commands/trust.ts +50 -19
- package/src/cli/commands/tts.ts +273 -0
- package/src/cli/commands/ui.ts +670 -0
- package/src/cli/commands/watchers.ts +509 -0
- package/src/cli/lib/daemon-credential-client.ts +0 -19
- package/src/cli/program.ts +23 -4
- package/src/cli.ts +0 -37
- package/src/config/bundled-skills/conversations/tools/rename-conversation.ts +23 -1
- package/src/config/bundled-skills/media-processing/services/reduce.ts +1 -1
- package/src/config/bundled-skills/messaging/SKILL.md +2 -2
- package/src/config/bundled-skills/messaging/TOOLS.json +4 -0
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +8 -1
- package/src/config/bundled-skills/messaging/tools/messaging-read.ts +15 -1
- package/src/config/bundled-skills/messaging/tools/messaging-search.ts +21 -1
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +11 -12
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +9 -8
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-tool-registry.ts +0 -175
- package/src/config/env.ts +7 -2
- package/src/config/feature-flag-registry.json +25 -9
- package/src/config/llm-resolver.ts +128 -0
- package/src/config/loader.ts +194 -10
- package/src/config/raw-config-utils.ts +30 -2
- package/src/config/sanitize-for-transfer.ts +35 -0
- package/src/config/schema.ts +30 -41
- package/src/config/schemas/analysis.ts +3 -22
- package/src/config/schemas/calls.ts +0 -4
- package/src/config/schemas/filing.ts +2 -7
- package/src/config/schemas/heartbeat.ts +0 -5
- package/src/config/schemas/inference.ts +3 -23
- package/src/config/schemas/llm.ts +318 -0
- package/src/config/schemas/memory-processing.ts +1 -9
- package/src/config/schemas/notifications.ts +4 -11
- package/src/config/schemas/platform.ts +3 -9
- package/src/config/schemas/security.ts +33 -0
- package/src/config/schemas/services.ts +9 -4
- package/src/config/schemas/stt.ts +1 -0
- package/src/config/schemas/tts.ts +53 -0
- package/src/config/schemas/updates.ts +1 -1
- package/src/config/schemas/workspace-git.ts +3 -40
- package/src/config/skills.ts +2 -2
- package/src/context/__tests__/compact-prompt.test.ts +45 -0
- package/src/context/__tests__/microcompact.test.ts +805 -0
- package/src/context/estimator-calibration.ts +136 -0
- package/src/context/microcompact.ts +443 -0
- package/src/context/prompts/compact.md +12 -0
- package/src/context/token-estimator.ts +61 -3
- package/src/context/window-manager.ts +229 -25
- package/src/credential-execution/approval-bridge.ts +0 -1
- package/src/credential-execution/executable-discovery.ts +19 -8
- package/src/credential-execution/process-manager.test.ts +109 -0
- package/src/credential-execution/process-manager.ts +65 -2
- package/src/daemon/approval-generators.ts +29 -4
- package/src/daemon/assistant-attachments.ts +24 -13
- package/src/daemon/classifier.ts +2 -2
- package/src/daemon/config-watcher.ts +0 -1
- package/src/daemon/context-overflow-reducer.ts +4 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +79 -12
- package/src/daemon/conversation-agent-loop.ts +462 -80
- package/src/daemon/conversation-attachments.ts +2 -6
- package/src/daemon/conversation-error.ts +36 -1
- package/src/daemon/conversation-lifecycle.ts +30 -6
- package/src/daemon/conversation-messaging.ts +73 -4
- package/src/daemon/conversation-process.ts +10 -4
- package/src/daemon/conversation-queue-manager.ts +3 -0
- package/src/daemon/conversation-runtime-assembly.ts +760 -29
- package/src/daemon/conversation-slash.ts +2 -2
- package/src/daemon/conversation-surfaces.ts +389 -1
- package/src/daemon/conversation-tool-setup.ts +10 -5
- package/src/daemon/conversation-usage.ts +1 -1
- package/src/daemon/conversation.ts +118 -30
- package/src/daemon/external-skills-bootstrap.ts +41 -0
- package/src/daemon/guardian-action-generators.ts +34 -14
- package/src/daemon/handlers/config-model.test.ts +86 -0
- package/src/daemon/handlers/config-model.ts +54 -12
- package/src/daemon/handlers/conversations.ts +9 -2
- package/src/daemon/handlers/shared.ts +39 -11
- package/src/daemon/handlers/skills.ts +2 -2
- package/src/daemon/handlers/slack-channel-oauth-install.ts +197 -0
- package/src/daemon/lifecycle.ts +76 -14
- package/src/daemon/message-types/conversations.ts +14 -0
- package/src/daemon/message-types/messages.ts +9 -1
- package/src/daemon/message-types/trust.ts +0 -2
- package/src/daemon/parse-actual-tokens-from-error.test.ts +57 -1
- package/src/daemon/parse-actual-tokens-from-error.ts +66 -0
- package/src/daemon/pkb-context-tracker.test.ts +169 -0
- package/src/daemon/pkb-context-tracker.ts +125 -0
- package/src/daemon/pkb-reminder-builder.test.ts +70 -0
- package/src/daemon/pkb-reminder-builder.ts +31 -0
- package/src/daemon/providers-setup.ts +6 -0
- package/src/daemon/server.ts +117 -9
- package/src/daemon/tool-side-effects.ts +0 -9
- package/src/daemon/watch-handler.ts +4 -4
- package/src/daemon/web-search-history.ts +126 -0
- package/src/events/domain-events.ts +0 -1
- package/src/filing/filing-service.ts +9 -10
- package/src/heartbeat/heartbeat-service.ts +76 -28
- package/src/home/__tests__/feed-scheduler.test.ts +39 -11
- package/src/home/__tests__/rollup-producer.test.ts +44 -0
- package/src/home/assistant-feed-authoring.ts +4 -0
- package/src/home/emit-feed-event.ts +4 -0
- package/src/home/feed-scheduler.ts +20 -4
- package/src/home/feed-types.ts +56 -2
- package/src/home/relationship-state-writer.ts +2 -2
- package/src/home/rollup-producer.ts +34 -5
- package/src/home/suggested-prompts.ts +101 -0
- package/src/ipc/__tests__/attachment-ipc.test.ts +213 -0
- package/src/ipc/__tests__/browser-ipc.test.ts +339 -0
- package/src/ipc/__tests__/cache-ipc.test.ts +266 -0
- package/src/ipc/__tests__/socket-path.test.ts +73 -0
- package/src/ipc/__tests__/task-ipc.test.ts +577 -0
- package/src/ipc/__tests__/ui-request-route.test.ts +495 -0
- package/src/ipc/__tests__/watcher-ipc.test.ts +295 -0
- package/src/ipc/cli-client.ts +2 -1
- package/src/ipc/cli-server.ts +26 -8
- package/src/ipc/gateway-client.ts +4 -4
- package/src/ipc/routes/attachment.ts +114 -0
- package/src/ipc/routes/browser-context.ts +61 -0
- package/src/ipc/routes/browser.ts +96 -0
- package/src/ipc/routes/cache.ts +96 -0
- package/src/ipc/routes/index.ts +17 -1
- package/src/ipc/routes/task-queue.ts +226 -0
- package/src/ipc/routes/task.ts +173 -0
- package/src/ipc/routes/ui-request.ts +50 -0
- package/src/ipc/routes/watcher.ts +203 -0
- package/src/ipc/socket-path.ts +100 -0
- package/src/memory/__tests__/conversation-analyze-job.test.ts +9 -8
- package/src/memory/__tests__/conversation-group-migration.test.ts +99 -0
- package/src/memory/admin.ts +18 -0
- package/src/memory/conversation-analyze-job.ts +14 -13
- package/src/memory/conversation-attention-store.ts +13 -6
- package/src/memory/conversation-crud.ts +103 -3
- package/src/memory/conversation-group-migration.ts +38 -6
- package/src/memory/conversation-title-service.ts +7 -4
- package/src/memory/db-init.ts +2 -0
- package/src/memory/embedding-backend.ts +1 -1
- package/src/memory/graph/compaction.ts +299 -0
- package/src/memory/graph/consolidation.ts +4 -4
- package/src/memory/graph/conversation-graph-memory.ts +89 -29
- package/src/memory/graph/extraction.test.ts +272 -2
- package/src/memory/graph/extraction.ts +173 -51
- package/src/memory/graph/graph-search.test.ts +92 -0
- package/src/memory/graph/graph-search.ts +4 -1
- package/src/memory/graph/narrative.ts +2 -2
- package/src/memory/graph/pattern-scan.ts +2 -2
- package/src/memory/graph/retriever.test.ts +459 -0
- package/src/memory/graph/retriever.ts +230 -48
- package/src/memory/graph/store.ts +41 -0
- package/src/memory/graph/tool-handlers.ts +27 -0
- package/src/memory/graph/tools.ts +6 -1
- package/src/memory/indexer.ts +5 -5
- package/src/memory/job-handlers/conversation-starters.ts +23 -20
- package/src/memory/job-handlers/summarization.ts +2 -2
- package/src/memory/job-utils.ts +7 -1
- package/src/memory/jobs/embed-pkb-file.test.ts +168 -0
- package/src/memory/jobs/embed-pkb-file.ts +54 -0
- package/src/memory/jobs-store.ts +44 -3
- package/src/memory/jobs-worker.ts +4 -0
- package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +1 -1
- package/src/memory/migrations/220-normalize-user-file-by-principal.ts +2 -2
- package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +82 -0
- package/src/memory/migrations/index.ts +1 -0
- package/src/memory/pkb/pkb-index.test.ts +368 -0
- package/src/memory/pkb/pkb-index.ts +255 -0
- package/src/memory/pkb/pkb-reconcile.test.ts +251 -0
- package/src/memory/pkb/pkb-reconcile.ts +148 -0
- package/src/memory/pkb/pkb-search.test.ts +438 -0
- package/src/memory/pkb/pkb-search.ts +137 -0
- package/src/memory/pkb/types.ts +53 -0
- package/src/memory/qdrant-client.ts +122 -1
- package/src/memory/slack-thread-store.ts +37 -0
- package/src/messaging/providers/gmail/adapter.ts +6 -16
- package/src/messaging/providers/gmail/client.ts +22 -0
- package/src/messaging/providers/gmail/types.ts +7 -0
- package/src/messaging/providers/slack/adapter.ts +14 -2
- package/src/messaging/providers/slack/backfill.test.ts +257 -0
- package/src/messaging/providers/slack/backfill.ts +101 -0
- package/src/messaging/providers/slack/message-metadata.test.ts +316 -0
- package/src/messaging/providers/slack/message-metadata.ts +123 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +1373 -0
- package/src/messaging/providers/slack/render-transcript.ts +443 -0
- package/src/messaging/style-analyzer.ts +5 -2
- package/src/notifications/README.md +9 -5
- package/src/notifications/decision-engine.ts +3 -9
- package/src/notifications/preference-extractor.ts +2 -6
- package/src/oauth/oauth-store.ts +1 -0
- package/src/oauth/platform-connection.test.ts +47 -0
- package/src/oauth/platform-connection.ts +15 -5
- package/src/oauth/seed-providers.ts +4 -2
- package/src/permissions/approval-policy.test.ts +948 -0
- package/src/permissions/approval-policy.ts +257 -0
- package/src/permissions/bash-risk-classifier.test.ts +1208 -0
- package/src/permissions/bash-risk-classifier.ts +707 -0
- package/src/permissions/checker.ts +217 -708
- package/src/permissions/command-registry.test.ts +535 -0
- package/src/permissions/command-registry.ts +825 -0
- package/src/permissions/defaults.ts +26 -78
- package/src/permissions/file-risk-classifier.test.ts +535 -0
- package/src/permissions/file-risk-classifier.ts +274 -0
- package/src/permissions/risk-types.ts +205 -0
- package/src/permissions/secret-prompter.ts +53 -2
- package/src/permissions/skill-risk-classifier.test.ts +311 -0
- package/src/permissions/skill-risk-classifier.ts +214 -0
- package/src/permissions/trust-client.ts +52 -25
- package/src/permissions/trust-store-interface.ts +1 -6
- package/src/permissions/trust-store.ts +161 -62
- package/src/permissions/types.ts +23 -14
- package/src/permissions/web-risk-classifier.test.ts +170 -0
- package/src/permissions/web-risk-classifier.ts +89 -0
- package/src/permissions/workspace-policy.ts +1 -16
- package/src/platform/client.ts +19 -1
- package/src/prompts/persona-resolver.ts +3 -3
- package/src/prompts/system-prompt.ts +19 -20
- package/src/prompts/templates/SOUL.md +2 -2
- package/src/prompts/update-bulletin-job.ts +190 -0
- package/src/providers/__tests__/context-overflow-error.test.ts +328 -0
- package/src/providers/__tests__/provider-env-vars.test.ts +102 -0
- package/src/providers/__tests__/retry-callsite.test.ts +424 -0
- package/src/providers/anthropic/client.ts +183 -14
- package/src/providers/call-site-routing.ts +71 -0
- package/src/providers/gemini/client.ts +65 -2
- package/src/providers/managed-proxy/constants.ts +2 -1
- package/src/providers/model-catalog.ts +501 -33
- package/src/providers/model-intents.ts +4 -4
- package/src/providers/openai/chat-completions-provider.ts +57 -1
- package/src/providers/openai/responses-provider.ts +86 -9
- package/src/providers/openrouter/client.ts +76 -9
- package/src/providers/provider-env-vars.ts +56 -0
- package/src/providers/provider-send-message.ts +22 -5
- package/src/providers/ratelimit.ts +4 -0
- package/src/providers/registry.ts +19 -8
- package/src/providers/retry.ts +174 -39
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +55 -0
- package/src/providers/speech-to-text/google-gemini-live-stream.ts +4 -4
- package/src/providers/speech-to-text/provider-catalog.ts +17 -0
- package/src/providers/speech-to-text/resolve.ts +7 -0
- package/src/providers/speech-to-text/xai-realtime.test.ts +578 -0
- package/src/providers/speech-to-text/xai-realtime.ts +796 -0
- package/src/providers/speech-to-text/xai.test.ts +155 -0
- package/src/providers/speech-to-text/xai.ts +97 -0
- package/src/providers/types.ts +93 -3
- package/src/runtime/AGENTS.md +2 -2
- package/src/runtime/__tests__/agent-wake.test.ts +43 -2
- package/src/runtime/__tests__/interactive-ui.test.ts +673 -0
- package/src/runtime/agent-wake.ts +63 -22
- package/src/runtime/auth/route-policy.ts +4 -0
- package/src/runtime/btw-sidechain.ts +13 -3
- package/src/runtime/channel-reply-delivery.ts +106 -2
- package/src/runtime/decision-token.ts +116 -0
- package/src/runtime/gateway-client.ts +2 -2
- package/src/runtime/http-router.ts +32 -0
- package/src/runtime/http-server.ts +52 -1
- package/src/runtime/http-types.ts +23 -1
- package/src/runtime/interactive-ui.ts +362 -0
- package/src/runtime/invite-instruction-generator.ts +2 -2
- package/src/runtime/migrations/__tests__/gcs-signed-url.test.ts +176 -0
- package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +390 -0
- package/src/runtime/migrations/__tests__/vbundle-metadata-merge.test.ts +221 -0
- package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +1540 -0
- package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +453 -0
- package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +222 -0
- package/src/runtime/migrations/gcs-signed-url.ts +162 -0
- package/src/runtime/migrations/vbundle-importer.ts +154 -9
- package/src/runtime/migrations/vbundle-metadata-merge.ts +124 -0
- package/src/runtime/migrations/vbundle-streaming-importer.ts +2522 -0
- package/src/runtime/migrations/vbundle-streaming-validator.ts +244 -0
- package/src/runtime/migrations/vbundle-tar-stream.ts +217 -0
- package/src/runtime/migrations/vbundle-validator.ts +15 -6
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +111 -0
- package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +114 -75
- package/src/runtime/routes/__tests__/migration-vellum-metadata-reconcile.test.ts +246 -0
- package/src/runtime/routes/approval-prompt-ts-tracker.ts +58 -0
- package/src/runtime/routes/approval-routes.ts +12 -17
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +9 -0
- package/src/runtime/routes/avatar-routes.ts +20 -4
- package/src/runtime/routes/btw-routes.ts +1 -4
- package/src/runtime/routes/conversation-management-routes.ts +20 -2
- package/src/runtime/routes/conversation-routes.ts +133 -27
- package/src/runtime/routes/debug-routes.ts +1 -1
- package/src/runtime/routes/diagnostics-routes.ts +6 -4
- package/src/runtime/routes/events-routes.ts +16 -0
- package/src/runtime/routes/guardian-approval-interception.ts +33 -3
- package/src/runtime/routes/guardian-approval-prompt.ts +13 -3
- package/src/runtime/routes/home-feed-routes.ts +120 -2
- package/src/runtime/routes/inbound-message-handler.ts +912 -2
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +113 -2
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +61 -3
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +129 -6
- package/src/runtime/routes/integrations/slack/channel.ts +25 -3
- package/src/runtime/routes/llm-context-normalization.ts +23 -1
- package/src/runtime/routes/migration-routes.ts +720 -124
- package/src/runtime/routes/settings-routes.ts +4 -2
- package/src/runtime/routes/trust-rules-routes.ts +30 -14
- package/src/runtime/routes/work-items-routes.test.ts +1 -1
- package/src/runtime/routes/work-items-routes.ts +3 -2
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +25 -43
- package/src/runtime/services/analyze-conversation.ts +12 -16
- package/src/runtime/skill-route-registry.ts +28 -6
- package/src/schedule/scheduler.ts +8 -0
- package/src/security/__tests__/provider-key-env-fallback.test.ts +119 -0
- package/src/security/__tests__/untrusted-content.test.ts +109 -0
- package/src/security/oauth2.ts +98 -35
- package/src/security/secure-keys.ts +7 -8
- package/src/security/token-manager.ts +27 -13
- package/src/security/untrusted-content.ts +102 -0
- package/src/skills/catalog-cache.ts +26 -7
- package/src/skills/catalog-install.ts +31 -3
- package/src/skills/skill-cache-store.ts +97 -0
- package/src/stt/__tests__/daemon-batch-transcriber.test.ts +76 -0
- package/src/stt/daemon-batch-transcriber.ts +33 -0
- package/src/stt/stt-stream-session.ts +8 -1
- package/src/stt/types.ts +5 -1
- package/src/subagent/manager.ts +41 -13
- package/src/tasks/ephemeral-permissions.ts +9 -4
- package/src/telemetry/usage-telemetry-reporter.ts +27 -5
- package/src/tools/browser/__tests__/browser-status.test.ts +45 -2
- package/src/tools/browser/browser-execution.ts +65 -38
- package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +22 -0
- package/src/tools/credentials/tool-policy.ts +39 -5
- package/src/tools/credentials/vault.ts +9 -4
- package/src/tools/executor.ts +4 -0
- package/src/tools/filesystem/write.ts +52 -0
- package/src/tools/host-terminal/host-shell.ts +45 -5
- package/src/tools/memory/register.test.ts +185 -0
- package/src/tools/memory/register.ts +3 -1
- package/src/tools/network/web-fetch.ts +20 -10
- package/src/tools/network/web-search.ts +19 -4
- package/src/tools/permission-checker.ts +36 -15
- package/src/tools/policy-context.ts +25 -8
- package/src/tools/registry.ts +55 -3
- package/src/tools/side-effects.ts +0 -11
- package/src/tools/skills/execute.ts +2 -2
- package/src/tools/skills/sandbox-runner.ts +5 -2
- package/src/tools/terminal/backends/native.ts +51 -2
- package/src/tools/terminal/safe-env.ts +3 -2
- package/src/tools/terminal/shell.ts +1 -0
- package/src/tools/tool-manifest.ts +6 -21
- package/src/tools/types.ts +12 -3
- package/src/tools/verification-control-plane-policy.ts +1 -1
- package/src/tts/__tests__/provider-adapters.test.ts +240 -13
- package/src/tts/provider-catalog.ts +18 -0
- package/src/tts/providers/index.ts +2 -0
- package/src/tts/providers/xai-provider.ts +224 -0
- package/src/tts/types.ts +46 -0
- package/src/types/tar-stream.d.ts +66 -0
- package/src/util/json.ts +17 -0
- package/src/util/platform.ts +2 -2
- package/src/util/pricing.ts +15 -5
- package/src/watcher/engine.ts +1 -1
- package/src/watcher/providers/google-calendar.ts +134 -8
- package/src/watcher/providers/outlook-calendar.ts +42 -2
- package/src/workspace/git-service.ts +23 -4
- package/src/workspace/migrations/038-unify-llm-callsite-configs.ts +516 -0
- package/src/workspace/migrations/039-drop-legacy-llm-keys.ts +171 -0
- package/src/workspace/migrations/040-seed-latency-callsite-defaults.ts +154 -0
- package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +57 -0
- package/src/workspace/migrations/042-fix-backfill-google-gmail-settings-scope.ts +70 -0
- package/src/workspace/migrations/043-release-notes-latex-rendering.ts +75 -0
- package/src/workspace/migrations/044-bump-stale-provider-stream-timeout.ts +51 -0
- package/src/workspace/migrations/045-release-notes-meet-avatar.ts +130 -0
- package/src/workspace/migrations/AGENTS.md +1 -1
- package/src/workspace/migrations/registry.ts +16 -0
- package/src/workspace/provider-commit-message-generator.ts +19 -38
- package/src/__tests__/gmail-archive-fallback.test.ts +0 -193
- package/src/__tests__/gmail-archive-gate.test.ts +0 -246
- package/src/__tests__/gmail-preferences.test.ts +0 -117
- package/src/__tests__/outlook-attachments.test.ts +0 -301
- package/src/__tests__/outlook-automation-tools.test.ts +0 -425
- package/src/__tests__/outlook-categories.test.ts +0 -212
- package/src/__tests__/outlook-compose-tools.test.ts +0 -325
- package/src/__tests__/outlook-declutter-tools.test.ts +0 -585
- package/src/__tests__/outlook-follow-up.test.ts +0 -196
- package/src/__tests__/outlook-trash.test.ts +0 -77
- package/src/__tests__/outlook-unsubscribe.test.ts +0 -279
- package/src/__tests__/update-bulletin-format.test.ts +0 -181
- package/src/__tests__/update-bulletin-state.test.ts +0 -135
- package/src/__tests__/update-bulletin.test.ts +0 -478
- package/src/__tests__/update-template-contract.test.ts +0 -29
- package/src/cli/commands/doctor.ts +0 -341
- package/src/config/bundled-skills/browser/SKILL.md +0 -88
- package/src/config/bundled-skills/browser/TOOLS.json +0 -516
- package/src/config/bundled-skills/browser/tools/browser-attach.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-click.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-close.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-detach.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-extract.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-fill-credential.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-hover.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-navigate.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-press-key.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-screenshot.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-scroll.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-select-option.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-snapshot.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-status.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-type.ts +0 -12
- package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +0 -49
- package/src/config/bundled-skills/browser/tools/browser-wait-for.ts +0 -12
- package/src/config/bundled-skills/chatgpt-import/SKILL.md +0 -27
- package/src/config/bundled-skills/chatgpt-import/TOOLS.json +0 -27
- package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +0 -378
- package/src/config/bundled-skills/gmail/SKILL.md +0 -221
- package/src/config/bundled-skills/gmail/TOOLS.json +0 -588
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +0 -256
- package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +0 -112
- package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +0 -44
- package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +0 -81
- package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +0 -108
- package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +0 -146
- package/src/config/bundled-skills/gmail/tools/gmail-label.ts +0 -53
- package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +0 -347
- package/src/config/bundled-skills/gmail/tools/gmail-preferences-tool.ts +0 -59
- package/src/config/bundled-skills/gmail/tools/gmail-preferences.ts +0 -82
- package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +0 -26
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +0 -347
- package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +0 -29
- package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +0 -122
- package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +0 -67
- package/src/config/bundled-skills/gmail/tools/scan-result-store.ts +0 -100
- package/src/config/bundled-skills/gmail/tools/shared.ts +0 -47
- package/src/config/bundled-skills/google-calendar/SKILL.md +0 -51
- package/src/config/bundled-skills/google-calendar/TOOLS.json +0 -226
- package/src/config/bundled-skills/google-calendar/calendar-client.ts +0 -223
- package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +0 -27
- package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +0 -48
- package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +0 -19
- package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +0 -36
- package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +0 -58
- package/src/config/bundled-skills/google-calendar/tools/shared.ts +0 -17
- package/src/config/bundled-skills/google-calendar/types.ts +0 -97
- package/src/config/bundled-skills/outlook/SKILL.md +0 -196
- package/src/config/bundled-skills/outlook/TOOLS.json +0 -530
- package/src/config/bundled-skills/outlook/tools/outlook-attachments.ts +0 -85
- package/src/config/bundled-skills/outlook/tools/outlook-categories.ts +0 -77
- package/src/config/bundled-skills/outlook/tools/outlook-draft.ts +0 -84
- package/src/config/bundled-skills/outlook/tools/outlook-follow-up.ts +0 -94
- package/src/config/bundled-skills/outlook/tools/outlook-forward.ts +0 -49
- package/src/config/bundled-skills/outlook/tools/outlook-outreach-scan.ts +0 -237
- package/src/config/bundled-skills/outlook/tools/outlook-rules.ts +0 -161
- package/src/config/bundled-skills/outlook/tools/outlook-send-draft.ts +0 -32
- package/src/config/bundled-skills/outlook/tools/outlook-sender-digest.ts +0 -272
- package/src/config/bundled-skills/outlook/tools/outlook-trash.ts +0 -29
- package/src/config/bundled-skills/outlook/tools/outlook-unsubscribe.ts +0 -129
- package/src/config/bundled-skills/outlook/tools/outlook-vacation.ts +0 -87
- package/src/config/bundled-skills/outlook/tools/shared.ts +0 -20
- package/src/config/bundled-skills/outlook-calendar/SKILL.md +0 -51
- package/src/config/bundled-skills/outlook-calendar/TOOLS.json +0 -221
- package/src/config/bundled-skills/outlook-calendar/calendar-client.ts +0 -252
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-check-availability.ts +0 -53
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-create-event.ts +0 -74
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-get-event.ts +0 -18
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-list-events.ts +0 -46
- package/src/config/bundled-skills/outlook-calendar/tools/outlook-calendar-rsvp.ts +0 -36
- package/src/config/bundled-skills/outlook-calendar/tools/shared.ts +0 -17
- package/src/config/bundled-skills/outlook-calendar/types.ts +0 -120
- package/src/config/bundled-skills/slack/SKILL.md +0 -108
- package/src/config/bundled-skills/tasks/SKILL.md +0 -37
- package/src/config/bundled-skills/tasks/TOOLS.json +0 -353
- package/src/config/bundled-skills/tasks/icon.svg +0 -34
- package/src/config/bundled-skills/tasks/tools/task-delete.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-add.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-remove.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-show.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list-update.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-list.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-queue-run.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-run.ts +0 -12
- package/src/config/bundled-skills/tasks/tools/task-save.ts +0 -12
- package/src/config/bundled-skills/watcher/SKILL.md +0 -31
- package/src/config/bundled-skills/watcher/TOOLS.json +0 -167
- package/src/config/bundled-skills/watcher/tools/watcher-create.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-delete.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-digest.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-list.ts +0 -12
- package/src/config/bundled-skills/watcher/tools/watcher-update.ts +0 -12
- package/src/prompts/templates/UPDATES.md +0 -50
- package/src/prompts/update-bulletin-format.ts +0 -85
- package/src/prompts/update-bulletin-state.ts +0 -58
- package/src/prompts/update-bulletin-template-path.ts +0 -13
- package/src/prompts/update-bulletin.ts +0 -139
- package/src/shared/provider-env-vars.ts +0 -19
- package/src/tools/watcher/create.ts +0 -86
- package/src/tools/watcher/delete.ts +0 -36
- package/src/tools/watcher/digest.ts +0 -54
- package/src/tools/watcher/list.ts +0 -83
- package/src/tools/watcher/update.ts +0 -71
|
@@ -81,9 +81,11 @@ function writeConfig(obj: unknown): void {
|
|
|
81
81
|
describe("AssistantConfigSchema", () => {
|
|
82
82
|
test("parses empty object with full defaults", () => {
|
|
83
83
|
const result = AssistantConfigSchema.parse({});
|
|
84
|
-
|
|
85
|
-
|
|
84
|
+
// services.inference now carries only `mode`; provider/model live under
|
|
85
|
+
// llm.default.{provider,model} (see PR 19 of unify-llm-callsites).
|
|
86
86
|
expect(result.services.inference.mode).toBe("your-own");
|
|
87
|
+
expect(result.llm.default.provider).toBe("anthropic");
|
|
88
|
+
expect(result.llm.default.model).toBe("claude-opus-4-7");
|
|
87
89
|
expect(result.services["image-generation"].provider).toBe("gemini");
|
|
88
90
|
expect(result.services["image-generation"].model).toBe(
|
|
89
91
|
"gemini-3.1-flash-image-preview",
|
|
@@ -93,12 +95,12 @@ describe("AssistantConfigSchema", () => {
|
|
|
93
95
|
"inference-provider-native",
|
|
94
96
|
);
|
|
95
97
|
expect(result.services["web-search"].mode).toBe("your-own");
|
|
96
|
-
expect(result.maxTokens).toBe(64000);
|
|
97
|
-
expect(result.thinking).toEqual({
|
|
98
|
+
expect(result.llm.default.maxTokens).toBe(64000);
|
|
99
|
+
expect(result.llm.default.thinking).toEqual({
|
|
98
100
|
enabled: true,
|
|
99
101
|
streamThinking: true,
|
|
100
102
|
});
|
|
101
|
-
expect(result.contextWindow).toEqual({
|
|
103
|
+
expect(result.llm.default.contextWindow).toEqual({
|
|
102
104
|
enabled: true,
|
|
103
105
|
maxInputTokens: 200000,
|
|
104
106
|
targetBudgetRatio: 0.3,
|
|
@@ -134,11 +136,13 @@ describe("AssistantConfigSchema", () => {
|
|
|
134
136
|
|
|
135
137
|
test("accepts valid complete config", () => {
|
|
136
138
|
const input = {
|
|
137
|
-
|
|
138
|
-
|
|
139
|
+
llm: {
|
|
140
|
+
default: {
|
|
141
|
+
provider: "openai" as const,
|
|
142
|
+
model: "gpt-4",
|
|
143
|
+
maxTokens: 4096,
|
|
144
|
+
},
|
|
139
145
|
},
|
|
140
|
-
maxTokens: 4096,
|
|
141
|
-
thinking: { enabled: true },
|
|
142
146
|
timeouts: {
|
|
143
147
|
shellDefaultTimeoutSec: 30,
|
|
144
148
|
shellMaxTimeoutSec: 300,
|
|
@@ -154,13 +158,186 @@ describe("AssistantConfigSchema", () => {
|
|
|
154
158
|
auditLog: { retentionDays: 30 },
|
|
155
159
|
};
|
|
156
160
|
const result = AssistantConfigSchema.parse(input);
|
|
157
|
-
expect(result.
|
|
158
|
-
expect(result.
|
|
159
|
-
expect(result.maxTokens).toBe(4096);
|
|
160
|
-
expect(result.thinking.enabled).toBe(true);
|
|
161
|
+
expect(result.llm.default.provider).toBe("openai");
|
|
162
|
+
expect(result.llm.default.model).toBe("gpt-4");
|
|
163
|
+
expect(result.llm.default.maxTokens).toBe(4096);
|
|
164
|
+
expect(result.llm.default.thinking.enabled).toBe(true);
|
|
161
165
|
expect(result.secretDetection.action).toBe("block");
|
|
162
166
|
});
|
|
163
167
|
|
|
168
|
+
test("applies llm defaults when llm key is omitted", () => {
|
|
169
|
+
const result = AssistantConfigSchema.parse({});
|
|
170
|
+
expect(result.llm).toBeDefined();
|
|
171
|
+
expect(result.llm.default).toEqual({
|
|
172
|
+
provider: "anthropic",
|
|
173
|
+
model: "claude-opus-4-7",
|
|
174
|
+
maxTokens: 64000,
|
|
175
|
+
effort: "max",
|
|
176
|
+
speed: "standard",
|
|
177
|
+
temperature: null,
|
|
178
|
+
thinking: { enabled: true, streamThinking: true },
|
|
179
|
+
contextWindow: {
|
|
180
|
+
enabled: true,
|
|
181
|
+
maxInputTokens: 200000,
|
|
182
|
+
targetBudgetRatio: 0.3,
|
|
183
|
+
compactThreshold: 0.8,
|
|
184
|
+
summaryBudgetRatio: 0.05,
|
|
185
|
+
overflowRecovery: {
|
|
186
|
+
enabled: true,
|
|
187
|
+
safetyMarginRatio: 0.05,
|
|
188
|
+
maxAttempts: 3,
|
|
189
|
+
interactiveLatestTurnCompression: "summarize",
|
|
190
|
+
nonInteractiveLatestTurnCompression: "truncate",
|
|
191
|
+
},
|
|
192
|
+
},
|
|
193
|
+
openrouter: { only: [] },
|
|
194
|
+
});
|
|
195
|
+
expect(result.llm.profiles).toEqual({});
|
|
196
|
+
expect(result.llm.callSites).toEqual({});
|
|
197
|
+
expect(result.llm.pricingOverrides).toEqual([]);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
test("accepts an explicit llm block with profiles and call sites", () => {
|
|
201
|
+
const input = {
|
|
202
|
+
llm: {
|
|
203
|
+
default: {
|
|
204
|
+
provider: "anthropic" as const,
|
|
205
|
+
model: "claude-opus-4-7",
|
|
206
|
+
maxTokens: 32000,
|
|
207
|
+
effort: "high" as const,
|
|
208
|
+
speed: "fast" as const,
|
|
209
|
+
temperature: null,
|
|
210
|
+
thinking: { enabled: true, streamThinking: false },
|
|
211
|
+
contextWindow: {
|
|
212
|
+
enabled: true,
|
|
213
|
+
maxInputTokens: 200000,
|
|
214
|
+
targetBudgetRatio: 0.3,
|
|
215
|
+
compactThreshold: 0.8,
|
|
216
|
+
summaryBudgetRatio: 0.05,
|
|
217
|
+
overflowRecovery: {
|
|
218
|
+
enabled: true,
|
|
219
|
+
safetyMarginRatio: 0.05,
|
|
220
|
+
maxAttempts: 3,
|
|
221
|
+
interactiveLatestTurnCompression: "summarize" as const,
|
|
222
|
+
nonInteractiveLatestTurnCompression: "truncate" as const,
|
|
223
|
+
},
|
|
224
|
+
},
|
|
225
|
+
},
|
|
226
|
+
profiles: {
|
|
227
|
+
fast: { speed: "fast" as const, effort: "low" as const },
|
|
228
|
+
},
|
|
229
|
+
callSites: {
|
|
230
|
+
mainAgent: { profile: "fast" },
|
|
231
|
+
commitMessage: { maxTokens: 256 },
|
|
232
|
+
},
|
|
233
|
+
pricingOverrides: [],
|
|
234
|
+
},
|
|
235
|
+
};
|
|
236
|
+
const result = AssistantConfigSchema.parse(input);
|
|
237
|
+
expect(result.llm.default.model).toBe("claude-opus-4-7");
|
|
238
|
+
expect(result.llm.default.speed).toBe("fast");
|
|
239
|
+
expect(result.llm.profiles?.fast).toEqual({
|
|
240
|
+
speed: "fast",
|
|
241
|
+
effort: "low",
|
|
242
|
+
});
|
|
243
|
+
expect(result.llm.callSites?.mainAgent).toEqual({ profile: "fast" });
|
|
244
|
+
expect(result.llm.callSites?.commitMessage).toEqual({ maxTokens: 256 });
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
test("rejects an llm.callSites entry that references an undefined profile", () => {
|
|
248
|
+
const input = {
|
|
249
|
+
llm: {
|
|
250
|
+
default: {
|
|
251
|
+
provider: "anthropic" as const,
|
|
252
|
+
model: "claude-opus-4-6",
|
|
253
|
+
maxTokens: 64000,
|
|
254
|
+
effort: "max" as const,
|
|
255
|
+
speed: "standard" as const,
|
|
256
|
+
temperature: null,
|
|
257
|
+
thinking: { enabled: true, streamThinking: true },
|
|
258
|
+
contextWindow: {
|
|
259
|
+
enabled: true,
|
|
260
|
+
maxInputTokens: 200000,
|
|
261
|
+
targetBudgetRatio: 0.3,
|
|
262
|
+
compactThreshold: 0.8,
|
|
263
|
+
summaryBudgetRatio: 0.05,
|
|
264
|
+
overflowRecovery: {
|
|
265
|
+
enabled: true,
|
|
266
|
+
safetyMarginRatio: 0.05,
|
|
267
|
+
maxAttempts: 3,
|
|
268
|
+
interactiveLatestTurnCompression: "summarize" as const,
|
|
269
|
+
nonInteractiveLatestTurnCompression: "truncate" as const,
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
},
|
|
273
|
+
callSites: {
|
|
274
|
+
mainAgent: { profile: "missing-profile" },
|
|
275
|
+
},
|
|
276
|
+
},
|
|
277
|
+
};
|
|
278
|
+
expect(() => AssistantConfigSchema.parse(input)).toThrow(/missing-profile/);
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
test("legacy top-level inference keys are ignored after PR 19 cleanup", () => {
|
|
282
|
+
// The legacy keys (top-level maxTokens, effort, speed, thinking,
|
|
283
|
+
// contextWindow, services.inference.{provider,model}) were removed in PR
|
|
284
|
+
// 19. Configs that still carry them parse cleanly because Zod strips
|
|
285
|
+
// unknown fields, and migration 039 erases them from the on-disk file
|
|
286
|
+
// entirely.
|
|
287
|
+
const input = {
|
|
288
|
+
services: {
|
|
289
|
+
inference: { provider: "openai", model: "gpt-4" },
|
|
290
|
+
},
|
|
291
|
+
maxTokens: 8000,
|
|
292
|
+
effort: "medium",
|
|
293
|
+
speed: "fast",
|
|
294
|
+
thinking: { enabled: false, streamThinking: false },
|
|
295
|
+
};
|
|
296
|
+
const result = AssistantConfigSchema.parse(input);
|
|
297
|
+
expect((result as Record<string, unknown>).maxTokens).toBeUndefined();
|
|
298
|
+
expect((result as Record<string, unknown>).effort).toBeUndefined();
|
|
299
|
+
expect((result as Record<string, unknown>).speed).toBeUndefined();
|
|
300
|
+
expect((result as Record<string, unknown>).thinking).toBeUndefined();
|
|
301
|
+
expect(
|
|
302
|
+
(result.services.inference as Record<string, unknown>).provider,
|
|
303
|
+
).toBeUndefined();
|
|
304
|
+
expect(
|
|
305
|
+
(result.services.inference as Record<string, unknown>).model,
|
|
306
|
+
).toBeUndefined();
|
|
307
|
+
expect(result.llm.default.provider).toBe("anthropic");
|
|
308
|
+
expect(result.llm.default.model).toBe("claude-opus-4-7");
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
test("partial llm config (empty `llm: {}`) doesn't trigger full config reset", () => {
|
|
312
|
+
// Regression guard: previously LLMConfigBase had no schema-level defaults,
|
|
313
|
+
// so any `llm: {}` block would fail validation and the loader's recovery
|
|
314
|
+
// path would fall through to `cloneDefaultConfig()`, discarding unrelated
|
|
315
|
+
// valid settings (like a custom `llm.default.maxTokens`). With leaf-level
|
|
316
|
+
// defaults, `llm: {}` parses cleanly and the user's other settings are
|
|
317
|
+
// preserved.
|
|
318
|
+
const result = AssistantConfigSchema.parse({
|
|
319
|
+
llm: { default: { maxTokens: 32000 } },
|
|
320
|
+
});
|
|
321
|
+
expect(result.llm.default.maxTokens).toBe(32000);
|
|
322
|
+
expect(result.llm.default.provider).toBe("anthropic");
|
|
323
|
+
expect(result.llm.default.model).toBe("claude-opus-4-7");
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
test("llm.default with one missing field still parses (defaults applied)", () => {
|
|
327
|
+
// A user can override a single field of `llm.default` without specifying
|
|
328
|
+
// the rest — schema-level defaults fill in everything that wasn't set.
|
|
329
|
+
const result = AssistantConfigSchema.parse({
|
|
330
|
+
llm: { default: { model: "claude-haiku-4-5" } },
|
|
331
|
+
});
|
|
332
|
+
expect(result.llm.default.model).toBe("claude-haiku-4-5");
|
|
333
|
+
expect(result.llm.default.provider).toBe("anthropic");
|
|
334
|
+
expect(result.llm.default.maxTokens).toBe(64000);
|
|
335
|
+
expect(result.llm.default.thinking).toEqual({
|
|
336
|
+
enabled: true,
|
|
337
|
+
streamThinking: true,
|
|
338
|
+
});
|
|
339
|
+
});
|
|
340
|
+
|
|
164
341
|
test("applies rollout defaults for dynamic budget", () => {
|
|
165
342
|
const result = AssistantConfigSchema.parse({});
|
|
166
343
|
expect(result.memory.retrieval.dynamicBudget).toEqual({
|
|
@@ -248,13 +425,15 @@ describe("AssistantConfigSchema", () => {
|
|
|
248
425
|
|
|
249
426
|
test("rejects invalid provider", () => {
|
|
250
427
|
const result = AssistantConfigSchema.safeParse({
|
|
251
|
-
|
|
428
|
+
llm: { default: { provider: "invalid" } },
|
|
252
429
|
});
|
|
253
430
|
expect(result.success).toBe(false);
|
|
254
431
|
});
|
|
255
432
|
|
|
256
|
-
test("rejects negative maxTokens", () => {
|
|
257
|
-
const result = AssistantConfigSchema.safeParse({
|
|
433
|
+
test("rejects negative llm.default.maxTokens", () => {
|
|
434
|
+
const result = AssistantConfigSchema.safeParse({
|
|
435
|
+
llm: { default: { maxTokens: -100 } },
|
|
436
|
+
});
|
|
258
437
|
expect(result.success).toBe(false);
|
|
259
438
|
if (!result.success) {
|
|
260
439
|
expect(
|
|
@@ -263,8 +442,10 @@ describe("AssistantConfigSchema", () => {
|
|
|
263
442
|
}
|
|
264
443
|
});
|
|
265
444
|
|
|
266
|
-
test("rejects non-integer maxTokens", () => {
|
|
267
|
-
const result = AssistantConfigSchema.safeParse({
|
|
445
|
+
test("rejects non-integer llm.default.maxTokens", () => {
|
|
446
|
+
const result = AssistantConfigSchema.safeParse({
|
|
447
|
+
llm: { default: { maxTokens: 3.14 } },
|
|
448
|
+
});
|
|
268
449
|
expect(result.success).toBe(false);
|
|
269
450
|
if (!result.success) {
|
|
270
451
|
expect(
|
|
@@ -273,9 +454,9 @@ describe("AssistantConfigSchema", () => {
|
|
|
273
454
|
}
|
|
274
455
|
});
|
|
275
456
|
|
|
276
|
-
test("rejects string maxTokens", () => {
|
|
457
|
+
test("rejects string llm.default.maxTokens", () => {
|
|
277
458
|
const result = AssistantConfigSchema.safeParse({
|
|
278
|
-
maxTokens: "not-a-number",
|
|
459
|
+
llm: { default: { maxTokens: "not-a-number" } },
|
|
279
460
|
});
|
|
280
461
|
expect(result.success).toBe(false);
|
|
281
462
|
if (!result.success) {
|
|
@@ -301,7 +482,7 @@ describe("AssistantConfigSchema", () => {
|
|
|
301
482
|
|
|
302
483
|
test("rejects invalid thinking config", () => {
|
|
303
484
|
const result = AssistantConfigSchema.safeParse({
|
|
304
|
-
thinking: { enabled: "yes" },
|
|
485
|
+
llm: { default: { thinking: { enabled: "yes" } } },
|
|
305
486
|
});
|
|
306
487
|
expect(result.success).toBe(false);
|
|
307
488
|
if (!result.success) {
|
|
@@ -311,16 +492,21 @@ describe("AssistantConfigSchema", () => {
|
|
|
311
492
|
|
|
312
493
|
test("rejects contextWindow targetBudgetRatio >= compactThreshold", () => {
|
|
313
494
|
const result = AssistantConfigSchema.safeParse({
|
|
314
|
-
|
|
495
|
+
llm: {
|
|
496
|
+
default: {
|
|
497
|
+
contextWindow: { targetBudgetRatio: 0.8, compactThreshold: 0.8 },
|
|
498
|
+
},
|
|
499
|
+
},
|
|
315
500
|
});
|
|
316
501
|
expect(result.success).toBe(false);
|
|
317
502
|
if (!result.success) {
|
|
318
503
|
expect(
|
|
319
504
|
result.error.issues.some(
|
|
320
505
|
(issue) =>
|
|
321
|
-
issue.path.join(".") ===
|
|
506
|
+
issue.path.join(".") ===
|
|
507
|
+
"llm.default.contextWindow.targetBudgetRatio" &&
|
|
322
508
|
issue.message.includes(
|
|
323
|
-
"must be less than contextWindow.compactThreshold",
|
|
509
|
+
"must be less than llm.default.contextWindow.compactThreshold",
|
|
324
510
|
),
|
|
325
511
|
),
|
|
326
512
|
).toBe(true);
|
|
@@ -330,7 +516,11 @@ describe("AssistantConfigSchema", () => {
|
|
|
330
516
|
test("rejects overflowRecovery safetyMarginRatio out of (0,1) range", () => {
|
|
331
517
|
for (const bad of [0, 1, -0.1, 1.5]) {
|
|
332
518
|
const result = AssistantConfigSchema.safeParse({
|
|
333
|
-
|
|
519
|
+
llm: {
|
|
520
|
+
default: {
|
|
521
|
+
contextWindow: { overflowRecovery: { safetyMarginRatio: bad } },
|
|
522
|
+
},
|
|
523
|
+
},
|
|
334
524
|
});
|
|
335
525
|
expect(result.success).toBe(false);
|
|
336
526
|
if (!result.success) {
|
|
@@ -345,8 +535,12 @@ describe("AssistantConfigSchema", () => {
|
|
|
345
535
|
|
|
346
536
|
test("rejects invalid overflowRecovery interactiveLatestTurnCompression", () => {
|
|
347
537
|
const result = AssistantConfigSchema.safeParse({
|
|
348
|
-
|
|
349
|
-
|
|
538
|
+
llm: {
|
|
539
|
+
default: {
|
|
540
|
+
contextWindow: {
|
|
541
|
+
overflowRecovery: { interactiveLatestTurnCompression: "explode" },
|
|
542
|
+
},
|
|
543
|
+
},
|
|
350
544
|
},
|
|
351
545
|
});
|
|
352
546
|
expect(result.success).toBe(false);
|
|
@@ -361,8 +555,12 @@ describe("AssistantConfigSchema", () => {
|
|
|
361
555
|
|
|
362
556
|
test("rejects invalid overflowRecovery nonInteractiveLatestTurnCompression", () => {
|
|
363
557
|
const result = AssistantConfigSchema.safeParse({
|
|
364
|
-
|
|
365
|
-
|
|
558
|
+
llm: {
|
|
559
|
+
default: {
|
|
560
|
+
contextWindow: {
|
|
561
|
+
overflowRecovery: { nonInteractiveLatestTurnCompression: "nope" },
|
|
562
|
+
},
|
|
563
|
+
},
|
|
366
564
|
},
|
|
367
565
|
});
|
|
368
566
|
expect(result.success).toBe(false);
|
|
@@ -433,7 +631,7 @@ describe("AssistantConfigSchema", () => {
|
|
|
433
631
|
"ollama",
|
|
434
632
|
] as const) {
|
|
435
633
|
const result = AssistantConfigSchema.safeParse({
|
|
436
|
-
|
|
634
|
+
llm: { default: { provider } },
|
|
437
635
|
});
|
|
438
636
|
expect(result.success).toBe(true);
|
|
439
637
|
}
|
|
@@ -450,13 +648,19 @@ describe("AssistantConfigSchema", () => {
|
|
|
450
648
|
|
|
451
649
|
test("provides helpful error messages", () => {
|
|
452
650
|
const result = AssistantConfigSchema.safeParse({
|
|
453
|
-
maxTokens: -1,
|
|
651
|
+
llm: { default: { maxTokens: -1 } },
|
|
454
652
|
secretDetection: { action: "explode" },
|
|
455
653
|
});
|
|
456
654
|
expect(result.success).toBe(false);
|
|
457
655
|
if (!result.success) {
|
|
458
656
|
const messages = result.error.issues.map((i) => i.message);
|
|
459
|
-
|
|
657
|
+
// The llm.default.maxTokens validation rejects -1 with a "Too small"
|
|
658
|
+
// / "expected number to be >0" message from Zod's default issue text.
|
|
659
|
+
expect(
|
|
660
|
+
messages.some(
|
|
661
|
+
(m) => m.includes("positive") || /expected number to be >0/i.test(m),
|
|
662
|
+
),
|
|
663
|
+
).toBe(true);
|
|
460
664
|
expect(
|
|
461
665
|
messages.some(
|
|
462
666
|
(m) =>
|
|
@@ -471,6 +675,11 @@ describe("AssistantConfigSchema", () => {
|
|
|
471
675
|
expect(result.permissions).toEqual({
|
|
472
676
|
mode: "workspace",
|
|
473
677
|
hostAccess: false,
|
|
678
|
+
autoApproveUpTo: {
|
|
679
|
+
conversation: "low",
|
|
680
|
+
background: "medium",
|
|
681
|
+
headless: "none",
|
|
682
|
+
},
|
|
474
683
|
});
|
|
475
684
|
});
|
|
476
685
|
|
|
@@ -507,6 +716,119 @@ describe("AssistantConfigSchema", () => {
|
|
|
507
716
|
}
|
|
508
717
|
});
|
|
509
718
|
|
|
719
|
+
test("defaults autoApproveUpTo to per-context object when not specified", () => {
|
|
720
|
+
const result = AssistantConfigSchema.parse({
|
|
721
|
+
permissions: { mode: "workspace" },
|
|
722
|
+
});
|
|
723
|
+
expect(result.permissions.autoApproveUpTo).toEqual({
|
|
724
|
+
conversation: "low",
|
|
725
|
+
background: "medium",
|
|
726
|
+
headless: "none",
|
|
727
|
+
});
|
|
728
|
+
});
|
|
729
|
+
|
|
730
|
+
test("accepts autoApproveUpTo none", () => {
|
|
731
|
+
const result = AssistantConfigSchema.parse({
|
|
732
|
+
permissions: { autoApproveUpTo: "none" },
|
|
733
|
+
});
|
|
734
|
+
expect(result.permissions.autoApproveUpTo).toBe("none");
|
|
735
|
+
});
|
|
736
|
+
|
|
737
|
+
test("accepts autoApproveUpTo low", () => {
|
|
738
|
+
const result = AssistantConfigSchema.parse({
|
|
739
|
+
permissions: { autoApproveUpTo: "low" },
|
|
740
|
+
});
|
|
741
|
+
expect(result.permissions.autoApproveUpTo).toBe("low");
|
|
742
|
+
});
|
|
743
|
+
|
|
744
|
+
test("accepts autoApproveUpTo medium", () => {
|
|
745
|
+
const result = AssistantConfigSchema.parse({
|
|
746
|
+
permissions: { autoApproveUpTo: "medium" },
|
|
747
|
+
});
|
|
748
|
+
expect(result.permissions.autoApproveUpTo).toBe("medium");
|
|
749
|
+
});
|
|
750
|
+
|
|
751
|
+
test("rejects autoApproveUpTo high", () => {
|
|
752
|
+
const result = AssistantConfigSchema.safeParse({
|
|
753
|
+
permissions: { autoApproveUpTo: "high" },
|
|
754
|
+
});
|
|
755
|
+
expect(result.success).toBe(false);
|
|
756
|
+
});
|
|
757
|
+
|
|
758
|
+
test("rejects invalid autoApproveUpTo string", () => {
|
|
759
|
+
const result = AssistantConfigSchema.safeParse({
|
|
760
|
+
permissions: { autoApproveUpTo: "everything" },
|
|
761
|
+
});
|
|
762
|
+
expect(result.success).toBe(false);
|
|
763
|
+
});
|
|
764
|
+
|
|
765
|
+
test("autoApproveUpTo round-trips through JSON serialization", () => {
|
|
766
|
+
const original = AssistantConfigSchema.parse({
|
|
767
|
+
permissions: { autoApproveUpTo: "medium" },
|
|
768
|
+
});
|
|
769
|
+
const json = JSON.stringify(original);
|
|
770
|
+
const parsed = AssistantConfigSchema.parse(JSON.parse(json));
|
|
771
|
+
expect(parsed.permissions.autoApproveUpTo).toBe("medium");
|
|
772
|
+
});
|
|
773
|
+
|
|
774
|
+
test("accepts autoApproveUpTo as per-context object", () => {
|
|
775
|
+
const result = AssistantConfigSchema.parse({
|
|
776
|
+
permissions: {
|
|
777
|
+
autoApproveUpTo: {
|
|
778
|
+
conversation: "low",
|
|
779
|
+
background: "medium",
|
|
780
|
+
headless: "none",
|
|
781
|
+
},
|
|
782
|
+
},
|
|
783
|
+
});
|
|
784
|
+
expect(result.permissions.autoApproveUpTo).toEqual({
|
|
785
|
+
conversation: "low",
|
|
786
|
+
background: "medium",
|
|
787
|
+
headless: "none",
|
|
788
|
+
});
|
|
789
|
+
});
|
|
790
|
+
|
|
791
|
+
test("per-context object applies defaults for omitted keys", () => {
|
|
792
|
+
const result = AssistantConfigSchema.parse({
|
|
793
|
+
permissions: {
|
|
794
|
+
autoApproveUpTo: {},
|
|
795
|
+
},
|
|
796
|
+
});
|
|
797
|
+
expect(result.permissions.autoApproveUpTo).toEqual({
|
|
798
|
+
conversation: "low",
|
|
799
|
+
background: "medium",
|
|
800
|
+
headless: "none",
|
|
801
|
+
});
|
|
802
|
+
});
|
|
803
|
+
|
|
804
|
+
test("per-context object rejects invalid enum values", () => {
|
|
805
|
+
const result = AssistantConfigSchema.safeParse({
|
|
806
|
+
permissions: {
|
|
807
|
+
autoApproveUpTo: { conversation: "high" },
|
|
808
|
+
},
|
|
809
|
+
});
|
|
810
|
+
expect(result.success).toBe(false);
|
|
811
|
+
});
|
|
812
|
+
|
|
813
|
+
test("per-context object round-trips through JSON serialization", () => {
|
|
814
|
+
const original = AssistantConfigSchema.parse({
|
|
815
|
+
permissions: {
|
|
816
|
+
autoApproveUpTo: {
|
|
817
|
+
conversation: "none",
|
|
818
|
+
background: "low",
|
|
819
|
+
headless: "medium",
|
|
820
|
+
},
|
|
821
|
+
},
|
|
822
|
+
});
|
|
823
|
+
const json = JSON.stringify(original);
|
|
824
|
+
const parsed = AssistantConfigSchema.parse(JSON.parse(json));
|
|
825
|
+
expect(parsed.permissions.autoApproveUpTo).toEqual({
|
|
826
|
+
conversation: "none",
|
|
827
|
+
background: "low",
|
|
828
|
+
headless: "medium",
|
|
829
|
+
});
|
|
830
|
+
});
|
|
831
|
+
|
|
510
832
|
test("applies workspaceGit defaults including interactiveGitTimeoutMs", () => {
|
|
511
833
|
const result = AssistantConfigSchema.parse({});
|
|
512
834
|
expect(result.workspaceGit).toEqual({
|
|
@@ -520,11 +842,7 @@ describe("AssistantConfigSchema", () => {
|
|
|
520
842
|
enrichmentMaxRetries: 2,
|
|
521
843
|
commitMessageLLM: {
|
|
522
844
|
enabled: false,
|
|
523
|
-
useConfiguredProvider: true,
|
|
524
|
-
providerFastModelOverrides: {},
|
|
525
845
|
timeoutMs: 600,
|
|
526
|
-
maxTokens: 120,
|
|
527
|
-
temperature: 0.2,
|
|
528
846
|
maxFilesInPrompt: 30,
|
|
529
847
|
maxDiffBytes: 12000,
|
|
530
848
|
minRemainingTurnBudgetMs: 1000,
|
|
@@ -578,11 +896,7 @@ describe("AssistantConfigSchema", () => {
|
|
|
578
896
|
const result = AssistantConfigSchema.parse({});
|
|
579
897
|
const llm = result.workspaceGit.commitMessageLLM;
|
|
580
898
|
expect(llm.enabled).toBe(false);
|
|
581
|
-
expect(llm.useConfiguredProvider).toBe(true);
|
|
582
|
-
expect(llm.providerFastModelOverrides).toEqual({});
|
|
583
899
|
expect(llm.timeoutMs).toBe(600);
|
|
584
|
-
expect(llm.maxTokens).toBe(120);
|
|
585
|
-
expect(llm.temperature).toBe(0.2);
|
|
586
900
|
expect(llm.maxFilesInPrompt).toBe(30);
|
|
587
901
|
expect(llm.maxDiffBytes).toBe(12000);
|
|
588
902
|
expect(llm.minRemainingTurnBudgetMs).toBe(1000);
|
|
@@ -595,13 +909,6 @@ describe("AssistantConfigSchema", () => {
|
|
|
595
909
|
expect(result.success).toBe(false);
|
|
596
910
|
});
|
|
597
911
|
|
|
598
|
-
test("rejects commitMessageLLM.temperature > 2", () => {
|
|
599
|
-
const result = AssistantConfigSchema.safeParse({
|
|
600
|
-
workspaceGit: { commitMessageLLM: { temperature: 2.5 } },
|
|
601
|
-
});
|
|
602
|
-
expect(result.success).toBe(false);
|
|
603
|
-
});
|
|
604
|
-
|
|
605
912
|
test("breaker settings have correct defaults", () => {
|
|
606
913
|
const result = AssistantConfigSchema.parse({});
|
|
607
914
|
const breaker = result.workspaceGit.commitMessageLLM.breaker;
|
|
@@ -616,14 +923,12 @@ describe("AssistantConfigSchema", () => {
|
|
|
616
923
|
commitMessageLLM: {
|
|
617
924
|
enabled: true,
|
|
618
925
|
timeoutMs: 1000,
|
|
619
|
-
temperature: 0.5,
|
|
620
926
|
breaker: { openAfterFailures: 5 },
|
|
621
927
|
},
|
|
622
928
|
},
|
|
623
929
|
});
|
|
624
930
|
expect(result.workspaceGit.commitMessageLLM.enabled).toBe(true);
|
|
625
931
|
expect(result.workspaceGit.commitMessageLLM.timeoutMs).toBe(1000);
|
|
626
|
-
expect(result.workspaceGit.commitMessageLLM.temperature).toBe(0.5);
|
|
627
932
|
expect(result.workspaceGit.commitMessageLLM.breaker.openAfterFailures).toBe(
|
|
628
933
|
5,
|
|
629
934
|
);
|
|
@@ -633,18 +938,18 @@ describe("AssistantConfigSchema", () => {
|
|
|
633
938
|
);
|
|
634
939
|
});
|
|
635
940
|
|
|
636
|
-
test("
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
const result = AssistantConfigSchema.safeParse({
|
|
645
|
-
workspaceGit: { commitMessageLLM: { maxTokens: 3.5 } },
|
|
941
|
+
test("ignores legacy commitMessageLLM.{maxTokens,temperature} keys", () => {
|
|
942
|
+
// PR 19 removed maxTokens/temperature from the schema; Zod silently
|
|
943
|
+
// strips them on parse. Migration 039 erases them from disk so they
|
|
944
|
+
// don't accumulate over time.
|
|
945
|
+
const result = AssistantConfigSchema.parse({
|
|
946
|
+
workspaceGit: {
|
|
947
|
+
commitMessageLLM: { maxTokens: 200, temperature: 0.5 },
|
|
948
|
+
},
|
|
646
949
|
});
|
|
647
|
-
|
|
950
|
+
const cm = result.workspaceGit.commitMessageLLM as Record<string, unknown>;
|
|
951
|
+
expect(cm.maxTokens).toBeUndefined();
|
|
952
|
+
expect(cm.temperature).toBeUndefined();
|
|
648
953
|
});
|
|
649
954
|
|
|
650
955
|
// ── Calls config ────────────────────────────────────────────────────
|
|
@@ -803,16 +1108,13 @@ describe("AssistantConfigSchema", () => {
|
|
|
803
1108
|
).toBeUndefined();
|
|
804
1109
|
});
|
|
805
1110
|
|
|
806
|
-
test("
|
|
1111
|
+
test("legacy calls.model key is stripped after PR 19 cleanup", () => {
|
|
1112
|
+
// calls.model moved to llm.callSites.callAgent.model in PR 4 and the
|
|
1113
|
+
// legacy field was removed in PR 19. Zod silently strips unknown keys.
|
|
807
1114
|
const result = AssistantConfigSchema.parse({
|
|
808
1115
|
calls: { model: "claude-haiku-4-5-20251001" },
|
|
809
1116
|
});
|
|
810
|
-
expect(result.calls.model).
|
|
811
|
-
});
|
|
812
|
-
|
|
813
|
-
test("calls.model is undefined by default", () => {
|
|
814
|
-
const result = AssistantConfigSchema.parse({});
|
|
815
|
-
expect(result.calls.model).toBeUndefined();
|
|
1117
|
+
expect((result.calls as Record<string, unknown>).model).toBeUndefined();
|
|
816
1118
|
});
|
|
817
1119
|
|
|
818
1120
|
// ── Caller identity config ────────────────────────────────────────
|
|
@@ -1938,28 +2240,27 @@ describe("loadConfig with schema validation", () => {
|
|
|
1938
2240
|
// intermittently trigger unhandled ENOENT in CI if the directory is removed.
|
|
1939
2241
|
test("loads valid config", () => {
|
|
1940
2242
|
writeConfig({
|
|
1941
|
-
|
|
1942
|
-
|
|
2243
|
+
llm: {
|
|
2244
|
+
default: { provider: "openai", model: "gpt-4", maxTokens: 4096 },
|
|
1943
2245
|
},
|
|
1944
|
-
maxTokens: 4096,
|
|
1945
2246
|
});
|
|
1946
2247
|
const config = loadConfig();
|
|
1947
|
-
expect(config.
|
|
1948
|
-
expect(config.
|
|
1949
|
-
expect(config.maxTokens).toBe(4096);
|
|
2248
|
+
expect(config.llm.default.provider).toBe("openai");
|
|
2249
|
+
expect(config.llm.default.model).toBe("gpt-4");
|
|
2250
|
+
expect(config.llm.default.maxTokens).toBe(4096);
|
|
1950
2251
|
});
|
|
1951
2252
|
|
|
1952
2253
|
test("applies defaults for missing fields", () => {
|
|
1953
2254
|
writeConfig({});
|
|
1954
2255
|
const config = loadConfig();
|
|
1955
|
-
expect(config.
|
|
1956
|
-
expect(config.
|
|
1957
|
-
expect(config.maxTokens).toBe(64000);
|
|
1958
|
-
expect(config.thinking).toEqual({
|
|
2256
|
+
expect(config.llm.default.provider).toBe("anthropic");
|
|
2257
|
+
expect(config.llm.default.model).toBe("claude-opus-4-7");
|
|
2258
|
+
expect(config.llm.default.maxTokens).toBe(64000);
|
|
2259
|
+
expect(config.llm.default.thinking).toEqual({
|
|
1959
2260
|
enabled: true,
|
|
1960
2261
|
streamThinking: true,
|
|
1961
2262
|
});
|
|
1962
|
-
expect(config.contextWindow).toEqual({
|
|
2263
|
+
expect(config.llm.default.contextWindow).toEqual({
|
|
1963
2264
|
enabled: true,
|
|
1964
2265
|
maxInputTokens: 200000,
|
|
1965
2266
|
targetBudgetRatio: 0.3,
|
|
@@ -1977,16 +2278,16 @@ describe("loadConfig with schema validation", () => {
|
|
|
1977
2278
|
|
|
1978
2279
|
test("falls back to default for invalid provider", () => {
|
|
1979
2280
|
writeConfig({
|
|
1980
|
-
|
|
2281
|
+
llm: { default: { provider: "invalid-provider" } },
|
|
1981
2282
|
});
|
|
1982
2283
|
const config = loadConfig();
|
|
1983
|
-
expect(config.
|
|
2284
|
+
expect(config.llm.default.provider).toBe("anthropic");
|
|
1984
2285
|
});
|
|
1985
2286
|
|
|
1986
2287
|
test("falls back to default for invalid maxTokens", () => {
|
|
1987
|
-
writeConfig({ maxTokens: -100 });
|
|
2288
|
+
writeConfig({ llm: { default: { maxTokens: -100 } } });
|
|
1988
2289
|
const config = loadConfig();
|
|
1989
|
-
expect(config.maxTokens).toBe(64000);
|
|
2290
|
+
expect(config.llm.default.maxTokens).toBe(64000);
|
|
1990
2291
|
});
|
|
1991
2292
|
|
|
1992
2293
|
test("falls back to defaults for invalid nested values", () => {
|
|
@@ -2001,23 +2302,26 @@ describe("loadConfig with schema validation", () => {
|
|
|
2001
2302
|
|
|
2002
2303
|
test("preserves valid fields when other fields are invalid", () => {
|
|
2003
2304
|
writeConfig({
|
|
2004
|
-
|
|
2005
|
-
|
|
2305
|
+
llm: {
|
|
2306
|
+
default: {
|
|
2307
|
+
provider: "openai",
|
|
2308
|
+
model: "gpt-4",
|
|
2309
|
+
maxTokens: -1,
|
|
2310
|
+
thinking: { enabled: true },
|
|
2311
|
+
},
|
|
2006
2312
|
},
|
|
2007
|
-
maxTokens: -1,
|
|
2008
|
-
thinking: { enabled: true },
|
|
2009
2313
|
});
|
|
2010
2314
|
const config = loadConfig();
|
|
2011
|
-
expect(config.
|
|
2012
|
-
expect(config.
|
|
2013
|
-
expect(config.thinking.enabled).toBe(true);
|
|
2014
|
-
expect(config.maxTokens).toBe(64000);
|
|
2315
|
+
expect(config.llm.default.provider).toBe("openai");
|
|
2316
|
+
expect(config.llm.default.model).toBe("gpt-4");
|
|
2317
|
+
expect(config.llm.default.thinking.enabled).toBe(true);
|
|
2318
|
+
expect(config.llm.default.maxTokens).toBe(64000);
|
|
2015
2319
|
});
|
|
2016
2320
|
|
|
2017
2321
|
test("handles no config file", () => {
|
|
2018
2322
|
const config = loadConfig();
|
|
2019
|
-
expect(config.
|
|
2020
|
-
expect(config.maxTokens).toBe(64000);
|
|
2323
|
+
expect(config.llm.default.provider).toBe("anthropic");
|
|
2324
|
+
expect(config.llm.default.maxTokens).toBe(64000);
|
|
2021
2325
|
});
|
|
2022
2326
|
|
|
2023
2327
|
test("partial nested objects get defaults for missing fields", () => {
|
|
@@ -2038,11 +2342,15 @@ describe("loadConfig with schema validation", () => {
|
|
|
2038
2342
|
|
|
2039
2343
|
test("falls back for invalid contextWindow relationship", () => {
|
|
2040
2344
|
writeConfig({
|
|
2041
|
-
|
|
2345
|
+
llm: {
|
|
2346
|
+
default: {
|
|
2347
|
+
contextWindow: { targetBudgetRatio: 0.8, compactThreshold: 0.8 },
|
|
2348
|
+
},
|
|
2349
|
+
},
|
|
2042
2350
|
});
|
|
2043
2351
|
const config = loadConfig();
|
|
2044
|
-
expect(config.contextWindow.targetBudgetRatio).toBe(0.3);
|
|
2045
|
-
expect(config.contextWindow.compactThreshold).toBe(0.8);
|
|
2352
|
+
expect(config.llm.default.contextWindow.targetBudgetRatio).toBe(0.3);
|
|
2353
|
+
expect(config.llm.default.contextWindow.compactThreshold).toBe(0.8);
|
|
2046
2354
|
});
|
|
2047
2355
|
|
|
2048
2356
|
test("falls back for invalid rateLimit values", () => {
|
|
@@ -2065,6 +2373,11 @@ describe("loadConfig with schema validation", () => {
|
|
|
2065
2373
|
expect(config.permissions).toEqual({
|
|
2066
2374
|
mode: "workspace",
|
|
2067
2375
|
hostAccess: false,
|
|
2376
|
+
autoApproveUpTo: {
|
|
2377
|
+
conversation: "low",
|
|
2378
|
+
background: "medium",
|
|
2379
|
+
headless: "none",
|
|
2380
|
+
},
|
|
2068
2381
|
});
|
|
2069
2382
|
});
|
|
2070
2383
|
|
|
@@ -2103,13 +2416,13 @@ describe("loadConfig with schema validation", () => {
|
|
|
2103
2416
|
// Only activeHoursStart is set. The superRefine must emit the issue so
|
|
2104
2417
|
// the loader's delete-and-retry can strip the set field; otherwise the
|
|
2105
2418
|
// mismatch persists and the config falls back to full defaults (which
|
|
2106
|
-
// would reset maxTokens below to 64000).
|
|
2419
|
+
// would reset llm.default.maxTokens below to 64000).
|
|
2107
2420
|
writeConfig({
|
|
2108
|
-
maxTokens: 4096,
|
|
2421
|
+
llm: { default: { maxTokens: 4096 } },
|
|
2109
2422
|
filing: { activeHoursStart: 8 },
|
|
2110
2423
|
});
|
|
2111
2424
|
const config = loadConfig();
|
|
2112
|
-
expect(config.maxTokens).toBe(4096);
|
|
2425
|
+
expect(config.llm.default.maxTokens).toBe(4096);
|
|
2113
2426
|
expect(config.filing.activeHoursStart).toBeNull();
|
|
2114
2427
|
expect(config.filing.activeHoursEnd).toBeNull();
|
|
2115
2428
|
});
|
|
@@ -2117,13 +2430,13 @@ describe("loadConfig with schema validation", () => {
|
|
|
2117
2430
|
test("recovers from partial heartbeat.activeHours without wiping unrelated fields", () => {
|
|
2118
2431
|
// activeHoursStart is explicitly nulled while activeHoursEnd defaults to
|
|
2119
2432
|
// 22 — a mismatch. Dual-emit strips both sides; both defaults restore
|
|
2120
|
-
// (8, 22). maxTokens is unaffected.
|
|
2433
|
+
// (8, 22). llm.default.maxTokens is unaffected.
|
|
2121
2434
|
writeConfig({
|
|
2122
|
-
maxTokens: 4096,
|
|
2435
|
+
llm: { default: { maxTokens: 4096 } },
|
|
2123
2436
|
heartbeat: { activeHoursStart: null },
|
|
2124
2437
|
});
|
|
2125
2438
|
const config = loadConfig();
|
|
2126
|
-
expect(config.maxTokens).toBe(4096);
|
|
2439
|
+
expect(config.llm.default.maxTokens).toBe(4096);
|
|
2127
2440
|
expect(config.heartbeat.activeHoursStart).toBe(8);
|
|
2128
2441
|
expect(config.heartbeat.activeHoursEnd).toBe(22);
|
|
2129
2442
|
});
|
|
@@ -2131,14 +2444,14 @@ describe("loadConfig with schema validation", () => {
|
|
|
2131
2444
|
test("recovers from heartbeat.activeHours null-mismatch where explicit value equals opposite default", () => {
|
|
2132
2445
|
// { start: null, end: 8 } — single-emit on the null side would strip
|
|
2133
2446
|
// start, the default 8 would restore it, and the equal-hours check would
|
|
2134
|
-
// fire, cascading to a full defaults reset that wipes maxTokens.
|
|
2447
|
+
// fire, cascading to a full defaults reset that wipes llm.default.maxTokens.
|
|
2135
2448
|
// Dual-emit strips both sides in one pass.
|
|
2136
2449
|
writeConfig({
|
|
2137
|
-
maxTokens: 4096,
|
|
2450
|
+
llm: { default: { maxTokens: 4096 } },
|
|
2138
2451
|
heartbeat: { activeHoursStart: null, activeHoursEnd: 8 },
|
|
2139
2452
|
});
|
|
2140
2453
|
const config = loadConfig();
|
|
2141
|
-
expect(config.maxTokens).toBe(4096);
|
|
2454
|
+
expect(config.llm.default.maxTokens).toBe(4096);
|
|
2142
2455
|
expect(config.heartbeat.activeHoursStart).toBe(8);
|
|
2143
2456
|
expect(config.heartbeat.activeHoursEnd).toBe(22);
|
|
2144
2457
|
});
|
|
@@ -2146,11 +2459,11 @@ describe("loadConfig with schema validation", () => {
|
|
|
2146
2459
|
test("recovers from heartbeat.activeHours null-mismatch on the end side", () => {
|
|
2147
2460
|
// { start: 22, end: null } — same cascade class as above, mirrored.
|
|
2148
2461
|
writeConfig({
|
|
2149
|
-
maxTokens: 4096,
|
|
2462
|
+
llm: { default: { maxTokens: 4096 } },
|
|
2150
2463
|
heartbeat: { activeHoursStart: 22, activeHoursEnd: null },
|
|
2151
2464
|
});
|
|
2152
2465
|
const config = loadConfig();
|
|
2153
|
-
expect(config.maxTokens).toBe(4096);
|
|
2466
|
+
expect(config.llm.default.maxTokens).toBe(4096);
|
|
2154
2467
|
expect(config.heartbeat.activeHoursStart).toBe(8);
|
|
2155
2468
|
expect(config.heartbeat.activeHoursEnd).toBe(22);
|
|
2156
2469
|
});
|
|
@@ -2159,13 +2472,13 @@ describe("loadConfig with schema validation", () => {
|
|
|
2159
2472
|
// { start: 22, end: 22 } — both equal to the default for end. Single-emit
|
|
2160
2473
|
// on one path would strip one side, the default would recreate the
|
|
2161
2474
|
// equal-hours mismatch, and the loader would fall back to full defaults,
|
|
2162
|
-
// wiping maxTokens. Dual-emit strips both sides at once.
|
|
2475
|
+
// wiping llm.default.maxTokens. Dual-emit strips both sides at once.
|
|
2163
2476
|
writeConfig({
|
|
2164
|
-
maxTokens: 4096,
|
|
2477
|
+
llm: { default: { maxTokens: 4096 } },
|
|
2165
2478
|
heartbeat: { activeHoursStart: 22, activeHoursEnd: 22 },
|
|
2166
2479
|
});
|
|
2167
2480
|
const config = loadConfig();
|
|
2168
|
-
expect(config.maxTokens).toBe(4096);
|
|
2481
|
+
expect(config.llm.default.maxTokens).toBe(4096);
|
|
2169
2482
|
expect(config.heartbeat.activeHoursStart).toBe(8);
|
|
2170
2483
|
expect(config.heartbeat.activeHoursEnd).toBe(22);
|
|
2171
2484
|
});
|
|
@@ -2174,14 +2487,14 @@ describe("loadConfig with schema validation", () => {
|
|
|
2174
2487
|
// activeHoursStart === activeHoursEnd is invalid (empty window). Filing's
|
|
2175
2488
|
// defaults are null/null, so single-emit on one path would strip one side
|
|
2176
2489
|
// and the null default would recreate a mismatch — cascading to a full
|
|
2177
|
-
// defaults reset that wipes maxTokens. Dual-emit strips both
|
|
2178
|
-
// both defaults restore to null.
|
|
2490
|
+
// defaults reset that wipes llm.default.maxTokens. Dual-emit strips both
|
|
2491
|
+
// sides so both defaults restore to null.
|
|
2179
2492
|
writeConfig({
|
|
2180
|
-
maxTokens: 1234,
|
|
2493
|
+
llm: { default: { maxTokens: 1234 } },
|
|
2181
2494
|
filing: { activeHoursStart: 5, activeHoursEnd: 5 },
|
|
2182
2495
|
});
|
|
2183
2496
|
const config = loadConfig();
|
|
2184
|
-
expect(config.maxTokens).toBe(1234);
|
|
2497
|
+
expect(config.llm.default.maxTokens).toBe(1234);
|
|
2185
2498
|
expect(config.filing.activeHoursStart).toBeNull();
|
|
2186
2499
|
expect(config.filing.activeHoursEnd).toBeNull();
|
|
2187
2500
|
});
|
|
@@ -2201,7 +2514,7 @@ describe("loadConfig with schema validation", () => {
|
|
|
2201
2514
|
expect(
|
|
2202
2515
|
(config.calls.voice as Record<string, unknown>).ttsProvider,
|
|
2203
2516
|
).toBeUndefined();
|
|
2204
|
-
expect(config.calls.model).toBeUndefined();
|
|
2517
|
+
expect((config.calls as Record<string, unknown>).model).toBeUndefined();
|
|
2205
2518
|
expect(config.calls.callerIdentity).toEqual({
|
|
2206
2519
|
allowPerCallOverride: true,
|
|
2207
2520
|
});
|