@vellumai/assistant 0.11.3 → 0.11.4-dev.202608190019.b94dbf2
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/AGENTS.md +9 -3
- package/ARCHITECTURE.md +32 -10
- package/docs/architecture/memory.md +43 -5
- package/docs/architecture/security.md +96 -152
- package/docs/architecture/turn-actor.md +70 -0
- package/docs/browser-use-architecture-phase2.md +128 -56
- package/docs/flux-turn-detection-spike.md +248 -0
- package/docs/guardian-request-flow.md +35 -0
- package/docs/stt-provider-onboarding.md +3 -1
- package/knip.json +3 -0
- 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__/url-normalization.test.ts +135 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/channels.ts +11 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +60 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/url-normalization.ts +107 -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__/url-normalization.test.ts +135 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/channels.ts +11 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +60 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/url-normalization.ts +107 -0
- package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +34 -0
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +166 -1
- package/node_modules/@vellumai/gateway-client/src/index.ts +2 -0
- package/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/url-normalization.test.ts +135 -0
- package/node_modules/@vellumai/service-contracts/src/channels.ts +11 -0
- package/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +60 -0
- package/node_modules/@vellumai/service-contracts/src/url-normalization.ts +107 -0
- package/openapi.yaml +289 -113
- package/package.json +1 -1
- package/scripts/voice-ttft-spike.ts +3 -3
- package/scripts/write-plugin-api-shim.ts +10 -0
- package/src/__tests__/app-compiler.test.ts +38 -3
- package/src/__tests__/app-control-flow.test.ts +1 -0
- package/src/__tests__/approval-routes-http.test.ts +2 -2
- package/src/__tests__/assistant-feature-flag-guard.test.ts +25 -3
- package/src/__tests__/attachments-store.test.ts +21 -12
- package/src/__tests__/byok-default-profile-ensure.test.ts +17 -0
- package/src/__tests__/call-setup-flow-name-capture.test.ts +0 -1
- package/src/__tests__/call-site-routing-provider.test.ts +1 -1
- package/src/__tests__/channel-availability-routes.test.ts +14 -1
- package/src/__tests__/channel-capabilities-dedupe.test.ts +214 -0
- package/src/__tests__/channel-delivery-store.test.ts +14 -14
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +4 -4
- package/src/__tests__/channel-setup-panel-ack.test.ts +1 -1
- package/src/__tests__/checker.test.ts +20 -314
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +6 -2
- package/src/__tests__/compaction-events.test.ts +8 -10
- package/src/__tests__/config-loader-backfill.test.ts +3 -3
- package/src/__tests__/config-schema.test.ts +25 -10
- package/src/__tests__/context-search-memory-v2-source.test.ts +0 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +8 -11
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +8 -11
- package/src/__tests__/conversation-agent-loop.test.ts +32 -21
- package/src/__tests__/conversation-attachments.test.ts +0 -1
- package/src/__tests__/conversation-attention-store.test.ts +63 -0
- package/src/__tests__/conversation-confirmation-signals.test.ts +112 -0
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +0 -4
- package/src/__tests__/conversation-fork-crud.test.ts +69 -0
- package/src/__tests__/conversation-fork-referential.test.ts +67 -0
- package/src/__tests__/conversation-fork-retrospective.test.ts +24 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +209 -0
- package/src/__tests__/conversation-notifiers-provenance.test.ts +59 -0
- package/src/__tests__/conversation-queue.test.ts +154 -4
- package/src/__tests__/conversation-routes-disk-view.test.ts +1 -1
- package/src/__tests__/conversation-routes-enabled-plugins.test.ts +1 -1
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +9 -9
- package/src/__tests__/conversation-routes-hidden-queue.test.ts +1 -1
- package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +187 -102
- package/src/__tests__/conversation-runtime-workspace.test.ts +14 -10
- package/src/__tests__/conversation-slash-queue.test.ts +3 -0
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-app-open.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-history-restored-completion.test.ts +21 -14
- package/src/__tests__/conversation-surfaces-queued-emit.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-standalone.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-state-update.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-table-action.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +1 -1
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +1 -1
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +1 -1
- package/src/__tests__/credential-prompt-route.test.ts +7 -10
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/cu-unified-flow.test.ts +1 -0
- package/src/__tests__/custom-profile-ensure.test.ts +5 -1
- package/src/__tests__/default-plugin-names-guard.test.ts +12 -1
- package/src/__tests__/discord-access-request-privacy.test.ts +5 -1
- package/src/__tests__/discord-requester-notice-privacy.test.ts +3 -3
- package/src/__tests__/document-append-idempotency.test.ts +233 -0
- package/src/__tests__/document-sync-tags.test.ts +0 -75
- package/src/__tests__/dynamic-skill-background-guard.test.ts +0 -2
- package/src/__tests__/edit-propagation.test.ts +107 -11
- package/src/__tests__/file-ops-service.test.ts +163 -30
- package/src/__tests__/filesystem-tools.test.ts +23 -24
- package/src/__tests__/gateway-only-guard.test.ts +2 -5
- package/src/__tests__/helpers/gateway-classify-mock.ts +27 -6
- package/src/__tests__/helpers/mock-actor-context.ts +49 -0
- package/src/__tests__/helpers/mock-conversation.ts +13 -1
- package/src/__tests__/host-file-read-tool.test.ts +16 -19
- package/src/__tests__/http-user-message-parity.test.ts +1 -1
- package/src/__tests__/init-feature-flag-overrides.test.ts +49 -0
- package/src/__tests__/injector-chain.test.ts +63 -41
- package/src/__tests__/injector-disk-pressure.test.ts +11 -23
- package/src/__tests__/inline-skill-load-permissions.test.ts +47 -36
- package/src/__tests__/llm-context-resolution.test.ts +73 -1
- package/src/__tests__/llm-schema.test.ts +5 -2
- package/src/__tests__/managed-skill-lifecycle.test.ts +7 -0
- package/src/__tests__/mcp-list-plugin-servers.test.ts +250 -0
- package/src/__tests__/media-generate-image.test.ts +131 -21
- package/src/__tests__/memory-retrieval-hook.test.ts +100 -7
- package/src/__tests__/messages-read-boundary-guard.test.ts +134 -0
- package/src/__tests__/mtime-cache.test.ts +3 -1
- package/src/__tests__/non-member-access-request.test.ts +0 -20
- package/src/__tests__/outbound-slack-persistence.test.ts +40 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +0 -4
- package/src/__tests__/plugin-api-store-credential.test.ts +261 -0
- package/src/__tests__/plugin-api-webhook-url.test.ts +10 -7
- package/src/__tests__/plugin-disabled-state.test.ts +2 -0
- package/src/__tests__/plugin-effective-enabled-set.test.ts +55 -3
- package/src/__tests__/plugin-execution-context.test.ts +73 -0
- package/src/__tests__/plugin-import-boundary-guard.test.ts +5 -1
- package/src/__tests__/plugin-import-boundary-reverse-guard.test.ts +7 -4
- package/src/__tests__/plugin-secret-pattern-contribution.test.ts +1 -1
- package/src/__tests__/post-compaction-reinjection-idempotency.test.ts +14 -7
- package/src/__tests__/provider-commit-message-generator.test.ts +20 -0
- package/src/__tests__/proxy-approval-callback.test.ts +1 -0
- package/src/__tests__/qdrant-manager.test.ts +14 -1
- package/src/__tests__/reaction-persistence.test.ts +200 -7
- package/src/__tests__/require-fresh-approval.test.ts +0 -4
- package/src/__tests__/risk-classification-boundary-guard.test.ts +115 -0
- package/src/__tests__/run-conversation-turn-persistence.test.ts +460 -105
- package/src/__tests__/run-due-schedules.test.ts +21 -0
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +187 -18
- package/src/__tests__/schedule-routes.test.ts +23 -0
- package/src/__tests__/schedule-store.test.ts +17 -0
- package/src/__tests__/scoped-approval-grants.test.ts +11 -6
- package/src/__tests__/secret-ingress-channel.test.ts +0 -1
- package/src/__tests__/secret-ingress-http.test.ts +1 -1
- package/src/__tests__/send-endpoint-busy.test.ts +3 -3
- package/src/__tests__/skills.test.ts +32 -0
- package/src/__tests__/slack-edit-ordering-characterization.test.ts +0 -1
- package/src/__tests__/starter-task-flow.test.ts +5 -4
- package/src/__tests__/subagent-call-site-routing.test.ts +31 -19
- package/src/__tests__/subagent-fork-prompt-role.test.ts +1 -1
- package/src/__tests__/subagent-spawn-and-await.test.ts +18 -17
- package/src/__tests__/subagent-tool-gate-mode.test.ts +1 -1
- package/src/__tests__/subagent-tools.test.ts +81 -101
- package/src/__tests__/surface-completion-in-flight-snapshot.test.ts +1 -0
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +1 -1
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +132 -5
- package/src/__tests__/tool-executor.test.ts +68 -39
- package/src/__tests__/turn-events-store.test.ts +43 -0
- package/src/__tests__/ui-choice-copy-surfaces.test.ts +1 -1
- package/src/__tests__/ui-shape-teaching.test.ts +33 -0
- package/src/__tests__/ui-visual-surface.test.ts +1 -1
- package/src/__tests__/ui-voice-picker-surface.test.ts +128 -0
- package/src/__tests__/ui-work-result-surface.test.ts +1 -1
- package/src/__tests__/user-plugin-loader.test.ts +3 -1
- package/src/__tests__/verification-control-plane-policy.test.ts +0 -2
- package/src/__tests__/visible-app-context.test.ts +16 -9
- package/src/__tests__/voice-config-update.test.ts +40 -0
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +5 -3
- package/src/__tests__/voice-session-bridge.test.ts +85 -29
- package/src/__tests__/worker-entrypoint-guards.test.ts +54 -0
- package/src/__tests__/worker-plugin-surface.test.ts +77 -0
- package/src/__tests__/workspace-migration-142-consolidate-voice-front-door.test.ts +158 -0
- package/src/__tests__/workspace-migration-143-repair-deprecated-codex-model-id.test.ts +133 -0
- package/src/__tests__/workspace-migration-144-convert-stranded-subscription-openai-profiles.test.ts +316 -0
- package/src/__tests__/workspace-migration-145-collapse-profile-bindings-to-entries.test.ts +325 -0
- package/src/__tests__/workspace-migration-146-repair-retired-fireworks-deepseek-flash-model-id.test.ts +235 -0
- package/src/acp/__tests__/acp-claude-oauth.test.ts +10 -2
- package/src/acp/__tests__/auth-required.test.ts +161 -0
- package/src/acp/acp-claude-oauth.ts +19 -2
- package/src/acp/agent-process.test.ts +100 -0
- package/src/acp/agent-process.ts +29 -26
- package/src/acp/auth-required.ts +102 -0
- package/src/acp/session-manager.test.ts +119 -0
- package/src/acp/session-manager.ts +76 -3
- package/src/api/events/acp-auth-required.ts +55 -0
- package/src/api/events/host-file.ts +2 -2
- package/src/api/index.ts +7 -0
- package/src/api/surfaces.ts +12 -3
- package/src/apps/app-store.ts +3 -0
- package/src/bundler/package-resolver.ts +2 -30
- package/src/calls/__tests__/voice-session-bridge.test.ts +194 -11
- package/src/calls/__tests__/voice-triage-escalate.test.ts +102 -0
- package/src/calls/call-controller.ts +19 -3
- package/src/calls/call-setup-flow.ts +0 -1
- package/src/calls/media-stream-stt-session.ts +15 -0
- package/src/calls/voice-session-bridge.ts +115 -41
- package/src/calls/voice-triage-escalate.ts +105 -2
- package/src/channels/__tests__/plugin-channel-declarations.test.ts +161 -0
- package/src/channels/config.ts +13 -0
- package/src/channels/plugin-channel-declarations.ts +108 -0
- package/src/channels/types.ts +30 -0
- package/src/cli/AGENTS.md +5 -2
- package/src/cli/bundled-modules.ts +29 -0
- package/src/cli/commands/credentials.help.ts +2 -2
- package/src/cli/commands/db/repair.ts +4 -8
- package/src/cli/commands/domain.ts +6 -3
- package/src/cli/commands/email.ts +6 -3
- package/src/cli/commands/inference-providers.ts +1 -1
- package/src/cli/commands/keys.ts +8 -3
- package/src/cli/commands/mcp.help.ts +13 -4
- package/src/cli/commands/mcp.ts +9 -0
- package/src/cli/commands/memory/__tests__/memory-v2.test.ts +57 -7
- package/src/cli/commands/memory/__tests__/memory-v3.test.ts +128 -5
- package/src/cli/commands/memory/index.help.ts +84 -28
- package/src/cli/commands/memory/index.ts +2 -0
- package/src/cli/commands/memory/memory-v2.ts +58 -54
- package/src/cli/commands/memory/memory-v3.ts +64 -0
- package/src/cli/commands/memory/memory-validate.ts +18 -0
- package/src/cli/commands/plugins.ts +85 -36
- package/src/cli/commands/schedules.ts +35 -1
- package/src/cli/commands/stt.help.ts +27 -2
- package/src/cli/commands/trust.ts +3 -14
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +39 -0
- package/src/cli/lib/bundled-marketplace.json +14 -1
- package/src/cli/lib/upgrade-plugin.ts +42 -0
- package/src/config/__tests__/balanced-model-experiment.test.ts +278 -0
- package/src/config/__tests__/default-profile-catalog.test.ts +34 -2
- package/src/config/__tests__/default-provider.test.ts +6 -1
- package/src/config/__tests__/profile-materialization.test.ts +75 -19
- package/src/config/assistant-feature-flags.ts +36 -15
- package/src/config/balanced-model-experiment.ts +35 -0
- package/src/config/bundled-skills/acp/SKILL.md +6 -7
- package/src/config/bundled-skills/document-editor/SKILL.md +2 -2
- package/src/config/bundled-skills/document-editor/TOOLS.json +2 -2
- package/src/config/bundled-skills/image-studio/SKILL.md +5 -4
- package/src/config/bundled-skills/image-studio/TOOLS.json +1 -1
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +101 -0
- package/src/config/bundled-skills/media-processing/services/preprocess.ts +14 -4
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-skills/settings/tools/navigate-settings-tab.test.ts +65 -0
- package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +7 -1
- package/src/config/bundled-skills/settings/tools/shared.ts +16 -0
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +19 -1
- package/src/config/bundled-skills/skill-management/TOOLS.json +9 -3
- package/src/config/bundled-skills/subagent/SKILL.md +17 -12
- package/src/config/bundled-skills/subagent/TOOLS.json +4 -4
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +22 -1
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +9 -2
- package/src/config/call-site-defaults.ts +11 -5
- package/src/config/default-profile-catalog.ts +179 -16
- package/src/config/default-profile-names.ts +4 -1
- package/src/config/default-provider-resolution.ts +4 -0
- package/src/config/feature-flag-registry.json +12 -12
- package/src/config/llm-context-resolution.ts +11 -3
- package/src/config/llm-resolver.ts +28 -1
- package/src/config/profile-materialization.ts +70 -22
- package/src/config/schemas/__tests__/live-voice.test.ts +107 -4
- package/src/config/schemas/call-site-catalog.ts +4 -4
- package/src/config/schemas/live-voice.ts +57 -23
- package/src/config/schemas/llm.ts +59 -32
- package/src/config/schemas/mcp.ts +23 -0
- package/src/config/schemas/plugin-updates.ts +6 -2
- package/src/config/schemas/stt.ts +1 -0
- package/src/config/skills.ts +9 -2
- package/src/context/outbound-sanitize.ts +96 -1
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +1 -1
- package/src/daemon/__tests__/plugin-mcp-reconcile.test.ts +82 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +15 -10
- package/src/daemon/conversation-agent-loop.ts +31 -19
- package/src/daemon/conversation-messaging.ts +5 -1
- package/src/daemon/conversation-notifiers.ts +20 -10
- package/src/daemon/conversation-process.ts +20 -6
- package/src/daemon/conversation-runtime-assembly.ts +12 -6
- package/src/daemon/conversation-store.ts +14 -4
- package/src/daemon/conversation-surfaces.ts +75 -26
- package/src/daemon/conversation-tool-setup.ts +3 -6
- package/src/daemon/conversation.ts +154 -51
- package/src/daemon/doordash-steps.ts +2 -2
- package/src/daemon/lifecycle.ts +14 -1
- package/src/daemon/mcp-reload-service.ts +36 -6
- package/src/daemon/process-message.ts +13 -26
- package/src/daemon/providers-setup.ts +6 -3
- package/src/daemon/trust-context-types.ts +29 -0
- package/src/daemon/trust-context.ts +12 -7
- package/src/daemon/wake-conversation-ops.ts +3 -2
- package/src/daemon/windows-compiled-entry.ts +4 -0
- package/src/documents/document-store.ts +143 -240
- package/src/hooks/hook-loader.ts +3 -3
- package/src/hooks/registry.ts +103 -45
- package/src/hooks/types.ts +5 -0
- package/src/inbound/__tests__/oauth-callback-url.test.ts +83 -0
- package/src/inbound/oauth-callback-url.ts +61 -0
- package/src/ipc/gateway-client.test.ts +1 -1
- package/src/ipc/gateway-client.ts +14 -21
- package/src/ipc/gateway-flag-listener.ts +17 -3
- package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +1 -104
- package/src/live-voice/__tests__/live-voice-events.test.ts +7 -8
- package/src/live-voice/__tests__/live-voice-flux-turn-end.test.ts +1050 -0
- package/src/live-voice/__tests__/live-voice-metrics.test.ts +115 -8
- package/src/live-voice/__tests__/live-voice-photo.test.ts +100 -0
- package/src/live-voice/__tests__/live-voice-progress.test.ts +60 -194
- package/src/live-voice/__tests__/live-voice-stt.test.ts +14 -0
- package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +29 -0
- package/src/live-voice/__tests__/live-voice-tts-session.test.ts +0 -483
- package/src/live-voice/__tests__/live-voice-vad.test.ts +0 -16
- package/src/live-voice/__tests__/progress-narration.test.ts +214 -0
- package/src/live-voice/live-voice-archive.ts +2 -0
- package/src/live-voice/live-voice-manager.ts +16 -3
- package/src/live-voice/live-voice-metrics.ts +57 -32
- package/src/live-voice/live-voice-photo.ts +1 -2
- package/src/live-voice/live-voice-session.ts +598 -323
- package/src/live-voice/progress-narration.ts +277 -0
- package/src/live-voice/protocol.ts +21 -1
- package/src/live-voice/windows-compiled-live-voice.ts +4 -0
- package/src/mcp/__tests__/effective-config.test.ts +238 -0
- package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +0 -1
- package/src/mcp/__tests__/mcp-oauth-client-registration.test.ts +200 -0
- package/src/mcp/__tests__/mcp-oauth-provider.test.ts +9 -9
- package/src/mcp/__tests__/plugin-server-credential-isolation.test.ts +95 -0
- package/src/mcp/client.ts +16 -11
- package/src/mcp/effective-config.ts +113 -0
- package/src/mcp/manager.ts +11 -6
- package/src/mcp/mcp-auth-orchestrator.ts +13 -22
- package/src/mcp/mcp-oauth-provider.ts +205 -240
- package/src/monitoring/__tests__/plugin-auto-update.test.ts +166 -3
- package/src/monitoring/control.ts +1 -0
- package/src/monitoring/db-integrity-sample.ts +4 -5
- package/src/monitoring/plugin-auto-update.ts +128 -24
- package/src/notifications/AGENTS.md +2 -0
- package/src/notifications/approval-card-data.ts +33 -0
- package/src/notifications/signal.ts +1 -0
- package/src/permissions/AGENTS.md +16 -0
- package/src/permissions/checker.test.ts +75 -122
- package/src/permissions/checker.ts +44 -560
- package/src/permissions/confirmation-guardian-request.test.ts +15 -11
- package/src/permissions/confirmation-guardian-request.ts +2 -2
- package/src/permissions/prompter.ts +1 -5
- package/src/permissions/question-guardian-request.test.ts +14 -6
- package/src/permissions/question-guardian-request.ts +1 -2
- package/src/persistence/attachments-store.ts +8 -1
- package/src/persistence/bookmark-crud.ts +3 -7
- package/src/persistence/conversation-attention-store.ts +16 -45
- package/src/persistence/conversation-crud.ts +33 -4
- package/src/persistence/conversation-lineage.ts +9 -0
- package/src/persistence/conversation-queries.ts +182 -52
- package/src/persistence/delivery-crud.ts +150 -36
- package/src/persistence/embeddings/qdrant-manager.ts +84 -49
- package/src/persistence/external-conversation-store.ts +32 -4
- package/src/persistence/llm-request-log-store.ts +4 -10
- package/src/persistence/llm-usage-store.ts +8 -3
- package/src/persistence/message-reads.test.ts +197 -0
- package/src/persistence/message-reads.ts +211 -0
- package/src/persistence/migrations/360-add-document-workspace-path.ts +5 -14
- package/src/persistence/migrations/366-chatgpt-subscription-row-identity.test.ts +120 -0
- package/src/persistence/migrations/366-chatgpt-subscription-row-identity.ts +62 -0
- package/src/persistence/real-user-turn-filter.ts +27 -3
- package/src/persistence/schema/documents.ts +4 -4
- package/src/persistence/steps.ts +9 -0
- package/src/plugin-api/__tests__/oauth-callback-url-export.test.ts +29 -0
- package/src/plugin-api/constants.ts +8 -0
- package/src/plugin-api/conversation-turn.ts +195 -5
- package/src/plugin-api/index.ts +38 -6
- package/src/plugin-api/resolve-credential.ts +3 -2
- package/src/plugin-api/store-credential.ts +146 -0
- package/src/plugin-api/vision-support.test.ts +1 -1
- package/src/plugin-api/webhook-url.ts +13 -11
- package/src/plugins/__tests__/mcp-servers.test.ts +371 -0
- package/src/plugins/defaults/main.ts +21 -7
- package/src/plugins/defaults/memory/AGENTS.md +15 -3
- package/src/plugins/defaults/memory/__tests__/buffer-format.test.ts +204 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-accounting.test.ts +72 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +4 -1
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-provider-path.test.ts +4 -1
- package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +0 -1
- package/src/plugins/defaults/memory/buffer-format.ts +165 -0
- package/src/plugins/defaults/memory/context-search/sources/conversations.ts +6 -0
- package/src/plugins/defaults/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +77 -0
- package/src/plugins/defaults/memory/graph/conversation-graph-memory.ts +24 -6
- package/src/plugins/defaults/memory/graph/image-ref-utils.ts +3 -0
- package/src/plugins/defaults/memory/graph/tool-handlers.ts +1 -30
- package/src/plugins/defaults/memory/graph-topology/pending-buffer.test.ts +34 -0
- package/src/plugins/defaults/memory/graph-topology/pending-buffer.ts +17 -24
- package/src/plugins/defaults/memory/hooks/post-compact.ts +1 -4
- package/src/plugins/defaults/memory/hooks/user-prompt-submit.ts +53 -5
- package/src/plugins/defaults/memory/indexer.ts +3 -1
- package/src/plugins/defaults/memory/memory-retrospective-accounting.ts +19 -7
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +4 -4
- package/src/plugins/defaults/memory/src/__tests__/memory-v3-gate-stats.test.ts +281 -0
- package/src/plugins/defaults/memory/src/memory-v2-routes.ts +12 -10
- package/src/plugins/defaults/memory/src/memory-v3-routes.ts +207 -0
- package/src/plugins/defaults/memory/substrate/__tests__/consolidation-job.test.ts +147 -0
- package/src/plugins/defaults/memory/substrate/__tests__/consolidation-prompt-flag-gating-guard.test.ts +8 -0
- package/src/plugins/defaults/memory/substrate/__tests__/edge-index.test.ts +0 -30
- package/src/plugins/defaults/memory/substrate/__tests__/ingest.test.ts +73 -1
- package/src/plugins/defaults/memory/substrate/__tests__/page-index.test.ts +37 -0
- package/src/plugins/defaults/memory/substrate/__tests__/page-links.test.ts +208 -0
- package/src/plugins/defaults/memory/substrate/__tests__/prompts-consolidation.test.ts +158 -1
- package/src/plugins/defaults/memory/substrate/__tests__/static-context.test.ts +195 -58
- package/src/plugins/defaults/memory/substrate/consolidation-job.ts +93 -24
- package/src/plugins/defaults/memory/substrate/edge-index.ts +0 -31
- package/src/plugins/defaults/memory/substrate/ingest.ts +59 -0
- package/src/plugins/defaults/memory/substrate/page-index.ts +35 -8
- package/src/plugins/defaults/memory/substrate/page-links.ts +133 -0
- package/src/plugins/defaults/memory/substrate/page-store.ts +10 -0
- package/src/plugins/defaults/memory/substrate/prompts/consolidation.ts +124 -34
- package/src/plugins/defaults/memory/substrate/skill-content.ts +8 -1
- package/src/plugins/defaults/memory/substrate/static-context.ts +160 -33
- package/src/plugins/defaults/memory/substrate/sweep-job.ts +2 -4
- package/src/plugins/defaults/memory/v1/graph/extraction.ts +3 -1
- package/src/plugins/defaults/memory/v3/__tests__/injection.test.ts +18 -0
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +66 -1
- package/src/plugins/defaults/memory/v3/card.ts +9 -9
- package/src/plugins/defaults/memory/v3/core-set.test.ts +7 -0
- package/src/plugins/defaults/memory/v3/core-set.ts +5 -1
- package/src/plugins/defaults/memory/v3/edge.ts +13 -57
- package/src/plugins/defaults/memory/v3/injector.ts +8 -0
- package/src/plugins/defaults/memory/v3/prune.ts +2 -0
- package/src/plugins/defaults/memory/v3/selection-log-store.ts +2 -0
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +23 -9
- package/src/plugins/defaults/memory/worker-control.ts +1 -0
- package/src/plugins/defaults/memory/worker.ts +6 -3
- package/src/plugins/defaults/worker-entrypoints.ts +3 -0
- package/src/plugins/external-plugin-loader.ts +47 -0
- package/src/plugins/mcp-servers.ts +361 -0
- package/src/plugins/mtime-cache.ts +37 -46
- package/src/plugins/pipeline.ts +14 -7
- package/src/plugins/plugin-execution-context.ts +35 -11
- package/src/plugins/worker-plugin-surface.ts +33 -0
- package/src/prompts/templates/system-sections.ts +0 -7
- package/src/providers/__tests__/connection-model-compat.test.ts +1 -1
- package/src/providers/__tests__/context-overflow-error.test.ts +24 -0
- package/src/providers/__tests__/dispatch-connection-routing.test.ts +214 -2
- package/src/providers/__tests__/preflight-resolved-config.test.ts +57 -0
- package/src/providers/__tests__/retry-callsite.test.ts +25 -2
- package/src/providers/anthropic/__tests__/pause-turn-continuation.test.ts +170 -0
- package/src/providers/anthropic/client.ts +332 -241
- package/src/providers/call-site-routing.ts +30 -3
- package/src/providers/connection-resolution.ts +194 -11
- package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +4 -0
- package/src/providers/inference/adapter-factory.ts +3 -0
- package/src/providers/inference/auth.ts +6 -0
- package/src/providers/inference/connection-availability.ts +24 -2
- package/src/providers/inference/connections.ts +2 -0
- package/src/providers/model-catalog.ts +3 -3
- package/src/providers/model-intents.ts +28 -8
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +163 -40
- package/src/providers/openai/__tests__/tool-choice-mapping.test.ts +125 -2
- package/src/providers/openai/chat-completions-provider.ts +133 -36
- package/src/providers/openai/codex-models.ts +2 -1
- package/src/providers/provider-send-message.ts +32 -3
- package/src/providers/speech-to-text/__tests__/deepgram-flux-frames.test.ts +433 -0
- package/src/providers/speech-to-text/__tests__/deepgram-flux-realtime.test.ts +625 -0
- package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +34 -0
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +285 -6
- package/src/providers/speech-to-text/deepgram-flux-frames.ts +395 -0
- package/src/providers/speech-to-text/deepgram-flux-realtime.ts +679 -0
- package/src/providers/speech-to-text/provider-catalog.ts +99 -8
- package/src/providers/speech-to-text/resolve.ts +25 -2
- package/src/routes/control.ts +1 -0
- package/src/routes/route-host-client.ts +1 -0
- package/src/routes/route-host-protocol.ts +7 -0
- package/src/routes/worker.ts +48 -15
- package/src/runtime/AGENTS.md +16 -17
- package/src/runtime/access-request-helper.ts +9 -12
- package/src/runtime/agent-wake.ts +18 -15
- package/src/runtime/effective-capabilities.test.ts +43 -0
- package/src/runtime/effective-capabilities.ts +27 -0
- package/src/runtime/guardian-reply-router.ts +6 -2
- package/src/runtime/pre-first-message-gate.ts +4 -0
- package/src/runtime/routes/__tests__/acp-claude-auth-routes.test.ts +12 -4
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +522 -2
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +52 -0
- package/src/runtime/routes/__tests__/default-provider-routes.test.ts +61 -0
- package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +44 -0
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +102 -1
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +132 -35
- package/src/runtime/routes/__tests__/schedule-routes-disarm-reason.test.ts +215 -0
- package/src/runtime/routes/__tests__/stt-routes.test.ts +25 -0
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +55 -6
- package/src/runtime/routes/__tests__/user-route-dispatcher-host.test.ts +52 -1
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +133 -1
- package/src/runtime/routes/channel-availability-routes.ts +32 -14
- package/src/runtime/routes/channel-route-shared.ts +0 -6
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +6 -6
- package/src/runtime/routes/conversation-list-routes.ts +181 -23
- package/src/runtime/routes/conversation-management-routes.ts +17 -12
- package/src/runtime/routes/conversation-query-routes.ts +40 -27
- package/src/runtime/routes/conversation-routes.ts +43 -29
- package/src/runtime/routes/credential-prompt-routes.ts +4 -7
- package/src/runtime/routes/credential-routes.ts +26 -82
- package/src/runtime/routes/default-provider-routes.ts +15 -0
- package/src/runtime/routes/documents-routes.ts +3 -222
- package/src/runtime/routes/inbound-message-handler.ts +21 -45
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +0 -1
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +0 -9
- package/src/runtime/routes/inbound-stages/admission-policy.ts +1 -17
- package/src/runtime/routes/inbound-stages/bootstrap-intercept.test.ts +0 -1
- package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +2 -3
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +101 -79
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +0 -1
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +12 -7
- package/src/runtime/routes/inbound-stages/reaction-intercept.test.ts +91 -8
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +72 -79
- package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +2 -3
- package/src/runtime/routes/inference-profiles-routes.ts +20 -11
- package/src/runtime/routes/inference-provider-connection-routes.ts +77 -15
- package/src/runtime/routes/log-export-routes.ts +3 -0
- package/src/runtime/routes/mcp-auth-routes.ts +148 -57
- package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +2 -0
- package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +3 -0
- package/src/runtime/routes/playground/inject-failures.ts +2 -2
- package/src/runtime/routes/playground/reset-circuit.ts +1 -1
- package/src/runtime/routes/plugins-routes.ts +38 -8
- package/src/runtime/routes/schedule-routes.ts +94 -7
- package/src/runtime/routes/settings-routes.ts +6 -6
- package/src/runtime/routes/stt-routes.ts +31 -25
- package/src/runtime/routes/surface-action-routes.ts +20 -19
- package/src/runtime/routes/surface-conversation-resolver.ts +3 -0
- package/src/runtime/routes/user-route-dispatcher.ts +69 -15
- package/src/runtime/routes/user-route-import.ts +108 -0
- package/src/runtime/routes/user-route-resolution.ts +18 -1
- package/src/runtime/routes/workspace-routes.ts +0 -9
- package/src/runtime/routes/workspace-utils.ts +3 -13
- package/src/runtime/services/conversation-serializer.ts +7 -2
- package/src/schedule/__tests__/plugin-schedule-declarations.test.ts +68 -5
- package/src/schedule/__tests__/plugin-schedule-reconciler.test.ts +81 -0
- package/src/schedule/plugin-schedule-availability.ts +58 -0
- package/src/schedule/plugin-schedule-declarations.ts +23 -27
- package/src/schedule/plugin-schedule-reconciler.ts +12 -3
- package/src/schedule/schedule-store.ts +5 -1
- package/src/schedule/scheduler.ts +9 -4
- package/src/schedule/worker-control.ts +1 -0
- package/src/schedule/worker.ts +6 -0
- package/src/security/oauth2.ts +6 -22
- package/src/stt/__tests__/daemon-batch-transcriber.test.ts +22 -0
- package/src/stt/__tests__/types.test.ts +94 -0
- package/src/stt/daemon-batch-transcriber.ts +10 -0
- package/src/stt/stt-stream-session.ts +8 -4
- package/src/stt/types.ts +103 -0
- package/src/subagent/__tests__/consult-prompt.test.ts +26 -15
- package/src/subagent/consult-context.ts +11 -11
- package/src/subagent/consult-prompt.ts +26 -35
- package/src/subagent/manager.ts +21 -40
- package/src/subagent/notify.ts +7 -1
- package/src/subagent/types.ts +15 -12
- package/src/tools/__tests__/tool-input-schemas.test.ts +7 -7
- package/src/tools/acp/spawn.test.ts +97 -0
- package/src/tools/acp/spawn.ts +38 -4
- package/src/tools/credentials/ref-parse.ts +35 -0
- package/src/tools/credentials/resolve.ts +4 -10
- package/src/tools/credentials/store.ts +168 -0
- package/src/tools/document/document-tool.ts +12 -3
- package/src/tools/executor.ts +53 -15
- package/src/tools/filesystem/read.ts +27 -10
- package/src/tools/host-filesystem/read.ts +27 -15
- package/src/tools/network/url-safety.ts +9 -16
- package/src/tools/permission-checker.ts +43 -52
- package/src/tools/registry.ts +2 -1
- package/src/tools/shared/filesystem/file-ops-service.ts +63 -35
- package/src/tools/shared/filesystem/legacy-read-args.ts +22 -0
- package/src/tools/shared/filesystem/types.ts +5 -5
- package/src/tools/skills/scaffold-managed.ts +25 -7
- package/src/tools/subagent/spawn.ts +28 -88
- package/src/tools/tool-types.ts +26 -13
- package/src/tools/types.ts +6 -6
- package/src/tools/ui-surface/surface-shape-docs.ts +12 -1
- package/src/tools/workflows/run-workflow.ts +1 -2
- package/src/tts/__tests__/reasoning-tag-filter.test.ts +78 -0
- package/src/tts/reasoning-tag-filter.ts +89 -0
- package/src/util/__tests__/worker-process-command.test.ts +37 -0
- package/src/util/logger.ts +16 -0
- package/src/util/think-tag-stream.ts +95 -0
- package/src/util/worker-process.ts +37 -4
- package/src/windows-compiled-cli.ts +32 -0
- package/src/windows-compiled-entry.ts +4 -0
- package/src/windows-compiled-logger.ts +6 -0
- package/src/windows-compiled-worker-entry.ts +29 -0
- package/src/workspace/byok-default-profile-ensure.ts +76 -24
- package/src/workspace/custom-profile-ensure.ts +4 -24
- package/src/workspace/migrations/142-consolidate-voice-front-door.ts +70 -0
- package/src/workspace/migrations/143-repair-deprecated-codex-model-id.ts +134 -0
- package/src/workspace/migrations/144-convert-stranded-subscription-openai-profiles.ts +265 -0
- package/src/workspace/migrations/145-collapse-profile-bindings-to-entries.ts +328 -0
- package/src/workspace/migrations/146-repair-retired-fireworks-deepseek-flash-model-id.ts +195 -0
- package/src/workspace/migrations/__tests__/141-stt-english-default-to-multilingual.test.ts +0 -10
- package/src/workspace/migrations/registry.ts +10 -0
- package/src/workspace/provider-commit-message-generator.ts +7 -5
- package/src/__tests__/document-workspace-file.test.ts +0 -467
- package/src/live-voice/__tests__/front-decision.test.ts +0 -645
- package/src/live-voice/front-decision.ts +0 -476
- package/src/permissions/ipc-risk-types.ts +0 -143
- package/src/permissions/risk-types.ts +0 -76
- package/src/subagent/__tests__/consult-transcript.test.ts +0 -184
- package/src/subagent/consult-transcript.ts +0 -90
|
@@ -0,0 +1,278 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { afterEach, describe, expect, test } from "bun:test";
|
|
4
|
+
|
|
5
|
+
import type { z } from "zod";
|
|
6
|
+
|
|
7
|
+
import { setOverridesForTesting } from "../../__tests__/feature-flag-test-helpers.js";
|
|
8
|
+
import {
|
|
9
|
+
catalogMaxOutputTokens,
|
|
10
|
+
isModelInCatalog,
|
|
11
|
+
} from "../../providers/model-catalog.js";
|
|
12
|
+
import { getManagedUpstream } from "../../providers/vellum-model-routing.js";
|
|
13
|
+
import { BALANCED_MODEL_EXPERIMENT_FLAG_KEY } from "../balanced-model-experiment.js";
|
|
14
|
+
import {
|
|
15
|
+
CODE_DEFAULT_PROFILE_ENTRIES,
|
|
16
|
+
getEffectiveProfilesForProvider,
|
|
17
|
+
resolveDefaultProfileForProvider,
|
|
18
|
+
} from "../default-profile-catalog.js";
|
|
19
|
+
import { clearCachedOverrides } from "../feature-flag-cache.js";
|
|
20
|
+
import { resolveCallSiteConfig } from "../llm-resolver.js";
|
|
21
|
+
import {
|
|
22
|
+
type DefaultProviderConfig,
|
|
23
|
+
LLMSchema,
|
|
24
|
+
type ProfileEntry,
|
|
25
|
+
} from "../schemas/llm.js";
|
|
26
|
+
|
|
27
|
+
// The `experiment-balanced-model-2026-08-06` arm repoints the model the managed
|
|
28
|
+
// Balanced profile resolves to. Both the runtime resolver and the client-facing
|
|
29
|
+
// profile listing go through `defaultProfileBodyForProvider`, so both are
|
|
30
|
+
// exercised here: a disagreement between them shows the user one model beside a
|
|
31
|
+
// profile that runs another.
|
|
32
|
+
|
|
33
|
+
const FLAG = BALANCED_MODEL_EXPERIMENT_FLAG_KEY;
|
|
34
|
+
const SHIPPED_MODEL = "gpt-5.6-luna";
|
|
35
|
+
const GLM_MODEL = "accounts/fireworks/models/glm-5p2";
|
|
36
|
+
|
|
37
|
+
function setArm(value: boolean | string): void {
|
|
38
|
+
setOverridesForTesting({ [FLAG]: value });
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const managed: DefaultProviderConfig = { provider: "vellum" };
|
|
42
|
+
|
|
43
|
+
function llmWithActiveBalanced(
|
|
44
|
+
overrides: Record<string, unknown> = {},
|
|
45
|
+
): z.infer<typeof LLMSchema> {
|
|
46
|
+
return LLMSchema.parse({
|
|
47
|
+
profiles: {},
|
|
48
|
+
profileOrder: [],
|
|
49
|
+
activeProfile: "balanced",
|
|
50
|
+
defaultProvider: managed,
|
|
51
|
+
...overrides,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
afterEach(() => {
|
|
56
|
+
clearCachedOverrides();
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
describe("balanced-model experiment arms", () => {
|
|
60
|
+
test("terra repoints mainAgent at gpt-5.6-terra on the managed connection", () => {
|
|
61
|
+
setArm("terra");
|
|
62
|
+
const resolved = resolveCallSiteConfig(
|
|
63
|
+
"mainAgent",
|
|
64
|
+
llmWithActiveBalanced(),
|
|
65
|
+
);
|
|
66
|
+
expect(resolved.model).toBe("gpt-5.6-terra");
|
|
67
|
+
expect(resolved.provider).toBe("vellum");
|
|
68
|
+
expect(getManagedUpstream("gpt-5.6-terra")).toBe("openai");
|
|
69
|
+
|
|
70
|
+
const entry = resolveDefaultProfileForProvider(
|
|
71
|
+
undefined,
|
|
72
|
+
"balanced",
|
|
73
|
+
managed,
|
|
74
|
+
);
|
|
75
|
+
expect(entry?.model).toBe("gpt-5.6-terra");
|
|
76
|
+
expect(entry?.provider).toBe("vellum");
|
|
77
|
+
// Routing-identity providers derive their connection per request.
|
|
78
|
+
expect(entry?.provider_connection).toBeUndefined();
|
|
79
|
+
expect(entry?.source).toBe("managed");
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test("glm-5p2 repoints mainAgent at GLM 5.2 within the model's output cap", () => {
|
|
83
|
+
setArm("glm-5p2");
|
|
84
|
+
const resolved = resolveCallSiteConfig(
|
|
85
|
+
"mainAgent",
|
|
86
|
+
llmWithActiveBalanced(),
|
|
87
|
+
);
|
|
88
|
+
expect(resolved.model).toBe(GLM_MODEL);
|
|
89
|
+
expect(resolved.provider).toBe("vellum");
|
|
90
|
+
|
|
91
|
+
const upstream = getManagedUpstream(GLM_MODEL);
|
|
92
|
+
expect(upstream).toBe("fireworks");
|
|
93
|
+
const cap = catalogMaxOutputTokens(upstream as string, GLM_MODEL);
|
|
94
|
+
expect(cap).toBeDefined();
|
|
95
|
+
expect(resolved.maxTokens).toBeLessThanOrEqual(cap as number);
|
|
96
|
+
// Only the model moves: the shipped token budget stands.
|
|
97
|
+
expect(resolved.maxTokens).toBe(
|
|
98
|
+
CODE_DEFAULT_PROFILE_ENTRIES.balanced.maxTokens as number,
|
|
99
|
+
);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test("an arm changes only the model of the managed balanced body", () => {
|
|
103
|
+
setArm("terra");
|
|
104
|
+
const entry = resolveDefaultProfileForProvider(
|
|
105
|
+
undefined,
|
|
106
|
+
"balanced",
|
|
107
|
+
managed,
|
|
108
|
+
);
|
|
109
|
+
const shipped = CODE_DEFAULT_PROFILE_ENTRIES.balanced;
|
|
110
|
+
expect(entry).toEqual({ ...shipped, model: "gpt-5.6-terra" });
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
test("the other default profiles are untouched by an arm", () => {
|
|
114
|
+
setArm("glm-5p2");
|
|
115
|
+
for (const key of [
|
|
116
|
+
"quality-optimized",
|
|
117
|
+
"cost-optimized",
|
|
118
|
+
"latency-optimized",
|
|
119
|
+
]) {
|
|
120
|
+
expect(
|
|
121
|
+
resolveDefaultProfileForProvider(undefined, key, managed)?.model,
|
|
122
|
+
).toBe(CODE_DEFAULT_PROFILE_ENTRIES[key].model);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
test("every pinned arm model is managed-routable and in its upstream catalog", () => {
|
|
127
|
+
for (const model of ["gpt-5.6-terra", GLM_MODEL]) {
|
|
128
|
+
const upstream = getManagedUpstream(model);
|
|
129
|
+
expect(upstream).not.toBeNull();
|
|
130
|
+
expect(isModelInCatalog(upstream as string, model)).toBe(true);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
describe("balanced-model experiment fallbacks", () => {
|
|
136
|
+
const shippedCases: [string, () => void][] = [
|
|
137
|
+
["the flag is unset", () => clearCachedOverrides()],
|
|
138
|
+
["no override is present", () => setOverridesForTesting({})],
|
|
139
|
+
["the arm is control", () => setArm("control")],
|
|
140
|
+
["the arm is an unknown string", () => setArm("gpt-9-does-not-exist")],
|
|
141
|
+
["the arm is the empty string", () => setArm("")],
|
|
142
|
+
["the value is boolean true", () => setArm(true)],
|
|
143
|
+
["the value is boolean false", () => setArm(false)],
|
|
144
|
+
// The arm is remote input, so it can name an Object.prototype member. The
|
|
145
|
+
// pin table is a Map, which has no such members to inherit.
|
|
146
|
+
["the arm is constructor", () => setArm("constructor")],
|
|
147
|
+
["the arm is toString", () => setArm("toString")],
|
|
148
|
+
["the arm is valueOf", () => setArm("valueOf")],
|
|
149
|
+
["the arm is __proto__", () => setArm("__proto__")],
|
|
150
|
+
["the arm is hasOwnProperty", () => setArm("hasOwnProperty")],
|
|
151
|
+
];
|
|
152
|
+
|
|
153
|
+
for (const [label, seed] of shippedCases) {
|
|
154
|
+
test(`balanced stays on the shipped model when ${label}`, () => {
|
|
155
|
+
seed();
|
|
156
|
+
expect(
|
|
157
|
+
resolveDefaultProfileForProvider(undefined, "balanced", managed)?.model,
|
|
158
|
+
).toBe(SHIPPED_MODEL);
|
|
159
|
+
expect(
|
|
160
|
+
resolveCallSiteConfig("mainAgent", llmWithActiveBalanced()).model,
|
|
161
|
+
).toBe(SHIPPED_MODEL);
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
test("the shipped catalog body is the control arm", () => {
|
|
166
|
+
expect(CODE_DEFAULT_PROFILE_ENTRIES.balanced.model).toBe(SHIPPED_MODEL);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
test("the registry default is control, which the override-only flag read assumes", () => {
|
|
170
|
+
const registryPath = join(
|
|
171
|
+
import.meta.dirname,
|
|
172
|
+
"..",
|
|
173
|
+
"..",
|
|
174
|
+
"..",
|
|
175
|
+
"..",
|
|
176
|
+
"meta",
|
|
177
|
+
"feature-flags",
|
|
178
|
+
"feature-flag-registry.json",
|
|
179
|
+
);
|
|
180
|
+
const registry = JSON.parse(readFileSync(registryPath, "utf-8")) as {
|
|
181
|
+
flags: {
|
|
182
|
+
key: string;
|
|
183
|
+
scope: string;
|
|
184
|
+
defaultEnabled: boolean | string;
|
|
185
|
+
values?: string[];
|
|
186
|
+
}[];
|
|
187
|
+
};
|
|
188
|
+
const flag = registry.flags.find((entry) => entry.key === FLAG);
|
|
189
|
+
expect(flag).toBeDefined();
|
|
190
|
+
expect(flag?.scope).toBe("assistant");
|
|
191
|
+
expect(flag?.defaultEnabled).toBe("control");
|
|
192
|
+
expect(flag?.values).toEqual(["control", "terra", "glm-5p2"]);
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
describe("balanced-model experiment boundaries", () => {
|
|
197
|
+
test("a user-owned balanced shadow wins over the arm", () => {
|
|
198
|
+
setArm("terra");
|
|
199
|
+
const profiles: Record<string, ProfileEntry> = {
|
|
200
|
+
balanced: { source: "user", provider: "openai", model: "gpt-5.5" },
|
|
201
|
+
};
|
|
202
|
+
expect(
|
|
203
|
+
resolveDefaultProfileForProvider(profiles, "balanced", managed),
|
|
204
|
+
).toEqual(profiles.balanced);
|
|
205
|
+
expect(
|
|
206
|
+
resolveCallSiteConfig("mainAgent", llmWithActiveBalanced({ profiles }))
|
|
207
|
+
.model,
|
|
208
|
+
).toBe("gpt-5.5");
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
test("a managed-source stub still resolves to the arm's body", () => {
|
|
212
|
+
setArm("terra");
|
|
213
|
+
const profiles: Record<string, ProfileEntry> = {
|
|
214
|
+
balanced: { source: "managed", label: "My Balanced" },
|
|
215
|
+
};
|
|
216
|
+
const entry = resolveDefaultProfileForProvider(
|
|
217
|
+
profiles,
|
|
218
|
+
"balanced",
|
|
219
|
+
managed,
|
|
220
|
+
);
|
|
221
|
+
expect(entry?.model).toBe("gpt-5.6-terra");
|
|
222
|
+
expect(entry?.label).toBe("My Balanced");
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
test("the chatgpt and BYOK columns stay out of the experiment", () => {
|
|
226
|
+
setArm("terra");
|
|
227
|
+
for (const provider of ["anthropic", "openai", "chatgpt"] as const) {
|
|
228
|
+
const armed = resolveDefaultProfileForProvider(undefined, "balanced", {
|
|
229
|
+
provider,
|
|
230
|
+
});
|
|
231
|
+
clearCachedOverrides();
|
|
232
|
+
const shipped = resolveDefaultProfileForProvider(undefined, "balanced", {
|
|
233
|
+
provider,
|
|
234
|
+
});
|
|
235
|
+
expect(armed).toEqual(shipped as ProfileEntry);
|
|
236
|
+
expect(armed?.provider).toBe(provider);
|
|
237
|
+
setArm("terra");
|
|
238
|
+
}
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
test("an install with no defaultProvider still picks up the arm", () => {
|
|
242
|
+
setArm("glm-5p2");
|
|
243
|
+
expect(
|
|
244
|
+
resolveDefaultProfileForProvider(undefined, "balanced", null)?.model,
|
|
245
|
+
).toBe(GLM_MODEL);
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
describe("client-facing profile listing", () => {
|
|
250
|
+
test("reports the arm's model so the UI matches what runs", () => {
|
|
251
|
+
setArm("terra");
|
|
252
|
+
const profiles = getEffectiveProfilesForProvider(undefined, managed);
|
|
253
|
+
expect(profiles.balanced?.model).toBe("gpt-5.6-terra");
|
|
254
|
+
expect(profiles["quality-optimized"]?.model).toBe(
|
|
255
|
+
CODE_DEFAULT_PROFILE_ENTRIES["quality-optimized"].model,
|
|
256
|
+
);
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
test("reports the shipped model on the control arm", () => {
|
|
260
|
+
setArm("control");
|
|
261
|
+
expect(
|
|
262
|
+
getEffectiveProfilesForProvider(undefined, managed).balanced?.model,
|
|
263
|
+
).toBe(SHIPPED_MODEL);
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
test("agrees with the runtime resolver on every arm", () => {
|
|
267
|
+
for (const arm of ["control", "terra", "glm-5p2", "nonsense"]) {
|
|
268
|
+
setArm(arm);
|
|
269
|
+
const listed = getEffectiveProfilesForProvider(undefined, managed)
|
|
270
|
+
.balanced?.model;
|
|
271
|
+
const resolved = resolveCallSiteConfig(
|
|
272
|
+
"mainAgent",
|
|
273
|
+
llmWithActiveBalanced(),
|
|
274
|
+
).model;
|
|
275
|
+
expect(listed).toBe(resolved as string);
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
});
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
CODE_DEFAULT_PROFILE_ENTRIES,
|
|
8
8
|
getEffectiveProfile,
|
|
9
9
|
getEffectiveProfiles,
|
|
10
|
+
getEffectiveProfilesForProvider,
|
|
10
11
|
PROFILE_IMPLS,
|
|
11
12
|
resolveDefaultProfileForProvider,
|
|
12
13
|
} from "../default-profile-catalog.js";
|
|
@@ -22,6 +23,7 @@ import {
|
|
|
22
23
|
import {
|
|
23
24
|
type DefaultProviderConfig,
|
|
24
25
|
type LLMCallSite,
|
|
26
|
+
LLMCallSiteEnum,
|
|
25
27
|
LLMSchema,
|
|
26
28
|
type ProfileEntry,
|
|
27
29
|
} from "../schemas/llm.js";
|
|
@@ -245,7 +247,10 @@ describe("resolver integration", () => {
|
|
|
245
247
|
},
|
|
246
248
|
});
|
|
247
249
|
const body = CODE_DEFAULT_PROFILE_ENTRIES["latency-optimized"]!;
|
|
248
|
-
for (const callSite of [
|
|
250
|
+
for (const callSite of [
|
|
251
|
+
"voiceFrontDoor",
|
|
252
|
+
"voiceProgressNarration",
|
|
253
|
+
] as const) {
|
|
249
254
|
const resolved = resolveCallSiteConfig(callSite, llm);
|
|
250
255
|
expect(resolved.model).toBe(body.model as string);
|
|
251
256
|
expect(resolved.model).not.toBe("claude-opus-4-6");
|
|
@@ -265,6 +270,12 @@ describe("resolver integration", () => {
|
|
|
265
270
|
});
|
|
266
271
|
|
|
267
272
|
describe("schema validation", () => {
|
|
273
|
+
test("voiceFrontDoor is the only front callsite", () => {
|
|
274
|
+
expect(
|
|
275
|
+
LLMCallSiteEnum.options.filter((callSite) => callSite.includes("Front")),
|
|
276
|
+
).toEqual(["voiceFrontDoor"]);
|
|
277
|
+
});
|
|
278
|
+
|
|
268
279
|
test("always-available default names are valid references; os-beta only when materialized", () => {
|
|
269
280
|
expect(() => LLMSchema.parse({ activeProfile: "balanced" })).not.toThrow();
|
|
270
281
|
expect(() =>
|
|
@@ -323,7 +334,7 @@ describe("resolveDefaultProfileForProvider", () => {
|
|
|
323
334
|
expect(typeof entry?.model).toBe("string");
|
|
324
335
|
expect(entry?.provider).toBeDefined();
|
|
325
336
|
// Identity columns stamp no connection; BYOK columns always do.
|
|
326
|
-
if (entry?.provider === "vellum") {
|
|
337
|
+
if (entry?.provider === "vellum" || entry?.provider === "chatgpt") {
|
|
327
338
|
expect(entry?.provider_connection).toBeUndefined();
|
|
328
339
|
} else {
|
|
329
340
|
expect(entry?.provider_connection).toBeDefined();
|
|
@@ -333,6 +344,27 @@ describe("resolveDefaultProfileForProvider", () => {
|
|
|
333
344
|
}
|
|
334
345
|
});
|
|
335
346
|
|
|
347
|
+
test("the chatgpt column resolves Codex-pinned models with no connection stamp", () => {
|
|
348
|
+
const byKey: Record<string, string> = {
|
|
349
|
+
balanced: "gpt-5.6-luna",
|
|
350
|
+
"quality-optimized": "gpt-5.6-sol",
|
|
351
|
+
"cost-optimized": "gpt-5.6-luna",
|
|
352
|
+
"latency-optimized": "gpt-5.6-luna",
|
|
353
|
+
};
|
|
354
|
+
const effective = getEffectiveProfilesForProvider(undefined, dp("chatgpt"));
|
|
355
|
+
for (const [key, model] of Object.entries(byKey)) {
|
|
356
|
+
const entry = effective[key];
|
|
357
|
+
expect(entry?.provider).toBe("chatgpt");
|
|
358
|
+
expect(entry?.model).toBe(model);
|
|
359
|
+
expect(entry?.provider_connection).toBeUndefined();
|
|
360
|
+
expect(entry?.source).toBe("managed");
|
|
361
|
+
}
|
|
362
|
+
// Cost and Speed both opt fully out of reasoning.
|
|
363
|
+
expect(effective["cost-optimized"]?.effort).toBe("none");
|
|
364
|
+
expect(effective["latency-optimized"]?.effort).toBe("none");
|
|
365
|
+
expect(effective.balanced?.thinking?.enabled).toBe(true);
|
|
366
|
+
});
|
|
367
|
+
|
|
336
368
|
test("a provider without a named matrix column materializes from the shared BYOK templates", () => {
|
|
337
369
|
const entry = resolveDefaultProfileForProvider(
|
|
338
370
|
undefined,
|
|
@@ -157,6 +157,12 @@ describe("resolveDefaultConnectionName", () => {
|
|
|
157
157
|
);
|
|
158
158
|
});
|
|
159
159
|
|
|
160
|
+
test("chatgpt resolves to the canonical subscription connection name", () => {
|
|
161
|
+
expect(resolveDefaultConnectionName({ provider: "chatgpt" })).toBe(
|
|
162
|
+
"chatgpt-subscription",
|
|
163
|
+
);
|
|
164
|
+
});
|
|
165
|
+
|
|
160
166
|
test("every other provider resolves to its personal connection", () => {
|
|
161
167
|
expect(resolveDefaultConnectionName({ provider: "anthropic" })).toBe(
|
|
162
168
|
"anthropic-personal",
|
|
@@ -221,7 +227,6 @@ describe("getDefaultProvider / setDefaultProvider", () => {
|
|
|
221
227
|
test("setDefaultProvider validates the provider before writing", () => {
|
|
222
228
|
expect(() =>
|
|
223
229
|
setDefaultProvider({
|
|
224
|
-
// @ts-expect-error deliberately invalid for the test
|
|
225
230
|
provider: "not-a-provider",
|
|
226
231
|
}),
|
|
227
232
|
).toThrow();
|
|
@@ -1,4 +1,17 @@
|
|
|
1
|
-
import { describe, expect, test } from "bun:test";
|
|
1
|
+
import { describe, expect, mock, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
// Entry-name folds are gated on the named row existing with an agreeing
|
|
4
|
+
// kind, so the tests control the row store directly.
|
|
5
|
+
const connectionRows = new Map<string, { name: string; provider: string }>([
|
|
6
|
+
["anthropic-personal", { name: "anthropic-personal", provider: "anthropic" }],
|
|
7
|
+
]);
|
|
8
|
+
mock.module("../../persistence/db-connection.js", () => ({
|
|
9
|
+
getDb: () => ({}),
|
|
10
|
+
}));
|
|
11
|
+
mock.module("../../providers/inference/connections.js", () => ({
|
|
12
|
+
getConnection: (_db: unknown, name: string) =>
|
|
13
|
+
connectionRows.get(name) ?? null,
|
|
14
|
+
}));
|
|
2
15
|
|
|
3
16
|
import { VELLUM_MANAGED_CONNECTION_NAME } from "../../providers/vellum-model-routing.js";
|
|
4
17
|
import { completeCustomProfile } from "../profile-materialization.js";
|
|
@@ -28,8 +41,10 @@ describe("completeCustomProfile", () => {
|
|
|
28
41
|
model: "claude-fable-5",
|
|
29
42
|
});
|
|
30
43
|
expect(completed.model).toBe("claude-fable-5");
|
|
31
|
-
|
|
32
|
-
|
|
44
|
+
// The default's explicit binding is inherited IN the provider value
|
|
45
|
+
// (the entries-model representation), never as a stamped binding.
|
|
46
|
+
expect(completed.provider).toBe("anthropic-personal");
|
|
47
|
+
expect(completed.provider_connection).toBeUndefined();
|
|
33
48
|
expect(completed.maxTokens).toBe(64000);
|
|
34
49
|
expect(completed.effort).toBe("max");
|
|
35
50
|
expect(completed.speed).toBe("standard");
|
|
@@ -78,12 +93,12 @@ describe("completeCustomProfile", () => {
|
|
|
78
93
|
expect(completed.contextWindow?.overflowRecovery?.enabled).toBe(true);
|
|
79
94
|
});
|
|
80
95
|
|
|
81
|
-
test("
|
|
96
|
+
test("inherits the default's binding as the entry name when the provider serves the model", () => {
|
|
82
97
|
const completed = completeCustomProfile(fullDefault, {
|
|
83
98
|
model: "claude-fable-5",
|
|
84
99
|
});
|
|
85
|
-
expect(completed.provider).toBe("anthropic");
|
|
86
|
-
expect(completed.provider_connection).
|
|
100
|
+
expect(completed.provider).toBe("anthropic-personal");
|
|
101
|
+
expect(completed.provider_connection).toBeUndefined();
|
|
87
102
|
});
|
|
88
103
|
|
|
89
104
|
test("stamps the catalog owner for a model the default provider does not serve, and drops the default's connection", () => {
|
|
@@ -123,36 +138,77 @@ describe("completeCustomProfile", () => {
|
|
|
123
138
|
expect(completed.provider_connection).toBeUndefined();
|
|
124
139
|
});
|
|
125
140
|
|
|
126
|
-
test("
|
|
141
|
+
test("a managed default's binding becomes the routing identity, never a stamped field", () => {
|
|
127
142
|
const managedDefault = LLMConfigBase.parse({
|
|
128
143
|
...fullDefault,
|
|
129
144
|
provider_connection: VELLUM_MANAGED_CONNECTION_NAME,
|
|
130
145
|
});
|
|
131
146
|
const implied = completeCustomProfile(managedDefault, { model: "gpt-5.5" });
|
|
132
|
-
expect(implied.provider).toBe("
|
|
133
|
-
expect(implied.provider_connection).
|
|
147
|
+
expect(implied.provider).toBe("vellum");
|
|
148
|
+
expect(implied.provider_connection).toBeUndefined();
|
|
134
149
|
|
|
135
150
|
const explicit = completeCustomProfile(managedDefault, {
|
|
136
151
|
provider: "openai",
|
|
137
152
|
model: "gpt-5.4",
|
|
138
153
|
});
|
|
139
|
-
expect(explicit.
|
|
154
|
+
expect(explicit.provider).toBe("vellum");
|
|
155
|
+
expect(explicit.provider_connection).toBeUndefined();
|
|
156
|
+
});
|
|
140
157
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
provider: "openrouter",
|
|
145
|
-
model: "minimax/minimax-m3",
|
|
158
|
+
test("inherits the binding as the entry name even for a model unknown to the catalog", () => {
|
|
159
|
+
const completed = completeCustomProfile(fullDefault, {
|
|
160
|
+
model: "totally-custom-model",
|
|
146
161
|
});
|
|
147
|
-
expect(
|
|
162
|
+
expect(completed.provider).toBe("anthropic-personal");
|
|
163
|
+
expect(completed.provider_connection).toBeUndefined();
|
|
148
164
|
});
|
|
149
165
|
|
|
150
|
-
test("
|
|
151
|
-
const
|
|
166
|
+
test("a dangling default binding passes through as the legacy field", () => {
|
|
167
|
+
const dangling = LLMConfigBase.parse({
|
|
168
|
+
...fullDefault,
|
|
169
|
+
provider_connection: "deleted-row",
|
|
170
|
+
});
|
|
171
|
+
const completed = completeCustomProfile(dangling, {
|
|
172
|
+
model: "claude-fable-5",
|
|
173
|
+
});
|
|
174
|
+
// Folding an unverifiable binding would hide it from the collapse
|
|
175
|
+
// migration's dangling recovery; the legacy field keeps it visible.
|
|
176
|
+
expect(completed.provider).toBe("anthropic");
|
|
177
|
+
expect(completed.provider_connection).toBe("deleted-row");
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
test("a kind-disagreeing default binding passes through as the legacy field", () => {
|
|
181
|
+
connectionRows.set("mislabeled", {
|
|
182
|
+
name: "mislabeled",
|
|
183
|
+
provider: "openai",
|
|
184
|
+
});
|
|
185
|
+
try {
|
|
186
|
+
const mismatched = LLMConfigBase.parse({
|
|
187
|
+
...fullDefault,
|
|
188
|
+
provider_connection: "mislabeled",
|
|
189
|
+
});
|
|
190
|
+
const completed = completeCustomProfile(mismatched, {
|
|
191
|
+
model: "claude-fable-5",
|
|
192
|
+
});
|
|
193
|
+
expect(completed.provider).toBe("anthropic");
|
|
194
|
+
expect(completed.provider_connection).toBe("mislabeled");
|
|
195
|
+
} finally {
|
|
196
|
+
connectionRows.delete("mislabeled");
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
test("a managed default binding is not inherited when the identity cannot serve the model", () => {
|
|
201
|
+
const managedDefault = LLMConfigBase.parse({
|
|
202
|
+
...fullDefault,
|
|
203
|
+
provider_connection: VELLUM_MANAGED_CONNECTION_NAME,
|
|
204
|
+
});
|
|
205
|
+
const completed = completeCustomProfile(managedDefault, {
|
|
152
206
|
model: "totally-custom-model",
|
|
153
207
|
});
|
|
208
|
+
// Dispatch auto-resolves by vendor instead of pinning an unservable
|
|
209
|
+
// managed route.
|
|
154
210
|
expect(completed.provider).toBe("anthropic");
|
|
155
|
-
expect(completed.provider_connection).
|
|
211
|
+
expect(completed.provider_connection).toBeUndefined();
|
|
156
212
|
});
|
|
157
213
|
|
|
158
214
|
test("passes mix profiles through untouched", () => {
|
|
@@ -59,6 +59,12 @@ function loadDefaultsRegistry(): FeatureFlagDefaultsRegistry {
|
|
|
59
59
|
// Works in Docker / packaged builds where the repo-root `meta/` dir
|
|
60
60
|
// is not available.
|
|
61
61
|
join(thisDir, REGISTRY_FILENAME),
|
|
62
|
+
...(process.platform === "win32"
|
|
63
|
+
? [
|
|
64
|
+
// Packaged Windows CLI runtime: assets live beside the executable.
|
|
65
|
+
join(dirname(process.execPath), REGISTRY_FILENAME),
|
|
66
|
+
]
|
|
67
|
+
: []),
|
|
62
68
|
// Packaged macOS app layout: the daemon binary lives at
|
|
63
69
|
// <App>.app/Contents/MacOS/vellum-daemon and the registry is copied
|
|
64
70
|
// to <App>.app/Contents/Resources/ by build.sh. In bun --compile
|
|
@@ -190,11 +196,11 @@ const DEFAULT_INIT_RETRY_BACKOFFS_MS: readonly number[] = [
|
|
|
190
196
|
* intentionally simulate an unreachable gateway and want immediate
|
|
191
197
|
* fallback without waiting through the production schedule).
|
|
192
198
|
*
|
|
193
|
-
* No-ops when the cache is already populated —
|
|
194
|
-
*
|
|
195
|
-
* tests preseed flag state via
|
|
196
|
-
* `__tests__/feature-flag-test-helpers.ts`)
|
|
197
|
-
* clobbering their setup.
|
|
199
|
+
* No-ops when the cache is already populated — this is the load-time
|
|
200
|
+
* populate, and `refreshOverridesFromGateway()` is what re-reads a cache that
|
|
201
|
+
* already holds values. The no-op also lets tests preseed flag state via
|
|
202
|
+
* `setOverridesForTesting()` (in `__tests__/feature-flag-test-helpers.ts`)
|
|
203
|
+
* without the gateway IPC call clobbering their setup.
|
|
198
204
|
*
|
|
199
205
|
* Resolves `true` when the override cache is populated from the gateway and
|
|
200
206
|
* `false` when the cache is left unset (exhausted retries / unreachable
|
|
@@ -274,10 +280,13 @@ function loadOverrides(): Record<string, boolean | string> {
|
|
|
274
280
|
* Invalidate the cached overrides so the next call to
|
|
275
281
|
* `isAssistantFeatureFlagEnabled` re-reads from the gateway.
|
|
276
282
|
*
|
|
277
|
-
*
|
|
278
|
-
* `
|
|
279
|
-
*
|
|
280
|
-
*
|
|
283
|
+
* Used by tests between cases to reset module state. (Tests typically call
|
|
284
|
+
* `setOverridesForTesting()` from `__tests__/feature-flag-test-helpers.ts`,
|
|
285
|
+
* which combines clear + seed.)
|
|
286
|
+
*
|
|
287
|
+
* Not a step in refreshing from the gateway: `refreshOverridesFromGateway()`
|
|
288
|
+
* swaps the cache atomically so flag values never read as unset while a
|
|
289
|
+
* refresh is in flight.
|
|
281
290
|
*/
|
|
282
291
|
export function clearFeatureFlagOverridesCache(): void {
|
|
283
292
|
clearCachedOverrides();
|
|
@@ -286,18 +295,30 @@ export function clearFeatureFlagOverridesCache(): void {
|
|
|
286
295
|
/**
|
|
287
296
|
* Re-fetch feature flag overrides from the gateway.
|
|
288
297
|
*
|
|
289
|
-
*
|
|
290
|
-
*
|
|
291
|
-
* Called by the gateway flag listener when a `feature_flags_changed`
|
|
292
|
-
* arrives.
|
|
298
|
+
* Runs the gateway IPC fetch without retries (the gateway is known to be up
|
|
299
|
+
* because it just pushed an event) and replaces the cache only once that fetch
|
|
300
|
+
* succeeds. Called by the gateway flag listener when a `feature_flags_changed`
|
|
301
|
+
* event arrives and on reconnect.
|
|
302
|
+
*
|
|
303
|
+
* The swap is atomic on purpose. The previously fetched values stay readable
|
|
304
|
+
* for the whole call, so a sync flag read that lands mid-refresh sees the last
|
|
305
|
+
* known values rather than an empty cache, and a failed fetch leaves them in
|
|
306
|
+
* place rather than dropping every flag to its registry default until the next
|
|
307
|
+
* event. A flag that selects behavior rather than gating it (an experiment
|
|
308
|
+
* arm, a kill switch) therefore cannot flip to its default because one IPC
|
|
309
|
+
* call timed out.
|
|
293
310
|
*
|
|
294
311
|
* Resolves `true` when the cache was repopulated from the gateway, `false`
|
|
295
312
|
* when the fetch came back empty/failed — callers gate persisted-state
|
|
296
313
|
* reconciliation on a `true` result.
|
|
297
314
|
*/
|
|
298
315
|
export async function refreshOverridesFromGateway(): Promise<boolean> {
|
|
299
|
-
|
|
300
|
-
|
|
316
|
+
const gatewayOverrides = await fetchOverridesFromGateway();
|
|
317
|
+
if (Object.keys(gatewayOverrides).length === 0) {
|
|
318
|
+
return false;
|
|
319
|
+
}
|
|
320
|
+
setCachedOverrides(gatewayOverrides, { fromGateway: true });
|
|
321
|
+
return true;
|
|
301
322
|
}
|
|
302
323
|
|
|
303
324
|
// ---------------------------------------------------------------------------
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Flag read for the managed Balanced profile's model A/B test.
|
|
3
|
+
*
|
|
4
|
+
* `experiment-balanced-model-2026-08-06` is a multivariate LaunchDarkly flag
|
|
5
|
+
* whose arm repoints the model the managed (`vellum`) implementation of the
|
|
6
|
+
* `balanced` default profile resolves to. The arm to model pins live beside
|
|
7
|
+
* the profile bodies in `default-profile-catalog.ts`, which validates their
|
|
8
|
+
* managed routability at load time; this module owns only the flag read.
|
|
9
|
+
*
|
|
10
|
+
* The read goes straight to the override cache rather than through
|
|
11
|
+
* `assistant-feature-flags.ts`. `feature-flag-cache.ts` is a stdlib-only leaf,
|
|
12
|
+
* so the profile catalog stays free of the pino logger and the gateway IPC
|
|
13
|
+
* client that resolver would pull into its import graph, and the registry
|
|
14
|
+
* declares `defaultEnabled: "control"` for this flag, which is the same
|
|
15
|
+
* shipped body an absent override already resolves to. That equivalence is
|
|
16
|
+
* pinned by `__tests__/balanced-model-experiment.test.ts` so it cannot drift.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { getCachedOverrides } from "./feature-flag-cache.js";
|
|
20
|
+
|
|
21
|
+
export const BALANCED_MODEL_EXPERIMENT_FLAG_KEY =
|
|
22
|
+
"experiment-balanced-model-2026-08-06";
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* The experiment arm in force, or `undefined` when the flag resolves to
|
|
26
|
+
* anything that is not an arm name: unset, a boolean, or the empty string.
|
|
27
|
+
* `control` and any arm this build does not know are returned as-is and miss
|
|
28
|
+
* the pin table, which is what keeps a stale or malformed LaunchDarkly value
|
|
29
|
+
* on the shipped model rather than stranding an install on one that does not
|
|
30
|
+
* exist.
|
|
31
|
+
*/
|
|
32
|
+
export function getBalancedModelExperimentArm(): string | undefined {
|
|
33
|
+
const value = getCachedOverrides()?.[BALANCED_MODEL_EXPERIMENT_FLAG_KEY];
|
|
34
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
35
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: acp
|
|
3
|
-
description:
|
|
3
|
+
description: Set up, authenticate, and run external coding agents (Claude Code, Codex) via the Agent Client Protocol
|
|
4
4
|
compatibility: "Designed for Vellum personal assistants"
|
|
5
5
|
metadata:
|
|
6
6
|
emoji: "🔗"
|
|
@@ -8,13 +8,12 @@ metadata:
|
|
|
8
8
|
display-name: "ACP"
|
|
9
9
|
category: "development"
|
|
10
10
|
activation-hints:
|
|
11
|
-
- "User
|
|
12
|
-
- "User
|
|
13
|
-
- "User wants
|
|
14
|
-
- "User
|
|
15
|
-
- "User mentions ACP, claude-agent-acp, codex-acp, or running multiple coding agents in parallel"
|
|
11
|
+
- "User wants to set up, install, configure, authenticate, or connect Claude Code or Codex"
|
|
12
|
+
- "User asks to use Claude Code or Codex, or delegate a coding task to an ACP agent"
|
|
13
|
+
- "User wants an agent to work autonomously and report back later"
|
|
14
|
+
- "User mentions ACP, claude-agent-acp, or codex-acp"
|
|
16
15
|
avoid-when:
|
|
17
|
-
- "
|
|
16
|
+
- "The task is small enough to do inline"
|
|
18
17
|
---
|
|
19
18
|
|
|
20
19
|
ACP agent orchestration - spawn external coding agents (Claude Code, Codex) to work on tasks via the Agent Client Protocol. Each agent runs as its own subprocess speaking ACP over stdio and streams results back into the conversation.
|