@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
|
@@ -150,6 +150,50 @@ describe("POST inference/profiles (create) validation", () => {
|
|
|
150
150
|
).rejects.toBeInstanceOf(BadRequestError);
|
|
151
151
|
});
|
|
152
152
|
|
|
153
|
+
test("creates an entry-backed profile, validating the model by the row's kind", async () => {
|
|
154
|
+
seedConnection("anthropic-work", "anthropic", {
|
|
155
|
+
type: "api_key",
|
|
156
|
+
credential: "credential/anthropic-work/api_key",
|
|
157
|
+
});
|
|
158
|
+
const result = (await call("inference_profiles_create", {
|
|
159
|
+
body: {
|
|
160
|
+
name: "work-profile",
|
|
161
|
+
provider: "anthropic-work",
|
|
162
|
+
model: "claude-opus-4-8",
|
|
163
|
+
},
|
|
164
|
+
})) as { entry: Record<string, unknown> };
|
|
165
|
+
expect(result.entry.provider).toBe("anthropic-work");
|
|
166
|
+
expect(result.entry.model).toBe("claude-opus-4-8");
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
test("rejects an entry-backed profile whose model the row's kind cannot serve", async () => {
|
|
170
|
+
seedConnection("anthropic-work", "anthropic", {
|
|
171
|
+
type: "api_key",
|
|
172
|
+
credential: "credential/anthropic-work/api_key",
|
|
173
|
+
});
|
|
174
|
+
await expect(
|
|
175
|
+
call("inference_profiles_create", {
|
|
176
|
+
body: {
|
|
177
|
+
name: "work-profile",
|
|
178
|
+
provider: "anthropic-work",
|
|
179
|
+
model: "gpt-5.5",
|
|
180
|
+
},
|
|
181
|
+
}),
|
|
182
|
+
).rejects.toBeInstanceOf(BadRequestError);
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
test("rejects a provider naming no known vendor or entry", async () => {
|
|
186
|
+
await expect(
|
|
187
|
+
call("inference_profiles_create", {
|
|
188
|
+
body: {
|
|
189
|
+
name: "ghost-profile",
|
|
190
|
+
provider: "no-such-entry",
|
|
191
|
+
model: "claude-opus-4-8",
|
|
192
|
+
},
|
|
193
|
+
}),
|
|
194
|
+
).rejects.toBeInstanceOf(BadRequestError);
|
|
195
|
+
});
|
|
196
|
+
|
|
153
197
|
test("creates a vellum profile for a managed-routable model", async () => {
|
|
154
198
|
seedVellumConnection();
|
|
155
199
|
const result = (await call("inference_profiles_create", {
|
|
@@ -232,6 +232,61 @@ describe("POST inference/provider-connections (create)", () => {
|
|
|
232
232
|
expect((err as BadRequestError).message).toContain("vellum");
|
|
233
233
|
});
|
|
234
234
|
|
|
235
|
+
test("rejects a chatgpt identity row under a non-canonical name", async () => {
|
|
236
|
+
const err = await call(
|
|
237
|
+
findHandler("inference_provider_connections_create"),
|
|
238
|
+
{
|
|
239
|
+
body: {
|
|
240
|
+
name: "my-chatgpt",
|
|
241
|
+
provider: "chatgpt",
|
|
242
|
+
auth: { type: "oauth_subscription", credential: "credential/x" },
|
|
243
|
+
},
|
|
244
|
+
},
|
|
245
|
+
).catch((e: unknown) => e);
|
|
246
|
+
|
|
247
|
+
expect(err).toBeInstanceOf(BadRequestError);
|
|
248
|
+
expect((err as BadRequestError).message).toContain("chatgpt-subscription");
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
test("rejects key auth on the chatgpt provider, derived or explicit", async () => {
|
|
252
|
+
for (const body of [
|
|
253
|
+
{
|
|
254
|
+
name: "chatgpt-subscription",
|
|
255
|
+
provider: "chatgpt",
|
|
256
|
+
auth: { type: "api_key", credential: "vault/x" },
|
|
257
|
+
},
|
|
258
|
+
// No explicit auth: derivation would fall through to api_key.
|
|
259
|
+
{
|
|
260
|
+
name: "chatgpt-subscription",
|
|
261
|
+
provider: "chatgpt",
|
|
262
|
+
credential: "vault/x",
|
|
263
|
+
},
|
|
264
|
+
]) {
|
|
265
|
+
const err = await call(
|
|
266
|
+
findHandler("inference_provider_connections_create"),
|
|
267
|
+
{ body },
|
|
268
|
+
).catch((e: unknown) => e);
|
|
269
|
+
expect(err).toBeInstanceOf(BadRequestError);
|
|
270
|
+
expect((err as BadRequestError).message).toContain("sign-in");
|
|
271
|
+
}
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
test("rejects subscription auth on a non-chatgpt provider", async () => {
|
|
275
|
+
const err = await call(
|
|
276
|
+
findHandler("inference_provider_connections_create"),
|
|
277
|
+
{
|
|
278
|
+
body: {
|
|
279
|
+
name: "keyed-oauth",
|
|
280
|
+
provider: "openai",
|
|
281
|
+
auth: { type: "oauth_subscription", credential: "credential/x" },
|
|
282
|
+
},
|
|
283
|
+
},
|
|
284
|
+
).catch((e: unknown) => e);
|
|
285
|
+
|
|
286
|
+
expect(err).toBeInstanceOf(BadRequestError);
|
|
287
|
+
expect((err as BadRequestError).message).toContain("chatgpt");
|
|
288
|
+
});
|
|
289
|
+
|
|
235
290
|
test("rejects key auth on the vellum provider", async () => {
|
|
236
291
|
const err = await call(
|
|
237
292
|
findHandler("inference_provider_connections_create"),
|
|
@@ -396,7 +451,7 @@ describe("POST inference/provider-connections (create)", () => {
|
|
|
396
451
|
models: [{ id: "my-model" }],
|
|
397
452
|
},
|
|
398
453
|
}),
|
|
399
|
-
).rejects.toThrow(/
|
|
454
|
+
).rejects.toThrow(/reserved as a provider id/);
|
|
400
455
|
|
|
401
456
|
await call(findHandler("inference_provider_connections_create"), {
|
|
402
457
|
body: {
|
|
@@ -677,6 +732,52 @@ describe("PATCH inference/provider-connections/:name (update)", () => {
|
|
|
677
732
|
|
|
678
733
|
// The guard must not trap a legacy row in its mismatched state: an auth
|
|
679
734
|
// change that repairs the pairing is exactly what should be allowed.
|
|
735
|
+
// The canonical subscription row owns the "chatgpt" identity: writing
|
|
736
|
+
// subscription auth to it stamps the provider (the CLI login-chatgpt path
|
|
737
|
+
// PATCHes auth through this route on a row the identity migration
|
|
738
|
+
// deliberately skipped).
|
|
739
|
+
test("stamps the chatgpt identity when subscription auth lands on the canonical row", async () => {
|
|
740
|
+
seedConnection({
|
|
741
|
+
name: "chatgpt-subscription",
|
|
742
|
+
provider: "openai",
|
|
743
|
+
auth: { type: "api_key", credential: "vault/openai/key" },
|
|
744
|
+
});
|
|
745
|
+
|
|
746
|
+
const result = (await call(
|
|
747
|
+
findHandler("inference_provider_connections_update"),
|
|
748
|
+
{
|
|
749
|
+
pathParams: { name: "chatgpt-subscription" },
|
|
750
|
+
body: {
|
|
751
|
+
auth: {
|
|
752
|
+
type: "oauth_subscription",
|
|
753
|
+
credential: "credential/chatgpt/access_token",
|
|
754
|
+
},
|
|
755
|
+
},
|
|
756
|
+
},
|
|
757
|
+
)) as { provider: string; auth: { type: string } };
|
|
758
|
+
expect(result.provider).toBe("chatgpt");
|
|
759
|
+
expect(result.auth.type).toBe("oauth_subscription");
|
|
760
|
+
});
|
|
761
|
+
|
|
762
|
+
test("does not stamp the identity for non-subscription auth on that name", async () => {
|
|
763
|
+
seedConnection({
|
|
764
|
+
name: "chatgpt-subscription",
|
|
765
|
+
provider: "openai",
|
|
766
|
+
auth: { type: "api_key", credential: "vault/openai/key" },
|
|
767
|
+
});
|
|
768
|
+
|
|
769
|
+
const result = (await call(
|
|
770
|
+
findHandler("inference_provider_connections_update"),
|
|
771
|
+
{
|
|
772
|
+
pathParams: { name: "chatgpt-subscription" },
|
|
773
|
+
body: {
|
|
774
|
+
auth: { type: "api_key", credential: "vault/openai/other-key" },
|
|
775
|
+
},
|
|
776
|
+
},
|
|
777
|
+
)) as { provider: string };
|
|
778
|
+
expect(result.provider).toBe("openai");
|
|
779
|
+
});
|
|
780
|
+
|
|
680
781
|
test("allows repairing a legacy mismatched row with a valid auth change", async () => {
|
|
681
782
|
seedConnection({
|
|
682
783
|
name: "legacy-managed-anthropic",
|
|
@@ -38,9 +38,12 @@
|
|
|
38
38
|
* `plugins:list` tag via the canonical resource-sync publisher (enable and
|
|
39
39
|
* disable emit the SAME invalidation)
|
|
40
40
|
* - Threads `x-vellum-client-id` into the published event's `originClientId`
|
|
41
|
-
* -
|
|
42
|
-
*
|
|
43
|
-
*
|
|
41
|
+
* - Enable pokes the imperative plugin source reconcile, which activates a
|
|
42
|
+
* plugin the boot scan skipped for its sentinel and converges its
|
|
43
|
+
* schedules and MCP servers
|
|
44
|
+
* - Disable pokes the plugin-declared schedule reconcile on a successful
|
|
45
|
+
* toggle (and not on a failed one), so the plugin's rows disarm
|
|
46
|
+
* immediately instead of at the reconciler's next backstop sweep
|
|
44
47
|
* - A broadcast failure does not fail a successful toggle (the publisher
|
|
45
48
|
* swallows hub errors)
|
|
46
49
|
* - Maps `InvalidPluginNameError` → BadRequestError (400)
|
|
@@ -109,6 +112,7 @@ import {
|
|
|
109
112
|
} from "../../../cli/lib/uninstall-plugin.js";
|
|
110
113
|
import {
|
|
111
114
|
PluginMergeBaselineError,
|
|
115
|
+
PluginNotCuratedError,
|
|
112
116
|
PluginNotUpgradableError,
|
|
113
117
|
type PluginUpgradeResult,
|
|
114
118
|
type UpgradePluginDeps,
|
|
@@ -252,6 +256,7 @@ const upgradeSpy = mock(
|
|
|
252
256
|
|
|
253
257
|
mock.module("../../../cli/lib/upgrade-plugin.js", () => ({
|
|
254
258
|
PluginMergeBaselineError,
|
|
259
|
+
PluginNotCuratedError,
|
|
255
260
|
PluginNotUpgradableError,
|
|
256
261
|
upgradePlugin: upgradeSpy,
|
|
257
262
|
}));
|
|
@@ -314,8 +319,8 @@ mock.module("../../../cli/lib/toggle-plugin.js", () => ({
|
|
|
314
319
|
enablePlugin: enablePluginSpy,
|
|
315
320
|
}));
|
|
316
321
|
|
|
317
|
-
// Spy on the plugin-schedule reconcile the
|
|
318
|
-
//
|
|
322
|
+
// Spy on the plugin-schedule reconcile the disable handler pokes. The handler
|
|
323
|
+
// imports it lazily at call time, so this mock intercepts the dynamic import
|
|
319
324
|
// and keeps the reconciler's persistence graph out of the test.
|
|
320
325
|
const reconcilePluginSchedulesSpy = mock(() => Promise.resolve());
|
|
321
326
|
|
|
@@ -323,6 +328,21 @@ mock.module("../../../schedule/plugin-schedule-reconciler.js", () => ({
|
|
|
323
328
|
reconcilePluginSchedules: reconcilePluginSchedulesSpy,
|
|
324
329
|
}));
|
|
325
330
|
|
|
331
|
+
// Spy on the imperative plugin source reconcile so the enable route's
|
|
332
|
+
// activation poke is assertable without scanning a real plugins tree. Only
|
|
333
|
+
// that one export is swapped; the rest of the module passes through real,
|
|
334
|
+
// because other modules in this route's graph import their own bindings from
|
|
335
|
+
// it.
|
|
336
|
+
const reconcilePluginSourcesNowSpy = mock(() => Promise.resolve());
|
|
337
|
+
|
|
338
|
+
const actualMtimeCache: typeof import("../../../plugins/mtime-cache.js") =
|
|
339
|
+
await import("../../../plugins/mtime-cache.js");
|
|
340
|
+
|
|
341
|
+
mock.module("../../../plugins/mtime-cache.js", () => ({
|
|
342
|
+
...actualMtimeCache,
|
|
343
|
+
reconcilePluginSourcesNow: reconcilePluginSourcesNowSpy,
|
|
344
|
+
}));
|
|
345
|
+
|
|
326
346
|
// Spy on broadcastMessage so we can assert the sync_changed invalidation the
|
|
327
347
|
// enable/disable handlers emit. The handlers publish through the canonical
|
|
328
348
|
// `publishPluginsChanged` → `publishSyncInvalidation` path (both left real), so
|
|
@@ -2127,6 +2147,7 @@ describe("POST /v1/plugins/:name/upgrade", () => {
|
|
|
2127
2147
|
name: "level-up",
|
|
2128
2148
|
dryRun: false,
|
|
2129
2149
|
strategy: undefined,
|
|
2150
|
+
marketplaceOnly: false,
|
|
2130
2151
|
});
|
|
2131
2152
|
});
|
|
2132
2153
|
|
|
@@ -2148,6 +2169,7 @@ describe("POST /v1/plugins/:name/upgrade", () => {
|
|
|
2148
2169
|
name: "level-up",
|
|
2149
2170
|
dryRun: undefined,
|
|
2150
2171
|
strategy: "ours",
|
|
2172
|
+
marketplaceOnly: false,
|
|
2151
2173
|
});
|
|
2152
2174
|
});
|
|
2153
2175
|
|
|
@@ -2175,6 +2197,7 @@ describe("POST /v1/plugins/:name/upgrade", () => {
|
|
|
2175
2197
|
name: "level-up",
|
|
2176
2198
|
dryRun: undefined,
|
|
2177
2199
|
strategy: "assistant",
|
|
2200
|
+
marketplaceOnly: false,
|
|
2178
2201
|
});
|
|
2179
2202
|
});
|
|
2180
2203
|
|
|
@@ -2300,6 +2323,10 @@ describe("POST /v1/plugins/:name/upgrade", () => {
|
|
|
2300
2323
|
expect(upgradeSpy.mock.calls[0]?.[0]).toEqual({
|
|
2301
2324
|
name: "level-up",
|
|
2302
2325
|
dryRun: undefined,
|
|
2326
|
+
strategy: undefined,
|
|
2327
|
+
// Unlike dryRun, an absent flag here is a definite "no": the untrusted
|
|
2328
|
+
// direct path stays available unless a caller opts out of it.
|
|
2329
|
+
marketplaceOnly: false,
|
|
2303
2330
|
});
|
|
2304
2331
|
});
|
|
2305
2332
|
|
|
@@ -2343,6 +2370,41 @@ describe("POST /v1/plugins/:name/upgrade", () => {
|
|
|
2343
2370
|
).rejects.toBeInstanceOf(ConflictError);
|
|
2344
2371
|
});
|
|
2345
2372
|
|
|
2373
|
+
test("marketplaceOnly is forwarded so the lib enforces it, not the caller", async () => {
|
|
2374
|
+
// The lib re-inspects the catalog inside the call, so the flag has to
|
|
2375
|
+
// travel with the request: a caller's own pre-check cannot bind a decision
|
|
2376
|
+
// the lib makes afterwards.
|
|
2377
|
+
upgradeSpy.mockImplementation(async () => upgradeResult());
|
|
2378
|
+
|
|
2379
|
+
await invokeUpgrade({
|
|
2380
|
+
pathParams: { name: "level-up" },
|
|
2381
|
+
body: { marketplaceOnly: true },
|
|
2382
|
+
});
|
|
2383
|
+
|
|
2384
|
+
expect(upgradeSpy.mock.calls[0]?.[0]).toEqual({
|
|
2385
|
+
name: "level-up",
|
|
2386
|
+
dryRun: undefined,
|
|
2387
|
+
strategy: undefined,
|
|
2388
|
+
marketplaceOnly: true,
|
|
2389
|
+
});
|
|
2390
|
+
});
|
|
2391
|
+
|
|
2392
|
+
test("PluginNotCuratedError → ConflictError (409)", async () => {
|
|
2393
|
+
// A marketplaceOnly caller asked about an install the catalog does not
|
|
2394
|
+
// claim. Retrying changes nothing: only a human upgrading it without the
|
|
2395
|
+
// flag can move it.
|
|
2396
|
+
upgradeSpy.mockImplementation(async () => {
|
|
2397
|
+
throw new PluginNotCuratedError("level-up");
|
|
2398
|
+
});
|
|
2399
|
+
|
|
2400
|
+
await expect(
|
|
2401
|
+
invokeUpgrade({
|
|
2402
|
+
pathParams: { name: "level-up" },
|
|
2403
|
+
body: { marketplaceOnly: true },
|
|
2404
|
+
}),
|
|
2405
|
+
).rejects.toBeInstanceOf(ConflictError);
|
|
2406
|
+
});
|
|
2407
|
+
|
|
2346
2408
|
test("PluginNotFoundError → NotFoundError (404)", async () => {
|
|
2347
2409
|
upgradeSpy.mockImplementation(async () => {
|
|
2348
2410
|
throw new PluginNotFoundError("level-up", "main", "vellum-ai/level-up");
|
|
@@ -2529,8 +2591,10 @@ function toggleResult(
|
|
|
2529
2591
|
};
|
|
2530
2592
|
}
|
|
2531
2593
|
|
|
2532
|
-
function invokeEnable(
|
|
2533
|
-
|
|
2594
|
+
async function invokeEnable(
|
|
2595
|
+
args: RouteHandlerArgs = {},
|
|
2596
|
+
): Promise<{ ok: boolean }> {
|
|
2597
|
+
return (await enableHandler(args)) as { ok: boolean };
|
|
2534
2598
|
}
|
|
2535
2599
|
|
|
2536
2600
|
function invokeDisable(args: RouteHandlerArgs = {}): { ok: boolean } {
|
|
@@ -2538,18 +2602,22 @@ function invokeDisable(args: RouteHandlerArgs = {}): { ok: boolean } {
|
|
|
2538
2602
|
}
|
|
2539
2603
|
|
|
2540
2604
|
/**
|
|
2541
|
-
* Wait for
|
|
2542
|
-
*
|
|
2543
|
-
* run on the handler's synchronous
|
|
2605
|
+
* Wait for a toggle handler's fire-and-forget reconcile poke to land. The poke
|
|
2606
|
+
* runs off the microtask queue (the disable path also resolves a lazy
|
|
2607
|
+
* `import()` first), so the assertion cannot run on the handler's synchronous
|
|
2608
|
+
* return.
|
|
2544
2609
|
*/
|
|
2545
|
-
async function
|
|
2610
|
+
async function waitForReconcile(
|
|
2611
|
+
spy: { mock: { calls: unknown[] } },
|
|
2612
|
+
label: string,
|
|
2613
|
+
): Promise<void> {
|
|
2546
2614
|
for (let i = 0; i < 50; i++) {
|
|
2547
|
-
if (
|
|
2615
|
+
if (spy.mock.calls.length > 0) {
|
|
2548
2616
|
return;
|
|
2549
2617
|
}
|
|
2550
2618
|
await new Promise((resolve) => setTimeout(resolve, 2));
|
|
2551
2619
|
}
|
|
2552
|
-
throw new Error(
|
|
2620
|
+
throw new Error(`${label} was never triggered`);
|
|
2553
2621
|
}
|
|
2554
2622
|
|
|
2555
2623
|
/** Assert the spy received exactly one sync_changed carrying `plugins:list`. */
|
|
@@ -2565,30 +2633,50 @@ describe("POST /v1/plugins/:name/enable", () => {
|
|
|
2565
2633
|
enablePluginSpy.mockReset();
|
|
2566
2634
|
broadcastMessageSpy.mockReset();
|
|
2567
2635
|
reconcilePluginSchedulesSpy.mockClear();
|
|
2636
|
+
reconcilePluginSourcesNowSpy.mockClear();
|
|
2568
2637
|
});
|
|
2569
2638
|
|
|
2570
|
-
test("
|
|
2639
|
+
test("awaits the source reconcile so a boot-disabled plugin activates before the route returns", async () => {
|
|
2571
2640
|
enablePluginSpy.mockImplementation((name) => toggleResult(name, "enable"));
|
|
2572
2641
|
|
|
2573
|
-
invokeEnable({ pathParams: { name: "simple-memory" } });
|
|
2642
|
+
await invokeEnable({ pathParams: { name: "simple-memory" } });
|
|
2643
|
+
|
|
2644
|
+
// The boot scan skipped this plugin for its sentinel, so clearing the
|
|
2645
|
+
// sentinel only brings its hooks, tools, MCP servers and schedules up if
|
|
2646
|
+
// the source reconcile runs. The route awaits it, so by the time the
|
|
2647
|
+
// response lands the reconcile has completed; it converges the schedules
|
|
2648
|
+
// itself, so the route does not poke them separately.
|
|
2649
|
+
expect(reconcilePluginSourcesNowSpy).toHaveBeenCalledTimes(1);
|
|
2650
|
+
expect(reconcilePluginSchedulesSpy).not.toHaveBeenCalled();
|
|
2651
|
+
});
|
|
2652
|
+
|
|
2653
|
+
test("a failed toggle does not run the source reconcile", async () => {
|
|
2654
|
+
enablePluginSpy.mockImplementation((name) => {
|
|
2655
|
+
throw new PluginDirectoryNotFoundError(name);
|
|
2656
|
+
});
|
|
2574
2657
|
|
|
2575
|
-
await
|
|
2658
|
+
await expect(
|
|
2659
|
+
invokeEnable({ pathParams: { name: "ghost" } }),
|
|
2660
|
+
).rejects.toThrow(NotFoundError);
|
|
2661
|
+
expect(reconcilePluginSourcesNowSpy).not.toHaveBeenCalled();
|
|
2576
2662
|
});
|
|
2577
2663
|
|
|
2578
|
-
test("enables the plugin and broadcasts sync_changed(plugins:list)", () => {
|
|
2664
|
+
test("enables the plugin and broadcasts sync_changed(plugins:list)", async () => {
|
|
2579
2665
|
enablePluginSpy.mockImplementation((name) => toggleResult(name, "enable"));
|
|
2580
2666
|
|
|
2581
|
-
const result = invokeEnable({
|
|
2667
|
+
const result = await invokeEnable({
|
|
2668
|
+
pathParams: { name: "simple-memory" },
|
|
2669
|
+
});
|
|
2582
2670
|
|
|
2583
2671
|
expect(result).toEqual({ ok: true });
|
|
2584
2672
|
expect(enablePluginSpy.mock.calls[0]?.[0]).toBe("simple-memory");
|
|
2585
2673
|
expectPluginsListBroadcast();
|
|
2586
2674
|
});
|
|
2587
2675
|
|
|
2588
|
-
test("threads x-vellum-client-id into the published event's originClientId", () => {
|
|
2676
|
+
test("threads x-vellum-client-id into the published event's originClientId", async () => {
|
|
2589
2677
|
enablePluginSpy.mockImplementation((name) => toggleResult(name, "enable"));
|
|
2590
2678
|
|
|
2591
|
-
invokeEnable({
|
|
2679
|
+
await invokeEnable({
|
|
2592
2680
|
pathParams: { name: "simple-memory" },
|
|
2593
2681
|
headers: { "x-vellum-client-id": "client-abc" },
|
|
2594
2682
|
});
|
|
@@ -2602,7 +2690,7 @@ describe("POST /v1/plugins/:name/enable", () => {
|
|
|
2602
2690
|
});
|
|
2603
2691
|
});
|
|
2604
2692
|
|
|
2605
|
-
test("a broadcast failure does not fail a successful toggle", () => {
|
|
2693
|
+
test("a broadcast failure does not fail a successful toggle", async () => {
|
|
2606
2694
|
enablePluginSpy.mockImplementation((name) => toggleResult(name, "enable"));
|
|
2607
2695
|
// The sentinel was already flipped; a hub throw AFTER that must not surface
|
|
2608
2696
|
// as a 500 — the canonical publisher swallows broadcast errors.
|
|
@@ -2610,40 +2698,42 @@ describe("POST /v1/plugins/:name/enable", () => {
|
|
|
2610
2698
|
throw new Error("hub unavailable");
|
|
2611
2699
|
});
|
|
2612
2700
|
|
|
2613
|
-
const result = invokeEnable({
|
|
2701
|
+
const result = await invokeEnable({
|
|
2702
|
+
pathParams: { name: "simple-memory" },
|
|
2703
|
+
});
|
|
2614
2704
|
expect(result).toEqual({ ok: true });
|
|
2615
2705
|
});
|
|
2616
2706
|
|
|
2617
|
-
test("PluginAlreadyInStateException → ConflictError (409), no broadcast", () => {
|
|
2707
|
+
test("PluginAlreadyInStateException → ConflictError (409), no broadcast", async () => {
|
|
2618
2708
|
enablePluginSpy.mockImplementation((name) => {
|
|
2619
2709
|
throw new PluginAlreadyInStateException(name, "enable");
|
|
2620
2710
|
});
|
|
2621
2711
|
|
|
2622
|
-
expect(
|
|
2712
|
+
await expect(
|
|
2623
2713
|
invokeEnable({ pathParams: { name: "simple-memory" } }),
|
|
2624
|
-
).toThrow(ConflictError);
|
|
2714
|
+
).rejects.toThrow(ConflictError);
|
|
2625
2715
|
// A no-op toggle must not fan out a spurious invalidation.
|
|
2626
2716
|
expect(broadcastMessageSpy).not.toHaveBeenCalled();
|
|
2627
2717
|
});
|
|
2628
2718
|
|
|
2629
|
-
test("PluginDirectoryNotFoundError → NotFoundError (404)", () => {
|
|
2719
|
+
test("PluginDirectoryNotFoundError → NotFoundError (404)", async () => {
|
|
2630
2720
|
enablePluginSpy.mockImplementation((name) => {
|
|
2631
2721
|
throw new PluginDirectoryNotFoundError(name);
|
|
2632
2722
|
});
|
|
2633
2723
|
|
|
2634
|
-
expect(
|
|
2635
|
-
|
|
2636
|
-
);
|
|
2724
|
+
await expect(
|
|
2725
|
+
invokeEnable({ pathParams: { name: "ghost" } }),
|
|
2726
|
+
).rejects.toThrow(NotFoundError);
|
|
2637
2727
|
});
|
|
2638
2728
|
|
|
2639
|
-
test("InvalidPluginNameError → BadRequestError (400)", () => {
|
|
2729
|
+
test("InvalidPluginNameError → BadRequestError (400)", async () => {
|
|
2640
2730
|
enablePluginSpy.mockImplementation(() => {
|
|
2641
2731
|
throw new ToggleInvalidPluginNameError("../escape");
|
|
2642
2732
|
});
|
|
2643
2733
|
|
|
2644
|
-
expect(
|
|
2645
|
-
|
|
2646
|
-
);
|
|
2734
|
+
await expect(
|
|
2735
|
+
invokeEnable({ pathParams: { name: "../escape" } }),
|
|
2736
|
+
).rejects.toThrow(BadRequestError);
|
|
2647
2737
|
});
|
|
2648
2738
|
});
|
|
2649
2739
|
|
|
@@ -2652,6 +2742,7 @@ describe("POST /v1/plugins/:name/disable", () => {
|
|
|
2652
2742
|
disablePluginSpy.mockReset();
|
|
2653
2743
|
broadcastMessageSpy.mockReset();
|
|
2654
2744
|
reconcilePluginSchedulesSpy.mockClear();
|
|
2745
|
+
reconcilePluginSourcesNowSpy.mockClear();
|
|
2655
2746
|
});
|
|
2656
2747
|
|
|
2657
2748
|
test("reconciles plugin-declared schedules so the plugin's rows disarm now", async () => {
|
|
@@ -2662,8 +2753,14 @@ describe("POST /v1/plugins/:name/disable", () => {
|
|
|
2662
2753
|
invokeDisable({ pathParams: { name: "simple-memory" } });
|
|
2663
2754
|
|
|
2664
2755
|
// Without this poke the rows stay armed until the reconciler's next
|
|
2665
|
-
// backstop sweep.
|
|
2666
|
-
|
|
2756
|
+
// backstop sweep. Disable stays on the schedule poke: the sentinel filters
|
|
2757
|
+
// the plugin out at read time, and a source reconcile here would run its
|
|
2758
|
+
// shutdown hooks.
|
|
2759
|
+
await waitForReconcile(
|
|
2760
|
+
reconcilePluginSchedulesSpy,
|
|
2761
|
+
"plugin schedule reconcile",
|
|
2762
|
+
);
|
|
2763
|
+
expect(reconcilePluginSourcesNowSpy).not.toHaveBeenCalled();
|
|
2667
2764
|
});
|
|
2668
2765
|
|
|
2669
2766
|
test("a failed toggle does not poke the schedule reconcile", async () => {
|