@vellumai/assistant 0.10.12 → 0.11.0-staging.2
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 +1 -1
- package/ARCHITECTURE.md +4 -5
- package/README.md +1 -1
- package/docs/architecture/memory.md +60 -23
- package/docs/error-handling.md +3 -3
- package/docs/guardian-request-flow.md +112 -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__/channels.test.ts +9 -1
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +449 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/channels.ts +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +468 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/app.d.ts +28 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/app.d.ts.map +1 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/index.d.ts +2 -2
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/index.d.ts.map +1 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/index.js.map +1 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/message.d.ts +2 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/message.d.ts.map +1 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/package.json +1 -1
- 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__/channels.test.ts +9 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +449 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/channels.ts +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +468 -0
- package/node_modules/@vellumai/gateway-client/package.json +1 -1
- package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +6 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +34 -0
- package/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +9 -1
- package/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +449 -0
- package/node_modules/@vellumai/service-contracts/src/channels.ts +1 -0
- package/node_modules/@vellumai/service-contracts/src/secret-detection.ts +468 -0
- package/openapi.yaml +264 -14
- package/package.json +2 -2
- package/src/__tests__/acp-session.test.ts +3 -3
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +3 -0
- package/src/__tests__/anthropic-provider.test.ts +40 -0
- package/src/__tests__/app-conversation-ids-backfill.test.ts +33 -2
- package/src/__tests__/app-conversation-ids.test.ts +204 -0
- package/src/__tests__/approval-cascade.test.ts +5 -5
- package/src/__tests__/approval-routes-http.test.ts +3 -3
- package/src/__tests__/ask-question-resolver.test.ts +207 -0
- package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +16 -16
- package/src/__tests__/assistant-event-hub-targeted.test.ts +13 -11
- package/src/__tests__/assistant-event-hub.test.ts +13 -11
- package/src/__tests__/assistant-event.test.ts +12 -9
- package/src/__tests__/assistant-feature-flag-guard.test.ts +3 -3
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +1 -1
- package/src/__tests__/assistant-id-boundary-guard.test.ts +0 -58
- package/src/__tests__/assistant-stream-state.test.ts +17 -7
- package/src/__tests__/avatar-identity-sync.test.ts +3 -3
- package/src/__tests__/background-workers-disk-pressure.test.ts +1 -0
- package/src/__tests__/call-conversation-messages.test.ts +134 -18
- package/src/__tests__/call-start-guardian-guard.test.ts +27 -0
- package/src/__tests__/channel-approvals.test.ts +0 -27
- package/src/__tests__/channel-guardian.test.ts +85 -512
- package/src/__tests__/channel-readiness-slack-remote.test.ts +151 -3
- package/src/__tests__/channel-retry-sweep.test.ts +88 -1
- package/src/__tests__/channel-setup-panel-ack.test.ts +12 -9
- package/src/__tests__/chat-reveal-guard-priming.test.ts +31 -34
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +2 -2
- package/src/__tests__/compaction-events.test.ts +8 -8
- package/src/__tests__/config-loader-platform-defaults.test.ts +54 -28
- package/src/__tests__/config-model-image-provider.test.ts +20 -0
- package/src/__tests__/config-schema-memory-substrate.test.ts +306 -0
- package/src/__tests__/config-schema.test.ts +14 -2
- package/src/__tests__/config-set-platform-guard.test.ts +11 -12
- package/src/__tests__/config-sounds-sync.test.ts +4 -4
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +5 -0
- package/src/__tests__/context-search-memory-source.test.ts +1 -1
- package/src/__tests__/context-search-memory-v2-source.test.ts +6 -6
- package/src/__tests__/context-token-estimator.test.ts +54 -1
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +12 -3
- package/src/__tests__/conversation-agent-loop-fatal-cleanup.test.ts +13 -4
- package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +4 -4
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +10 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +22 -13
- package/src/__tests__/conversation-agent-loop.test.ts +39 -30
- package/src/__tests__/conversation-confirmation-signals.test.ts +14 -14
- package/src/__tests__/conversation-evictor.test.ts +49 -0
- package/src/__tests__/conversation-fork-crud.test.ts +1 -1
- package/src/__tests__/conversation-group-tools.test.ts +279 -0
- package/src/__tests__/conversation-history-web-search.test.ts +1 -1
- package/src/__tests__/conversation-key-store-disk-view.test.ts +5 -5
- package/src/__tests__/conversation-lineage.test.ts +235 -0
- package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +5 -5
- package/src/__tests__/conversation-message-sync-tags.test.ts +4 -4
- package/src/__tests__/conversation-queue.test.ts +81 -81
- package/src/__tests__/conversation-routes-enabled-plugins.test.ts +8 -1
- package/src/__tests__/conversation-routes-hidden-queue.test.ts +8 -1
- package/src/__tests__/conversation-routes-slash-commands.test.ts +10 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +29 -2
- package/src/__tests__/conversation-slash-queue.test.ts +11 -11
- package/src/__tests__/conversation-slash-unknown.test.ts +2 -2
- package/src/__tests__/conversation-speed-override.test.ts +2 -2
- package/src/__tests__/conversation-summarize-route.test.ts +9 -0
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +18 -16
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +17 -17
- package/src/__tests__/conversation-surfaces-app-open.test.ts +7 -4
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +7 -7
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +9 -9
- package/src/__tests__/conversation-surfaces-standalone.test.ts +12 -12
- package/src/__tests__/conversation-surfaces-state-update.test.ts +8 -5
- package/src/__tests__/conversation-surfaces-table-action.test.ts +6 -3
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +46 -46
- package/src/__tests__/conversation-sync-tags.test.ts +5 -5
- package/src/__tests__/conversation-wait-for-idle.test.ts +2 -2
- package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -4
- package/src/__tests__/conversation-workspace-injection.test.ts +0 -3
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -3
- package/src/__tests__/copy-composer-tc-templates.test.ts +3 -131
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/daemon-assistant-events.test.ts +14 -15
- package/src/__tests__/db-test-helpers.ts +13 -27
- package/src/__tests__/disk-pressure-routes.test.ts +12 -3
- package/src/__tests__/document-tool-security.test.ts +95 -0
- package/src/__tests__/drain-kick-guard.test.ts +232 -0
- package/src/__tests__/dynamic-skill-background-guard.test.ts +19 -6
- package/src/__tests__/emit-event-signal.test.ts +5 -6
- package/src/__tests__/encrypted-store-test-helpers.ts +10 -20
- package/src/__tests__/events-tail-route.test.ts +6 -4
- package/src/__tests__/feature-flag-test-helpers.ts +10 -20
- package/src/__tests__/file-edit-tool.test.ts +24 -4
- package/src/__tests__/file-list-tool.test.ts +2 -1
- package/src/__tests__/file-read-tool.test.ts +62 -10
- package/src/__tests__/file-write-tool.test.ts +24 -5
- package/src/__tests__/followup-tools.test.ts +58 -0
- package/src/__tests__/gateway-threshold-reader-mock.ts +99 -0
- package/src/__tests__/graph-extraction-event-date.test.ts +1 -1
- package/src/__tests__/guardian-question-mode.test.ts +42 -3
- package/src/__tests__/guardian-reply-router-answer-mode.test.ts +283 -0
- package/src/__tests__/guardian-vellum-destination-pinning.test.ts +221 -0
- package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
- package/src/__tests__/heartbeat-service.test.ts +1 -0
- package/src/__tests__/helpers/native-web-search-harness.ts +10 -10
- package/src/__tests__/host-browser-proxy.test.ts +1 -1
- package/src/__tests__/host-file-edit-tool.test.ts +3 -3
- package/src/__tests__/host-file-read-tool.test.ts +2 -2
- package/src/__tests__/host-file-write-tool.test.ts +7 -3
- package/src/__tests__/host-shell-tool.test.ts +17 -5
- package/src/__tests__/host-transfer-pending-interactions.test.ts +8 -8
- package/src/__tests__/image-credentials.test.ts +65 -8
- package/src/__tests__/injection-block.test.ts +4 -4
- package/src/__tests__/injector-chain.test.ts +1 -1
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +2 -2
- package/src/__tests__/injector-registry-order-guard.test.ts +4 -9
- package/src/__tests__/injector-v3-suppression.test.ts +6 -4
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +27 -28
- package/src/__tests__/list-messages-page-latest.test.ts +2 -2
- package/src/__tests__/llm-usage-store.test.ts +67 -4
- package/src/__tests__/log-redact.test.ts +18 -0
- package/src/__tests__/managed-profile-guard.test.ts +27 -0
- package/src/__tests__/managed-skill-lifecycle.test.ts +2 -2
- package/src/__tests__/media-generate-image.test.ts +62 -11
- package/src/__tests__/memory-identity-context-parity.test.ts +1 -1
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +9 -1
- package/src/__tests__/memory-retrieval-hook.test.ts +4 -4
- package/src/__tests__/notification-decision-strategy.test.ts +115 -11
- package/src/__tests__/notification-deep-link.test.ts +12 -12
- package/src/__tests__/notification-vellum-adapter.test.ts +8 -8
- package/src/__tests__/outbound-slack-persistence.test.ts +8 -8
- package/src/__tests__/path-policy.test.ts +315 -0
- package/src/__tests__/pending-interactions-resolved-event.test.ts +6 -6
- package/src/__tests__/persistence-layering-guard.test.ts +2 -2
- package/src/__tests__/pkb-autoinject.test.ts +1 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +1 -0
- package/src/__tests__/platform-callback-registration.test.ts +10 -10
- package/src/__tests__/plugin-event-hub-facade.test.ts +22 -15
- package/src/__tests__/plugin-import-boundary-guard.test.ts +15 -15
- package/src/__tests__/processing-flag-persist-failure.test.ts +0 -4
- package/src/__tests__/provider-platform-proxy-integration.test.ts +0 -1
- package/src/__tests__/rebuild-index-graph-nodes.test.ts +1 -1
- package/src/__tests__/request-secret-standalone-channel-gate.test.ts +5 -5
- package/src/__tests__/require-fresh-approval.test.ts +38 -38
- package/src/__tests__/resolve-app-id.test.ts +32 -0
- package/src/__tests__/run-due-schedules.test.ts +72 -1
- package/src/__tests__/runtime-events-sse-parity.test.ts +11 -10
- package/src/__tests__/runtime-events-sse.test.ts +1 -1
- package/src/__tests__/schedule-routes.test.ts +44 -5
- package/src/__tests__/schedule-store.test.ts +3 -3
- package/src/__tests__/schedule-tools.test.ts +176 -0
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +3 -3
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +3 -3
- package/src/__tests__/secret-response-routing.test.ts +3 -3
- package/src/__tests__/secret-routes-platform-proxy.test.ts +4 -7
- package/src/__tests__/secret-scanner.test.ts +36 -0
- package/src/__tests__/send-endpoint-busy.test.ts +7 -7
- package/src/__tests__/slack-required-scopes-mirror.test.ts +81 -0
- package/src/__tests__/starter-task-flow.test.ts +26 -3
- package/src/__tests__/subagent-call-site-routing.test.ts +2 -2
- package/src/__tests__/subagent-disposal.test.ts +40 -11
- package/src/__tests__/subagent-fork-notifications.test.ts +4 -4
- package/src/__tests__/subagent-fork-prompt-role.test.ts +3 -3
- package/src/__tests__/subagent-fork-spawn.test.ts +4 -4
- package/src/__tests__/subagent-manager-notify.test.ts +73 -14
- package/src/__tests__/subagent-notify-parent.test.ts +48 -4
- package/src/__tests__/subagent-spawn-and-await.test.ts +62 -14
- package/src/__tests__/subagent-tools.test.ts +64 -0
- package/src/__tests__/sync-message-contract.test.ts +3 -3
- package/src/__tests__/terminal-tools.test.ts +12 -3
- package/src/__tests__/test-preload.ts +9 -0
- package/src/__tests__/tool-approval-handler.test.ts +587 -43
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +7 -4
- package/src/__tests__/tool-executor.test.ts +116 -0
- package/src/__tests__/tool-grant-request-escalation.test.ts +5 -0
- package/src/__tests__/tool-preview-lifecycle.test.ts +32 -29
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +5 -5
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
- package/src/__tests__/tool-start-timestamp.test.ts +4 -4
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +9 -22
- package/src/__tests__/ui-choice-copy-surfaces.test.ts +13 -13
- package/src/__tests__/ui-work-result-surface.test.ts +3 -3
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +6 -6
- package/src/__tests__/voice-session-bridge.test.ts +44 -44
- package/src/__tests__/workspace-migration-134-image-generation-mode-to-provider.test.ts +284 -0
- package/src/__tests__/workspace-policy.test.ts +482 -2
- package/src/acp/__tests__/client-handler.test.ts +3 -3
- package/src/acp/__tests__/session-manager-persistence.test.ts +10 -10
- package/src/acp/__tests__/session-manager-resume.test.ts +7 -7
- package/src/acp/client-handler.ts +3 -3
- package/src/acp/session-manager.ts +8 -8
- package/src/api/events/subagent-event.ts +2 -2
- package/src/api/responses/memory-v2-activation-log.ts +2 -2
- package/src/api/responses/subagent-detail.ts +13 -0
- package/src/approvals/AGENTS.md +2 -0
- package/src/approvals/guardian-request-resolvers.ts +118 -24
- package/src/apps/app-store.ts +95 -4
- package/src/calls/__tests__/voice-control-protocol.test.ts +57 -0
- package/src/calls/__tests__/voice-session-bridge.test.ts +229 -7
- package/src/calls/__tests__/voice-triage-escalate.test.ts +3 -4
- package/src/calls/call-controller.ts +27 -27
- package/src/calls/call-conversation-messages.ts +58 -18
- package/src/calls/voice-control-protocol.ts +56 -0
- package/src/calls/voice-session-bridge.ts +178 -65
- package/src/calls/voice-triage-escalate.ts +2 -3
- package/src/channels/config.ts +8 -0
- package/src/channels/types.ts +1 -0
- package/src/cli/commands/config.ts +49 -13
- package/src/cli/commands/memory/index.help.ts +4 -2
- package/src/cli/commands/memory/memory-retrospective.ts +5 -0
- package/src/cli/commands/webhooks.help.ts +9 -4
- package/src/cli/lib/bundled-marketplace.json +12 -0
- package/src/cli.ts +2 -109
- package/src/config/__tests__/deployment-context-defaults.test.ts +9 -0
- package/src/config/__tests__/substrate-twin-shadowing.test.ts +191 -0
- package/src/config/assistant-feature-flags.ts +1 -1
- package/src/config/bundled-skills/conversation-groups/SKILL.md +29 -0
- package/src/config/bundled-skills/conversation-groups/TOOLS.json +58 -0
- package/src/config/bundled-skills/conversation-groups/tools/group-create.ts +12 -0
- package/src/config/bundled-skills/conversation-groups/tools/group-list.ts +12 -0
- package/src/config/bundled-skills/conversation-groups/tools/move-to-group.ts +12 -0
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +13 -7
- package/src/config/bundled-skills/schedule/SKILL.md +2 -0
- package/src/config/feature-flag-cache.ts +6 -16
- package/src/config/feature-flag-registry.json +14 -38
- package/src/config/loader.ts +7 -1
- package/src/config/memory-tier.ts +15 -10
- package/src/config/memory-v3-gate.test.ts +278 -1
- package/src/config/memory-v3-gate.ts +88 -26
- package/src/config/raw-config-utils.ts +1 -1
- package/src/config/schemas/__tests__/live-voice.test.ts +27 -16
- package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
- package/src/config/schemas/live-voice.ts +33 -7
- package/src/config/schemas/llm.ts +1 -0
- package/src/config/schemas/memory-retrospective.ts +13 -0
- package/src/config/schemas/memory-substrate.ts +183 -0
- package/src/config/schemas/memory-v2.ts +3 -2
- package/src/config/schemas/memory-v3.ts +11 -4
- package/src/config/schemas/memory.ts +35 -1
- package/src/config/schemas/services.ts +10 -2
- package/src/config/substrate-twin-shadowing.ts +195 -0
- package/src/config/webhook-routing.ts +67 -0
- package/src/context/compactor.ts +10 -3
- package/src/context/token-estimator.ts +21 -0
- package/src/daemon/__tests__/channel-ui-capability.test.ts +85 -0
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +3 -3
- package/src/daemon/__tests__/embedding-reconcile.test.ts +3 -3
- package/src/daemon/__tests__/inference-profile-notification.test.ts +3 -6
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +5 -5
- package/src/daemon/__tests__/web-search-status-text.test.ts +2 -2
- package/src/daemon/channel-ui-capability.ts +70 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +4 -4
- package/src/daemon/conversation-agent-loop.ts +12 -5
- package/src/daemon/conversation-evictor.ts +26 -4
- package/src/daemon/conversation-launch.ts +11 -14
- package/src/daemon/conversation-lineage.ts +76 -0
- package/src/daemon/conversation-messaging.ts +14 -14
- package/src/daemon/conversation-notifiers.ts +2 -2
- package/src/daemon/conversation-process.ts +133 -21
- package/src/daemon/conversation-queue-manager.ts +7 -7
- package/src/daemon/conversation-runtime-assembly.ts +16 -0
- package/src/daemon/conversation-store.ts +11 -3
- package/src/daemon/conversation-surfaces.ts +8 -14
- package/src/daemon/conversation-tool-setup.ts +13 -7
- package/src/daemon/conversation-usage.ts +12 -11
- package/src/daemon/conversation.ts +38 -15
- package/src/daemon/disk-pressure-guard.ts +5 -12
- package/src/daemon/embedding-reconcile.ts +14 -9
- package/src/daemon/handlers/config-channels.ts +40 -134
- package/src/daemon/handlers/config-model.ts +15 -7
- package/src/daemon/handlers/conversations.ts +4 -2
- package/src/daemon/handlers/shared.ts +29 -0
- package/src/daemon/host-proxy-base.ts +4 -4
- package/src/daemon/lifecycle.ts +13 -0
- package/src/daemon/message-protocol.ts +8 -144
- package/src/daemon/message-types/computer-use.ts +0 -12
- package/src/daemon/message-types/conversations.ts +9 -345
- package/src/daemon/message-types/host-app-control.ts +0 -9
- package/src/daemon/message-types/host-browser.ts +0 -7
- package/src/daemon/message-types/host-ui-snapshot.ts +0 -7
- package/src/daemon/message-types/messages.ts +0 -48
- package/src/daemon/message-types/notifications.ts +0 -7
- package/src/daemon/message-types/skills.ts +0 -5
- package/src/daemon/message-types/surfaces.ts +0 -9
- package/src/daemon/message-types/sync.ts +0 -2
- package/src/daemon/process-message.ts +5 -5
- package/src/daemon/skill-memory-refresh.ts +5 -5
- package/src/daemon/tool-side-effects.ts +32 -16
- package/src/daemon/trust-context.ts +1 -1
- package/src/daemon/wake-conversation-ops.ts +4 -4
- package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +100 -7
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +67 -0
- package/src/heartbeat/heartbeat-run-store.ts +81 -4
- package/src/heartbeat/heartbeat-service.ts +32 -1
- package/src/home/__tests__/feed-writer.test.ts +7 -7
- package/src/home/__tests__/home-content-refresh.test.ts +3 -0
- package/src/home/__tests__/suggested-prompts.test.ts +1 -0
- package/src/home/feed-writer.ts +6 -13
- package/src/home/home-content-refresh.ts +6 -9
- package/src/home/relationship-state-writer.ts +5 -12
- package/src/home/suggested-prompts-cache.ts +6 -19
- package/src/ipc/__tests__/events-publish-client.test.ts +67 -0
- package/src/ipc/events-publish-client.ts +44 -0
- package/src/ipc/routes/__tests__/conversation-sync-ipc-routes.test.ts +2 -2
- package/src/ipc/routes/__tests__/events-ipc-routes.test.ts +38 -9
- package/src/ipc/routes/events-ipc-routes.ts +11 -31
- package/src/live-voice/__tests__/front-decision.test.ts +4 -176
- package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +276 -68
- package/src/live-voice/__tests__/live-voice-continuation-fork-hydration.test.ts +286 -0
- package/src/live-voice/__tests__/live-voice-events.test.ts +6 -3
- package/src/live-voice/__tests__/live-voice-progress.test.ts +185 -46
- package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +24 -59
- package/src/live-voice/__tests__/live-voice-tts-session.test.ts +38 -54
- package/src/live-voice/__tests__/live-voice-vad.test.ts +1154 -636
- package/src/live-voice/front-decision.ts +5 -155
- package/src/live-voice/live-voice-metrics.ts +4 -1
- package/src/live-voice/live-voice-session.ts +1288 -439
- package/src/live-voice/progress-phrases.ts +17 -0
- package/src/live-voice/protocol.ts +15 -0
- package/src/media/app-icon-generator.ts +15 -8
- package/src/media/avatar-router.ts +9 -5
- package/src/media/image-credentials.ts +42 -10
- package/src/media/image-service.ts +1 -13
- package/src/media/types.ts +26 -3
- package/src/notifications/AGENTS.md +2 -0
- package/src/notifications/__tests__/broadcaster.test.ts +95 -0
- package/src/notifications/adapters/macos.ts +3 -3
- package/src/notifications/broadcaster.ts +57 -0
- package/src/notifications/copy-composer.ts +0 -15
- package/src/notifications/decision-engine.ts +21 -22
- package/src/notifications/guardian-question-mode.ts +57 -2
- package/src/notifications/home-feed-side-effect.ts +4 -0
- package/src/notifications/signal.ts +6 -4
- package/src/notifications/trusted-contact-payloads.ts +3 -4
- package/src/notifications/vellum-card-affinity.ts +39 -0
- package/src/oauth/AGENTS.md +1 -1
- package/src/permissions/channel-permission-query.test.ts +69 -0
- package/src/permissions/channel-permission-query.ts +73 -1
- package/src/permissions/checker.test.ts +298 -15
- package/src/permissions/checker.ts +102 -36
- package/src/permissions/confirmation-guardian-request.test.ts +2 -2
- package/src/permissions/confirmation-guardian-request.ts +2 -2
- package/src/permissions/gateway-threshold-reader.test.ts +224 -17
- package/src/permissions/gateway-threshold-reader.ts +82 -10
- package/src/permissions/ipc-risk-types.ts +8 -0
- package/src/permissions/prompter.ts +5 -5
- package/src/permissions/question-guardian-request.test.ts +222 -0
- package/src/permissions/question-guardian-request.ts +179 -0
- package/src/permissions/question-prompter.test.ts +8 -8
- package/src/permissions/question-prompter.ts +18 -0
- package/src/permissions/secret-prompter.ts +2 -4
- package/src/permissions/workspace-policy.ts +269 -34
- package/src/persistence/__tests__/lifecycle-quiesce.test.ts +82 -0
- package/src/persistence/__tests__/message-content-file.test.ts +58 -3
- package/src/persistence/conversation-crud.ts +93 -0
- package/src/persistence/conversation-key-store.ts +63 -0
- package/src/persistence/conversation-parent.ts +27 -0
- package/src/persistence/db-async-query.ts +1 -1
- package/src/persistence/db-singleton.ts +14 -27
- package/src/persistence/delivery-crud.ts +45 -0
- package/src/persistence/embeddings/embedding-backend.ts +2 -1
- package/src/persistence/embeddings/embedding-identity.ts +7 -3
- package/src/persistence/job-utils.ts +32 -27
- package/src/persistence/jobs-store.ts +92 -3
- package/src/persistence/lifecycle-quiesce.ts +80 -0
- package/src/persistence/llm-usage-store.ts +45 -8
- package/src/persistence/message-content-file.ts +4 -4
- package/src/persistence/migrations/336-move-memory-v2-activation-logs-to-memory-db.ts +1 -1
- package/src/persistence/migrations/351-schedule-skill-script-handoff.ts +39 -0
- package/src/persistence/migrations/352-drop-schedule-skill-script-handoff.test.ts +83 -0
- package/src/persistence/migrations/352-drop-schedule-skill-script-handoff.ts +36 -0
- package/src/persistence/migrations/353-add-llm-usage-conversation-type.test.ts +110 -0
- package/src/persistence/migrations/353-add-llm-usage-conversation-type.ts +49 -0
- package/src/persistence/migrations/354-backfill-app-conversation-lineage.ts +41 -0
- package/src/persistence/schema/infrastructure.ts +11 -0
- package/src/persistence/steps.ts +9 -1
- package/src/plugin-api/__tests__/publish-event-forwarding.test.ts +113 -0
- package/src/plugin-api/__tests__/publish-event.test.ts +57 -0
- package/src/plugin-api/conversation-turn.ts +4 -4
- package/src/plugin-api/event-hub-facade.ts +15 -6
- package/src/plugin-api/index.ts +10 -4
- package/src/plugin-api/publish-event.ts +36 -0
- package/src/plugins/AGENTS.md +2 -0
- package/src/plugins/defaults/compaction/window-manager.ts +9 -0
- package/src/plugins/defaults/index.ts +9 -13
- package/src/plugins/defaults/memory/AGENTS.md +775 -0
- package/src/plugins/defaults/memory/__tests__/capability-seed-embed-gate.test.ts +186 -0
- package/src/plugins/defaults/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +1 -1
- package/src/plugins/defaults/memory/__tests__/indexer-tier-dispatch.test.ts +129 -0
- package/src/plugins/defaults/memory/__tests__/jobs-worker-quiesce-gate.test.ts +91 -0
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v1-graph-substrate-noop.test.ts +342 -0
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +9 -1
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-schedule.test.ts +36 -1
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-sweep-defer.test.ts +9 -1
- package/src/plugins/defaults/memory/__tests__/memory-log-stores-degraded.test.ts +2 -2
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +44 -10
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +151 -10
- package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +1155 -0
- package/src/plugins/defaults/memory/__tests__/memory-v2-activation-log-store.test.ts +1 -1
- package/src/plugins/defaults/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -3
- package/src/plugins/defaults/memory/__tests__/tools-delete-memory-page.test.ts +1 -1
- package/src/plugins/defaults/memory/context-search/sources/memory-v2.ts +71 -35
- package/src/plugins/defaults/memory/context-search/sources/memory.ts +5 -1
- package/src/plugins/defaults/memory/fork-conversation-memory.ts +4 -4
- package/src/plugins/defaults/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +80 -10
- package/src/plugins/defaults/memory/graph/__tests__/handle-remember-v2.test.ts +1 -1
- package/src/plugins/defaults/memory/graph/capability-seed.ts +24 -10
- package/src/plugins/defaults/memory/graph/conversation-graph-memory.ts +123 -49
- package/src/plugins/defaults/memory/graph/graph-search.ts +6 -118
- package/src/plugins/defaults/memory/graph/in-context-tracker.test.ts +173 -0
- package/src/plugins/defaults/memory/graph/in-context-tracker.ts +109 -0
- package/src/plugins/defaults/memory/graph/store.ts +1 -0
- package/src/plugins/defaults/memory/graph/tool-handlers.test.ts +1 -1
- package/src/plugins/defaults/memory/graph/tool-handlers.ts +5 -2
- package/src/plugins/defaults/memory/graph-topology/__tests__/build-memory-graph.test.ts +1 -1
- package/src/plugins/defaults/memory/graph-topology/build-memory-graph.ts +6 -9
- package/src/plugins/defaults/memory/hooks/__tests__/user-prompt-submit.test.ts +30 -16
- package/src/plugins/defaults/memory/hooks/user-prompt-submit.ts +18 -14
- package/src/plugins/defaults/memory/indexer.ts +146 -89
- package/src/plugins/defaults/memory/injectors.ts +86 -41
- package/src/plugins/defaults/memory/job-handlers.ts +130 -39
- package/src/plugins/defaults/memory/jobs/__tests__/embed-concept-page.test.ts +2 -2
- package/src/plugins/defaults/memory/jobs/embed-concept-page.ts +22 -10
- package/src/plugins/defaults/memory/jobs-worker.ts +279 -208
- package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +4 -2
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +40 -3
- package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +99 -11
- package/src/plugins/defaults/memory/src/__tests__/memory-v2-routes.test.ts +5 -3
- package/src/plugins/defaults/memory/src/__tests__/memory-v2-simulate-route.test.ts +3 -4
- package/src/plugins/defaults/memory/src/memory-graph-routes.ts +2 -1
- package/src/plugins/defaults/memory/src/memory-item-routes.test.ts +7 -5
- package/src/plugins/defaults/memory/src/memory-item-routes.ts +51 -19
- package/src/plugins/defaults/memory/src/memory-v2-routes.ts +31 -20
- package/src/plugins/defaults/memory/startup.ts +58 -21
- package/src/plugins/defaults/memory/substrate/__tests__/boot-maintenance.test.ts +335 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/cli-command-store.test.ts +14 -8
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/consolidation-job.test.ts +51 -21
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/edge-index.test.ts +1 -1
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/frontmatter-sweep.test.ts +3 -3
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/page-index.test.ts +1 -1
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/page-store.test.ts +1 -1
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/prompts-consolidation.test.ts +2 -2
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/qdrant.test.ts +23 -14
- package/src/plugins/defaults/memory/substrate/__tests__/reembed-job.test.ts +262 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sim.test.ts +9 -12
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/skill-content.test.ts +2 -2
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/skill-store.test.ts +9 -9
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sparse-bm25.test.ts +12 -5
- package/src/plugins/defaults/memory/substrate/__tests__/spread.test.ts +276 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/static-context.test.ts +17 -8
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sweep-job.test.ts +9 -9
- package/src/plugins/defaults/memory/{v3/substrate/memory-v2-startup.ts → substrate/boot-maintenance.ts} +43 -24
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/cli-command-store.ts +13 -8
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/consolidation-job.ts +51 -27
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/constants.ts +1 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/edge-index.ts +28 -9
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/frontmatter-sweep.ts +14 -7
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/injected-block-slugs.ts +9 -3
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/page-index.ts +29 -10
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/page-store.ts +35 -12
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/prompts/consolidation.ts +14 -8
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/prompts/sweep.ts +4 -1
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/qdrant.ts +96 -36
- package/src/plugins/defaults/memory/substrate/reembed-job.ts +54 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/sim.ts +26 -15
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/skill-content.ts +1 -1
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/skill-store.ts +13 -8
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/sparse-bm25.ts +27 -10
- package/src/plugins/defaults/memory/substrate/spread.ts +165 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/static-context.ts +12 -7
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/sweep-job.ts +20 -15
- package/src/plugins/defaults/memory/substrate/tuning.ts +93 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/types.ts +7 -4
- package/src/plugins/defaults/memory/tools.test.ts +1 -1
- package/src/plugins/defaults/memory/tools.ts +1 -1
- package/src/plugins/defaults/memory/v1/README.md +5 -0
- package/src/plugins/defaults/memory/{__tests__ → v1/__tests__}/filing-jobs.test.ts +4 -4
- package/src/plugins/defaults/memory/{filing-jobs.ts → v1/filing-jobs.ts} +3 -3
- package/src/plugins/defaults/memory/{graph → v1/graph}/bootstrap.test.ts +68 -6
- package/src/plugins/defaults/memory/{graph → v1/graph}/bootstrap.ts +40 -21
- package/src/plugins/defaults/memory/{graph → v1/graph}/consolidation.ts +14 -14
- package/src/plugins/defaults/memory/{graph → v1/graph}/decay.test.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/decay.ts +3 -3
- package/src/plugins/defaults/memory/{graph → v1/graph}/extraction-job.ts +5 -5
- package/src/plugins/defaults/memory/{graph → v1/graph}/extraction.test.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/extraction.ts +20 -14
- package/src/plugins/defaults/memory/{graph → v1/graph}/graph-search.test.ts +3 -3
- package/src/plugins/defaults/memory/v1/graph/graph-search.ts +123 -0
- package/src/plugins/defaults/memory/{graph → v1/graph}/injection.test.ts +1 -118
- package/src/plugins/defaults/memory/{graph → v1/graph}/injection.ts +9 -111
- package/src/plugins/defaults/memory/{graph → v1/graph}/narrative.ts +6 -6
- package/src/plugins/defaults/memory/{graph → v1/graph}/pattern-scan.ts +5 -5
- package/src/plugins/defaults/memory/{graph → v1/graph}/retriever.test.ts +135 -42
- package/src/plugins/defaults/memory/{graph → v1/graph}/retriever.ts +40 -22
- package/src/plugins/defaults/memory/{graph → v1/graph}/scoring.test.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/scoring.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/serendipity.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/triggers.test.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/triggers.ts +1 -1
- package/src/plugins/defaults/memory/{identity-context.ts → v1/identity-context.ts} +4 -4
- package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/backfill.ts +6 -6
- package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/embedding.test.ts +6 -6
- package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/embedding.ts +6 -6
- package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/index-maintenance.ts +8 -8
- package/src/plugins/defaults/memory/{jobs → v1/jobs}/embed-pkb-file.test.ts +7 -7
- package/src/plugins/defaults/memory/{jobs → v1/jobs}/embed-pkb-file.ts +5 -5
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/autoinject.ts +1 -1
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/context.ts +2 -2
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-index.test.ts +3 -3
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-index.ts +2 -2
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-reconcile.test.ts +3 -3
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-reconcile.ts +2 -2
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-search.test.ts +3 -3
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-search.ts +6 -6
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/types.ts +3 -5
- package/src/plugins/defaults/memory/{pkb-schedule.ts → v1/pkb-schedule.ts} +2 -2
- package/src/plugins/defaults/memory/{search/semantic.ts → v1/semantic-search.ts} +1 -1
- package/src/plugins/defaults/memory/v2/__tests__/activation-store.test.ts +1 -1
- package/src/plugins/defaults/memory/v2/__tests__/activation.test.ts +11 -274
- package/src/plugins/defaults/memory/v2/__tests__/backfill-jobs.test.ts +9 -131
- package/src/plugins/defaults/memory/v2/__tests__/harness-compare.test.ts +1 -1
- package/src/plugins/defaults/memory/v2/__tests__/harness-oracle.test.ts +1 -1
- package/src/plugins/defaults/memory/v2/__tests__/harness-replay-input.test.ts +1 -1
- package/src/plugins/defaults/memory/v2/__tests__/injection.test.ts +14 -10
- package/src/plugins/defaults/memory/v2/__tests__/reranker.test.ts +7 -5
- package/src/plugins/defaults/memory/v2/__tests__/router.test.ts +12 -6
- package/src/plugins/defaults/memory/{memory-v2-activation-log-store.ts → v2/activation-log-store.ts} +2 -2
- package/src/plugins/defaults/memory/v2/activation-store.ts +22 -8
- package/src/plugins/defaults/memory/v2/activation.ts +30 -163
- package/src/plugins/defaults/memory/v2/backfill-jobs.ts +7 -54
- package/src/plugins/defaults/memory/{memory-v2-concept-frequency.ts → v2/concept-frequency.ts} +3 -3
- package/src/plugins/defaults/memory/v2/harness/oracle.ts +1 -1
- package/src/plugins/defaults/memory/v2/harness/replay-input.ts +2 -2
- package/src/plugins/defaults/memory/v2/harness/retriever.ts +1 -1
- package/src/plugins/defaults/memory/v2/injection.ts +36 -26
- package/src/plugins/defaults/memory/v2/migration.ts +2 -2
- package/src/plugins/defaults/memory/{rerank-local.ts → v2/rerank-local.ts} +44 -18
- package/src/plugins/defaults/memory/v2/reranker.ts +29 -11
- package/src/plugins/defaults/memory/v2/router.ts +38 -15
- package/src/plugins/defaults/memory/v3/__tests__/candidate-match.test.ts +5 -3
- package/src/plugins/defaults/memory/v3/__tests__/carry-integration.test.ts +21 -8
- package/src/plugins/defaults/memory/v3/__tests__/edge.test.ts +1 -1
- package/src/plugins/defaults/memory/v3/__tests__/live-integration.test.ts +1 -1
- package/src/plugins/defaults/memory/v3/__tests__/maintain-job.test.ts +4 -1
- package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +181 -3
- package/src/plugins/defaults/memory/v3/__tests__/selection-log-store.test.ts +3 -0
- package/src/plugins/defaults/memory/v3/__tests__/shadow-integration.test.ts +14 -5
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +40 -50
- package/src/plugins/defaults/memory/v3/__tests__/tuning-profile.test.ts +1 -0
- package/src/plugins/defaults/memory/v3/candidate-match.ts +2 -2
- package/src/plugins/defaults/memory/v3/capabilities.ts +6 -4
- package/src/plugins/defaults/memory/v3/card.ts +25 -9
- package/src/plugins/defaults/memory/v3/edge.ts +52 -18
- package/src/plugins/defaults/memory/v3/gate.ts +4 -4
- package/src/plugins/defaults/memory/v3/injector.ts +10 -3
- package/src/plugins/defaults/memory/v3/maintain-job.ts +3 -3
- package/src/plugins/defaults/memory/v3/orchestrate.ts +100 -18
- package/src/plugins/defaults/memory/v3/page-content.ts +26 -10
- package/src/plugins/defaults/memory/v3/prune.ts +40 -16
- package/src/plugins/defaults/memory/v3/selection-log-store.ts +34 -12
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +9 -13
- package/src/plugins/defaults/memory/v3/span-query.test.ts +86 -0
- package/src/plugins/defaults/memory/v3/span-query.ts +71 -0
- package/src/plugins/defaults/memory/v3/tuning-profile.ts +3 -0
- package/src/plugins/defaults/memory/v3/types.ts +4 -1
- package/src/plugins/defaults/memory/v3-eval/eval-packets.ts +2 -2
- package/src/plugins/defaults/memory/validation.ts +1 -1
- package/src/plugins/defaults/memory/worker.ts +2 -1
- package/src/plugins/defaults/platform-hosted/__tests__/reengage.test.ts +104 -12
- package/src/plugins/defaults/platform-hosted/routes/reengage.ts +104 -12
- package/src/plugins/types.ts +2 -2
- package/src/prompts/sections.ts +4 -16
- package/src/providers/__tests__/registry-native-web-search.test.ts +47 -2
- package/src/providers/anthropic/client.ts +15 -6
- package/src/providers/content-block-schema.ts +26 -0
- package/src/providers/inference/__tests__/connections-credential-normalize.test.ts +87 -0
- package/src/providers/inference/adapter-factory.ts +6 -0
- package/src/providers/inference/connections.ts +30 -14
- package/src/providers/model-catalog.ts +77 -0
- package/src/providers/openai/__tests__/chat-completions-input-audio.test.ts +260 -0
- package/src/providers/openai/chat-completions-provider.ts +65 -17
- package/src/providers/openai/input-audio.ts +76 -0
- package/src/providers/openrouter/client.ts +0 -2
- package/src/providers/platform-proxy/constants.ts +4 -0
- package/src/providers/poolside/client.ts +42 -0
- package/src/providers/registry.ts +40 -8
- package/src/providers/retry.ts +2 -0
- package/src/providers/types.ts +39 -1
- package/src/providers/vercel-ai-gateway/client.ts +0 -2
- package/src/runtime/AGENTS.md +7 -5
- package/src/runtime/__tests__/question-request-guardian-bridge.test.ts +173 -0
- package/src/runtime/__tests__/question-resolution.test.ts +111 -0
- package/src/runtime/access-request-helper.ts +7 -15
- package/src/runtime/assistant-event-hub.ts +43 -31
- package/src/runtime/assistant-event-publish-options.ts +31 -0
- package/src/runtime/assistant-event.ts +19 -30
- package/src/runtime/assistant-stream-state.ts +4 -4
- package/src/runtime/channel-approvals.ts +0 -25
- package/src/runtime/channel-readiness-service.ts +99 -40
- package/src/runtime/channel-retry-sweep.ts +38 -15
- package/src/runtime/confirmation-request-guardian-bridge.ts +4 -0
- package/src/runtime/guardian-reply-router.ts +108 -0
- package/src/runtime/http-server.ts +8 -0
- package/src/runtime/http-types.ts +2 -2
- package/src/runtime/process-role.ts +42 -0
- package/src/runtime/question-request-guardian-bridge.ts +184 -0
- package/src/runtime/question-resolution.ts +153 -0
- package/src/runtime/routes/__tests__/bookmark-routes.test.ts +6 -2
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/subagents-routes.test.ts +250 -0
- package/src/runtime/routes/__tests__/webhook-routes.test.ts +201 -0
- package/src/runtime/routes/acp-routes.ts +2 -2
- package/src/runtime/routes/bookmark-routes.ts +3 -15
- package/src/runtime/routes/canned-message-complete.ts +2 -2
- package/src/runtime/routes/consolidation-routes.ts +8 -2
- package/src/runtime/routes/conversation-list-routes.ts +3 -19
- package/src/runtime/routes/conversation-management-routes.ts +1 -5
- package/src/runtime/routes/conversation-query-routes.ts +52 -8
- package/src/runtime/routes/conversation-routes.ts +36 -22
- package/src/runtime/routes/credential-request-routes.ts +0 -1
- package/src/runtime/routes/filing-routes.ts +7 -7
- package/src/runtime/routes/global-search-routes.ts +1 -1
- package/src/runtime/routes/guardian-approval-prompt.ts +2 -2
- package/src/runtime/routes/image-generation-routes.ts +12 -9
- package/src/runtime/routes/inbound-message-handler.ts +17 -0
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +50 -0
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +19 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +4 -4
- package/src/runtime/routes/inbound-stages/inbound-content-prep.test.ts +129 -0
- package/src/runtime/routes/inbound-stages/inbound-content-prep.ts +141 -9
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/lifecycle-routes.ts +199 -0
- package/src/runtime/routes/platform-routes.ts +3 -8
- package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +7 -7
- package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +5 -5
- package/src/runtime/routes/question-routes.ts +34 -87
- package/src/runtime/routes/secret-routes.ts +11 -1
- package/src/runtime/routes/settings-routes.ts +8 -18
- package/src/runtime/routes/subagents-routes.ts +35 -8
- package/src/runtime/routes/upgrade-broadcast-routes.ts +4 -5
- package/src/runtime/routes/webhook-routes.ts +89 -30
- package/src/runtime/routes/workspace-routes.test.ts +7 -4
- package/src/runtime/slack-reply-session.test.ts +12 -12
- package/src/runtime/slack-reply-session.ts +17 -17
- package/src/runtime/sync/sync-publisher.test.ts +7 -5
- package/src/runtime/tool-grant-request-helper.ts +4 -0
- package/src/schedule/schedule-store.ts +70 -0
- package/src/schedule/scheduler.ts +27 -0
- package/src/security/AGENTS.md +1 -1
- package/src/security/credential-key.ts +17 -0
- package/src/security/secret-ingress.ts +14 -105
- package/src/security/secret-patterns.ts +8 -139
- package/src/security/secret-scanner.ts +8 -3
- package/src/security/store-path-override.ts +6 -16
- package/src/sequence/store.ts +8 -0
- package/src/signals/emit-event.ts +5 -10
- package/src/signals/event-stream.ts +20 -10
- package/src/subagent/manager.ts +76 -25
- package/src/subagent/notify.ts +8 -0
- package/src/subagent/types.ts +13 -3
- package/src/telegram/__tests__/webhook-health.test.ts +442 -0
- package/src/telegram/webhook-health.ts +478 -0
- package/src/telemetry/AGENTS.md +6 -0
- package/src/telemetry/memory-corpus-size.test.ts +129 -0
- package/src/telemetry/memory-corpus-size.ts +184 -0
- package/src/telemetry/memory-tier-reporter.test.ts +67 -2
- package/src/telemetry/memory-tier-reporter.ts +30 -3
- package/src/tools/__tests__/conversation-group-tool-input-schemas.test.ts +61 -0
- package/src/tools/__tests__/document-tool-input-schemas.test.ts +103 -0
- package/src/tools/__tests__/followup-call-acp-tool-input-schemas.test.ts +125 -0
- package/src/tools/__tests__/schedule-tool-input-schemas.test.ts +83 -0
- package/src/tools/__tests__/subagent-workflow-tool-input-schemas.test.ts +116 -0
- package/src/tools/__tests__/tool-input-schemas.test.ts +192 -0
- package/src/tools/__tests__/tool-schema-drift-harness.ts +142 -0
- package/src/tools/acp/abort.ts +21 -1
- package/src/tools/acp/context.ts +5 -5
- package/src/tools/acp/spawn.test.ts +15 -5
- package/src/tools/acp/spawn.ts +26 -3
- package/src/tools/acp/status.ts +20 -1
- package/src/tools/acp/steer.test.ts +20 -0
- package/src/tools/acp/steer.ts +23 -2
- package/src/tools/apps/resolve-app-id.ts +15 -3
- package/src/tools/ask-question/ask-question-tool.test.ts +65 -0
- package/src/tools/ask-question/ask-question-tool.ts +68 -92
- package/src/tools/browser/browser-screencast.ts +6 -6
- package/src/tools/calls/call-end.ts +24 -3
- package/src/tools/calls/call-start.ts +35 -11
- package/src/tools/calls/call-status.ts +20 -1
- package/src/tools/conversation-groups/group_create.ts +63 -0
- package/src/tools/conversation-groups/group_list.ts +20 -0
- package/src/tools/conversation-groups/group_shared.ts +52 -0
- package/src/tools/conversation-groups/move_to_group.ts +106 -0
- package/src/tools/document/document-comment-tool.test.ts +49 -0
- package/src/tools/document/document-comment-tool.ts +45 -6
- package/src/tools/document/document-tool.ts +142 -24
- package/src/tools/executor.ts +27 -13
- package/src/tools/filesystem/edit.ts +62 -60
- package/src/tools/filesystem/list.ts +36 -29
- package/src/tools/filesystem/read.ts +56 -39
- package/src/tools/filesystem/write.ts +44 -38
- package/src/tools/followups/followup_create.ts +41 -12
- package/src/tools/followups/followup_list.ts +34 -6
- package/src/tools/followups/followup_resolve.ts +26 -4
- package/src/tools/host-filesystem/edit.ts +50 -60
- package/src/tools/host-filesystem/read.ts +45 -39
- package/src/tools/host-filesystem/write.ts +31 -36
- package/src/tools/host-terminal/host-shell.ts +76 -62
- package/src/tools/policy-context.ts +27 -10
- package/src/tools/schedule/create.ts +76 -33
- package/src/tools/schedule/delete.ts +21 -2
- package/src/tools/schedule/list.ts +25 -3
- package/src/tools/schedule/update.ts +105 -48
- package/src/tools/shared/filesystem/path-policy.ts +246 -40
- package/src/tools/shared/zod-tool-schema.ts +117 -0
- package/src/tools/subagent/abort.ts +12 -4
- package/src/tools/subagent/consult-deadline.ts +9 -3
- package/src/tools/subagent/message.ts +21 -5
- package/src/tools/subagent/notify-parent.ts +44 -23
- package/src/tools/subagent/read.ts +15 -4
- package/src/tools/subagent/resolve.ts +26 -4
- package/src/tools/subagent/spawn.ts +37 -13
- package/src/tools/subagent/status.ts +12 -4
- package/src/tools/system/request-permission.ts +35 -26
- package/src/tools/terminal/shell.ts +68 -55
- package/src/tools/tool-approval-handler.ts +327 -53
- package/src/tools/tool-input-schemas.ts +85 -0
- package/src/tools/tool-types.ts +7 -0
- package/src/tools/types.ts +8 -0
- package/src/tools/workflows/manage-workflows.ts +30 -2
- package/src/tools/workflows/run-workflow.test.ts +54 -2
- package/src/tools/workflows/run-workflow.ts +32 -4
- package/src/util/fs-symlinks.ts +30 -0
- package/src/util/log-redact.ts +7 -3
- package/src/util/platform.ts +15 -0
- package/src/vellum-assistant-namespace.d.ts +80 -0
- package/src/watcher/watcher-store.ts +8 -0
- package/src/workflows/leaf-runner.test.ts +104 -2
- package/src/workflows/leaf-runner.ts +31 -6
- package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +2 -2
- package/src/workspace/migrations/134-image-generation-mode-to-provider.ts +128 -0
- package/src/workspace/migrations/135-copy-substrate-tunables.ts +248 -0
- package/src/workspace/migrations/__tests__/135-copy-substrate-tunables.test.ts +446 -0
- package/src/workspace/migrations/__tests__/backfill-v3-leaves.test.ts +2 -2
- package/src/workspace/migrations/registry.ts +4 -0
- package/tsconfig.plugin-api.json +1 -1
- package/src/__tests__/memory-retrieval-budget.test.ts +0 -49
- package/src/__tests__/secret-patterns.test.ts +0 -27
- package/src/config/__tests__/proc-to-skills.test.ts +0 -21
- package/src/config/memory-tier.test.ts +0 -44
- package/src/daemon/message-types/acp.ts +0 -20
- package/src/daemon/message-types/apps.ts +0 -11
- package/src/daemon/message-types/background-tools.ts +0 -14
- package/src/daemon/message-types/bookmarks.ts +0 -13
- package/src/daemon/message-types/contacts.ts +0 -13
- package/src/daemon/message-types/document-comments.ts +0 -14
- package/src/daemon/message-types/documents.ts +0 -13
- package/src/daemon/message-types/home.ts +0 -15
- package/src/daemon/message-types/host-bash.ts +0 -12
- package/src/daemon/message-types/host-cu.ts +0 -10
- package/src/daemon/message-types/host-file.ts +0 -12
- package/src/daemon/message-types/host-transfer.ts +0 -12
- package/src/daemon/message-types/integrations.ts +0 -90
- package/src/daemon/message-types/memory.ts +0 -10
- package/src/daemon/message-types/schedules.ts +0 -14
- package/src/daemon/message-types/settings.ts +0 -17
- package/src/daemon/message-types/subagents.ts +0 -63
- package/src/daemon/message-types/upgrades.ts +0 -14
- package/src/daemon/message-types/workflows.ts +0 -25
- package/src/daemon/message-types/workspace.ts +0 -137
- package/src/live-voice/ack-phrases.ts +0 -58
- package/src/plugins/defaults/memory/retrieval-budget.ts +0 -29
- package/src/plugins/defaults/memory/v3/__tests__/gate-flag.test.ts +0 -69
- package/src/plugins/defaults/memory/v3/gate-flag.ts +0 -20
- package/src/plugins/defaults/memory/v3/substrate/__tests__/memory-v2-startup.test.ts +0 -86
- package/src/plugins/defaults/memory/v3/substrate/memory-v2-startup.test.ts +0 -205
- /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/concept-page-frontmatter-schema.test.ts +0 -0
- /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/consolidation-prompt-flag-gating-guard.test.ts +0 -0
- /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/injected-block-slugs.test.ts +0 -0
- /package/src/plugins/defaults/memory/{v3/substrate → substrate}/cli-command-content.ts +0 -0
|
@@ -12,7 +12,7 @@ import { describe, expect, mock, test } from "bun:test";
|
|
|
12
12
|
|
|
13
13
|
import { CompactionCircuit } from "../agent/compaction-circuit.js";
|
|
14
14
|
import type { AgentEvent } from "../agent/loop.js";
|
|
15
|
-
import type {
|
|
15
|
+
import type { AssistantEvent } from "../api/index.js";
|
|
16
16
|
import type { ContextWindowResult } from "../plugins/defaults/compaction/window-manager.js";
|
|
17
17
|
import type { Message, ProviderResponse } from "../providers/types.js";
|
|
18
18
|
|
|
@@ -233,7 +233,7 @@ function makeProvider() {
|
|
|
233
233
|
}
|
|
234
234
|
|
|
235
235
|
function makeConversation(
|
|
236
|
-
collected:
|
|
236
|
+
collected: AssistantEvent[],
|
|
237
237
|
id = "conv-compact-events",
|
|
238
238
|
): Conversation {
|
|
239
239
|
return new Conversation(
|
|
@@ -254,7 +254,7 @@ function makeConversation(
|
|
|
254
254
|
|
|
255
255
|
describe("forceCompact event emission", () => {
|
|
256
256
|
test("emits context_compacted and a usage_update without contextWindow when compacted", async () => {
|
|
257
|
-
const collected:
|
|
257
|
+
const collected: AssistantEvent[] = [];
|
|
258
258
|
mockCompactResult = {
|
|
259
259
|
messages: [],
|
|
260
260
|
compacted: true,
|
|
@@ -279,7 +279,7 @@ describe("forceCompact event emission", () => {
|
|
|
279
279
|
);
|
|
280
280
|
expect(compactedEvents.length).toBe(1);
|
|
281
281
|
const compactedEvent = compactedEvents[0] as Extract<
|
|
282
|
-
|
|
282
|
+
AssistantEvent,
|
|
283
283
|
{ type: "context_compacted" }
|
|
284
284
|
>;
|
|
285
285
|
expect(compactedEvent.conversationId).toBe("conv-compact-events");
|
|
@@ -298,7 +298,7 @@ describe("forceCompact event emission", () => {
|
|
|
298
298
|
const usageEvents = collected.filter((m) => m.type === "usage_update");
|
|
299
299
|
expect(usageEvents.length).toBe(1);
|
|
300
300
|
const usageEvent = usageEvents[0] as Extract<
|
|
301
|
-
|
|
301
|
+
AssistantEvent,
|
|
302
302
|
{ type: "usage_update" }
|
|
303
303
|
>;
|
|
304
304
|
// `context_compacted` is now the single source of truth for the UI
|
|
@@ -312,7 +312,7 @@ describe("forceCompact event emission", () => {
|
|
|
312
312
|
});
|
|
313
313
|
|
|
314
314
|
test("emits context_compacted even when summary LLM was skipped (truncation-only path)", async () => {
|
|
315
|
-
const collected:
|
|
315
|
+
const collected: AssistantEvent[] = [];
|
|
316
316
|
mockCompactResult = {
|
|
317
317
|
messages: [],
|
|
318
318
|
compacted: true,
|
|
@@ -342,7 +342,7 @@ describe("forceCompact event emission", () => {
|
|
|
342
342
|
);
|
|
343
343
|
expect(compactedEvents.length).toBe(1);
|
|
344
344
|
const compactedEvent = compactedEvents[0] as Extract<
|
|
345
|
-
|
|
345
|
+
AssistantEvent,
|
|
346
346
|
{ type: "context_compacted" }
|
|
347
347
|
>;
|
|
348
348
|
expect(compactedEvent.conversationId).toBe("conv-compact-trunc");
|
|
@@ -356,7 +356,7 @@ describe("forceCompact event emission", () => {
|
|
|
356
356
|
});
|
|
357
357
|
|
|
358
358
|
test("skips emission when compacted is false", async () => {
|
|
359
|
-
const collected:
|
|
359
|
+
const collected: AssistantEvent[] = [];
|
|
360
360
|
mockCompactResult = {
|
|
361
361
|
messages: [],
|
|
362
362
|
compacted: false,
|
|
@@ -76,9 +76,10 @@ function readConfig(): Record<string, unknown> {
|
|
|
76
76
|
// Without IS_PLATFORM, services split by Zod schema default: google/notion-oauth
|
|
77
77
|
// resolve to "managed" (per JARVIS-966), the rest resolve to "your-own".
|
|
78
78
|
// web-search is deliberately absent: `provider` is its only axis, so the
|
|
79
|
-
// platform context injects no mode for it.
|
|
79
|
+
// platform context injects no mode for it. image-generation is also absent:
|
|
80
|
+
// its managed axis is the provider ("vellum" proxies through the platform),
|
|
81
|
+
// so the platform context fills `provider: "vellum"` rather than a mode.
|
|
80
82
|
const MANAGED_SERVICES = [
|
|
81
|
-
"image-generation",
|
|
82
83
|
"google-oauth",
|
|
83
84
|
"outlook-oauth",
|
|
84
85
|
"linear-oauth",
|
|
@@ -101,8 +102,9 @@ const SCHEMA_MANAGED_DEFAULT_SERVICES = [
|
|
|
101
102
|
] as const;
|
|
102
103
|
|
|
103
104
|
// web-search is absent from both lists: it carries no mode at all.
|
|
105
|
+
// image-generation and web-search are absent from both lists: they carry
|
|
106
|
+
// no mode at all.
|
|
104
107
|
const SCHEMA_YOUR_OWN_DEFAULT_SERVICES = [
|
|
105
|
-
"image-generation",
|
|
106
108
|
"outlook-oauth",
|
|
107
109
|
"linear-oauth",
|
|
108
110
|
"github-oauth",
|
|
@@ -132,7 +134,7 @@ describe("platform-managed config defaults", () => {
|
|
|
132
134
|
}
|
|
133
135
|
});
|
|
134
136
|
|
|
135
|
-
test("IS_PLATFORM=true, no config file → all
|
|
137
|
+
test("IS_PLATFORM=true, no config file → all 6 managed service modes written as 'managed', image-generation provider written as 'vellum'", () => {
|
|
136
138
|
process.env.IS_PLATFORM = "true";
|
|
137
139
|
|
|
138
140
|
loadConfig();
|
|
@@ -147,6 +149,15 @@ describe("platform-managed config defaults", () => {
|
|
|
147
149
|
expect((services["web-search"] as { provider?: string })?.provider).toBe(
|
|
148
150
|
"inference-provider-native",
|
|
149
151
|
);
|
|
152
|
+
// image-generation's managed axis is its provider: the platform context
|
|
153
|
+
// fills "vellum" and never injects a managed mode (the persisted mode is
|
|
154
|
+
// the schema default).
|
|
155
|
+
const imageGen = services["image-generation"] as {
|
|
156
|
+
provider?: string;
|
|
157
|
+
mode?: string;
|
|
158
|
+
};
|
|
159
|
+
expect(imageGen?.provider).toBe("vellum");
|
|
160
|
+
expect(imageGen?.mode).not.toBe("managed");
|
|
150
161
|
});
|
|
151
162
|
|
|
152
163
|
test("IS_PLATFORM=false, no config file → service modes follow schema defaults (your-own except google/notion-oauth which are managed)", () => {
|
|
@@ -204,13 +215,16 @@ describe("platform-managed config defaults", () => {
|
|
|
204
215
|
|
|
205
216
|
const written = readConfig() as { services?: Record<string, unknown> };
|
|
206
217
|
expect(written.services).toBeDefined();
|
|
207
|
-
// The
|
|
218
|
+
// The raw value must be preserved — backfill path, not fresh-write path.
|
|
219
|
+
// (Migration 134 rewrites this legacy shape at daemon startup; the loader
|
|
220
|
+
// itself must simply leave it alone.)
|
|
208
221
|
expect(
|
|
209
222
|
(written.services!["image-generation"] as { mode?: string })?.mode,
|
|
210
223
|
).toBe("your-own");
|
|
211
|
-
//
|
|
212
|
-
//
|
|
213
|
-
expect(config.services["image-generation"]
|
|
224
|
+
// The parsed config strips the legacy key and carries the filled
|
|
225
|
+
// provider; no mode survives the schema.
|
|
226
|
+
expect(config.services["image-generation"]).not.toHaveProperty("mode");
|
|
227
|
+
expect(config.services["image-generation"].provider).toBe("vellum");
|
|
214
228
|
});
|
|
215
229
|
|
|
216
230
|
test("IS_PLATFORM=true, config file with explicit notion-oauth mode='your-own' → preserved (schema default is 'managed')", () => {
|
|
@@ -279,6 +293,8 @@ describe("platform-managed config defaults", () => {
|
|
|
279
293
|
.mode,
|
|
280
294
|
).toBe("managed");
|
|
281
295
|
}
|
|
296
|
+
// ...and for image-generation's provider, whose fill is "vellum".
|
|
297
|
+
expect(config.services["image-generation"].provider).toBe("vellum");
|
|
282
298
|
|
|
283
299
|
// The on-disk file is NOT modified by the fill pass — disk reflects only
|
|
284
300
|
// what was already there. Existing-file branch never re-writes config.json.
|
|
@@ -286,15 +302,13 @@ describe("platform-managed config defaults", () => {
|
|
|
286
302
|
expect(onDisk["services"]).toBeUndefined();
|
|
287
303
|
});
|
|
288
304
|
|
|
289
|
-
test("IS_PLATFORM=true, config file exists with
|
|
305
|
+
test("IS_PLATFORM=true, config file exists with an explicit image-generation provider → provider wins over the vellum fill", () => {
|
|
290
306
|
process.env.IS_PLATFORM = "true";
|
|
291
307
|
|
|
292
|
-
// User has an image-generation provider
|
|
293
|
-
//
|
|
294
|
-
//
|
|
295
|
-
//
|
|
296
|
-
// migration 039 — image-generation still carries them, so it's the
|
|
297
|
-
// right schema to exercise the partial-subtree case.)
|
|
308
|
+
// User has an explicit BYOK image-generation provider on disk. The fill
|
|
309
|
+
// pass targets exactly that leaf (`provider: "vellum"`), so the explicit
|
|
310
|
+
// value must win and no mode is injected — the effective mode is the
|
|
311
|
+
// schema default.
|
|
298
312
|
writeFileSync(
|
|
299
313
|
CONFIG_PATH,
|
|
300
314
|
JSON.stringify(
|
|
@@ -313,11 +327,11 @@ describe("platform-managed config defaults", () => {
|
|
|
313
327
|
const imageGen = (
|
|
314
328
|
config.services as unknown as Record<
|
|
315
329
|
string,
|
|
316
|
-
{ mode
|
|
330
|
+
{ mode?: string; provider?: string }
|
|
317
331
|
>
|
|
318
332
|
)["image-generation"]!;
|
|
319
|
-
expect(imageGen.mode).toBe("managed");
|
|
320
333
|
expect(imageGen.provider).toBe("openai");
|
|
334
|
+
expect(imageGen).not.toHaveProperty("mode");
|
|
321
335
|
});
|
|
322
336
|
|
|
323
337
|
test("IS_PLATFORM=false, config file exists without services key → in-memory config keeps schema defaults (your-own except google/notion-oauth which are managed)", () => {
|
|
@@ -404,19 +418,27 @@ describe("GET /v1/config handler — context-default fill on raw response", () =
|
|
|
404
418
|
string,
|
|
405
419
|
unknown
|
|
406
420
|
>;
|
|
407
|
-
const services = result["services"] as Record<
|
|
421
|
+
const services = result["services"] as Record<
|
|
422
|
+
string,
|
|
423
|
+
{ mode?: string; provider?: string }
|
|
424
|
+
>;
|
|
408
425
|
expect(services).toBeDefined();
|
|
409
426
|
for (const svc of MANAGED_SERVICES) {
|
|
410
427
|
expect(services[svc]!.mode).toBe("managed");
|
|
411
428
|
}
|
|
429
|
+
// image-generation is filled by provider, not mode.
|
|
430
|
+
expect(services["image-generation"]!.provider).toBe("vellum");
|
|
431
|
+
expect(services["image-generation"]!.mode).toBeUndefined();
|
|
412
432
|
});
|
|
413
433
|
|
|
414
434
|
test("IS_PLATFORM=true, raw config has explicit services.image-generation.mode='your-own' → preserved", () => {
|
|
415
435
|
process.env.IS_PLATFORM = "true";
|
|
416
436
|
|
|
417
|
-
//
|
|
418
|
-
//
|
|
419
|
-
//
|
|
437
|
+
// A legacy raw shape: mode with no provider leaf. Migration 134 rewrites
|
|
438
|
+
// it (pinning provider gemini) before any real request reaches this
|
|
439
|
+
// function, so the fill's only obligation here is to be non-destructive:
|
|
440
|
+
// existing keys pass through untouched, absent leaves get the platform
|
|
441
|
+
// default.
|
|
420
442
|
const raw: Record<string, unknown> = {
|
|
421
443
|
services: {
|
|
422
444
|
"image-generation": { mode: "your-own" },
|
|
@@ -427,8 +449,12 @@ describe("GET /v1/config handler — context-default fill on raw response", () =
|
|
|
427
449
|
string,
|
|
428
450
|
unknown
|
|
429
451
|
>;
|
|
430
|
-
const services = result["services"] as Record<
|
|
452
|
+
const services = result["services"] as Record<
|
|
453
|
+
string,
|
|
454
|
+
{ mode?: string; provider?: string }
|
|
455
|
+
>;
|
|
431
456
|
expect(services["image-generation"]!.mode).toBe("your-own");
|
|
457
|
+
expect(services["image-generation"]!.provider).toBe("vellum");
|
|
432
458
|
// web-search is not context-filled: a filled `mode` would override BYOK
|
|
433
459
|
// configs on every load.
|
|
434
460
|
expect(services["web-search"]).toBeUndefined();
|
|
@@ -455,12 +481,12 @@ describe("GET /v1/config handler — context-default fill on raw response", () =
|
|
|
455
481
|
expect(result["services"]).toBeUndefined();
|
|
456
482
|
});
|
|
457
483
|
|
|
458
|
-
test("IS_PLATFORM=true, raw config has
|
|
484
|
+
test("IS_PLATFORM=true, raw config has an explicit image-generation provider → preserved, no mode injected", () => {
|
|
459
485
|
process.env.IS_PLATFORM = "true";
|
|
460
486
|
|
|
461
|
-
// User set image-generation.provider
|
|
462
|
-
//
|
|
463
|
-
//
|
|
487
|
+
// User set image-generation.provider explicitly. The fill targets that
|
|
488
|
+
// same leaf (`provider: "vellum"`), so the explicit value wins and no
|
|
489
|
+
// mode is injected.
|
|
464
490
|
const raw: Record<string, unknown> = {
|
|
465
491
|
services: {
|
|
466
492
|
"image-generation": { provider: "openai" },
|
|
@@ -473,10 +499,10 @@ describe("GET /v1/config handler — context-default fill on raw response", () =
|
|
|
473
499
|
>;
|
|
474
500
|
const services = result["services"] as Record<
|
|
475
501
|
string,
|
|
476
|
-
{ mode
|
|
502
|
+
{ mode?: string; provider?: string }
|
|
477
503
|
>;
|
|
478
|
-
expect(services["image-generation"]!.mode).toBe("managed");
|
|
479
504
|
expect(services["image-generation"]!.provider).toBe("openai");
|
|
505
|
+
expect(services["image-generation"]!.mode).toBeUndefined();
|
|
480
506
|
// services.inference.mode is synthesized as a legacy wire-only field for
|
|
481
507
|
// older macOS clients during the rollout window (Phase 1.2 schema removal
|
|
482
508
|
// landed before the macOS Providers UI ships).
|
|
@@ -107,3 +107,23 @@ describe("setImageGenModel — provider derived from model prefix", () => {
|
|
|
107
107
|
expect(imageGen?.provider).toBe("openai");
|
|
108
108
|
});
|
|
109
109
|
});
|
|
110
|
+
|
|
111
|
+
describe("setImageGenModel with provider vellum", () => {
|
|
112
|
+
test("a model change leaves provider vellum untouched", () => {
|
|
113
|
+
writeConfig({
|
|
114
|
+
services: {
|
|
115
|
+
"image-generation": { provider: "vellum", model: "gpt-image-2" },
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
setImageGenModel("gemini-3-pro-image-preview", makeCtx());
|
|
120
|
+
|
|
121
|
+
const raw = readConfig() as {
|
|
122
|
+
services: { "image-generation": { provider: string; model: string } };
|
|
123
|
+
};
|
|
124
|
+
expect(raw.services["image-generation"].model).toBe(
|
|
125
|
+
"gemini-3-pro-image-preview",
|
|
126
|
+
);
|
|
127
|
+
expect(raw.services["image-generation"].provider).toBe("vellum");
|
|
128
|
+
});
|
|
129
|
+
});
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the `memory.substrate.*` config namespace and its resolver.
|
|
3
|
+
*
|
|
4
|
+
* The substrate schema mirrors the substrate-consumed subset of `memory.v2.*`
|
|
5
|
+
* with every field optional and no defaults; `resolveSubstrateTuning` is the
|
|
6
|
+
* single choke point that resolves each tunable from `memory.substrate` with
|
|
7
|
+
* fallback to the historical `memory.v2` key. Coverage:
|
|
8
|
+
*
|
|
9
|
+
* - Fallback resolution: substrate unset → v2 value (defaults and explicit
|
|
10
|
+
* values); substrate set → wins; `spread_k`/`spread_hops` map onto
|
|
11
|
+
* `memory.v2.k`/`memory.v2.hops`; explicit `null` on a nullable substrate
|
|
12
|
+
* key wins over a non-null v2 value.
|
|
13
|
+
* - Namespace parsing (LUM-2758 guard): configs carrying only old keys,
|
|
14
|
+
* only new keys, or both parse cleanly with no refinement misfires, both
|
|
15
|
+
* through the memory slice schema and the full assistant schema.
|
|
16
|
+
* - The substrate hybrid-weight refinement fires only when BOTH weights are
|
|
17
|
+
* set and mis-summed.
|
|
18
|
+
* - The parent memory schema validates the RESOLVED weight pair: a single
|
|
19
|
+
* substrate weight is paired with its `memory.v2` twin (schema default
|
|
20
|
+
* applied), and the effective sum must respect the sum-to-one invariant.
|
|
21
|
+
*/
|
|
22
|
+
import { describe, expect, test } from "bun:test";
|
|
23
|
+
|
|
24
|
+
import { AssistantConfigSchema } from "../config/schema.js";
|
|
25
|
+
import { MemoryConfigSchema } from "../config/schemas/memory.js";
|
|
26
|
+
import { MemorySubstrateConfigSchema } from "../config/schemas/memory-substrate.js";
|
|
27
|
+
import { resolveSubstrateTuning } from "../plugins/defaults/memory/substrate/tuning.js";
|
|
28
|
+
|
|
29
|
+
describe("memory.substrate schema", () => {
|
|
30
|
+
test("empty object parses and every field stays unset", () => {
|
|
31
|
+
const parsed = MemorySubstrateConfigSchema.parse({});
|
|
32
|
+
expect(parsed).toEqual({});
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
test("memory slice parse mounts substrate as an empty object by default", () => {
|
|
36
|
+
const memory = MemoryConfigSchema.parse({});
|
|
37
|
+
expect(memory.substrate).toEqual({});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test("config with only historical memory.v2 keys parses cleanly", () => {
|
|
41
|
+
const memory = MemoryConfigSchema.parse({
|
|
42
|
+
v2: { consolidation_interval_hours: 3, bm25_k1: 1.5 },
|
|
43
|
+
});
|
|
44
|
+
expect(memory.v2.consolidation_interval_hours).toBe(3);
|
|
45
|
+
expect(memory.substrate).toEqual({});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test("config with only memory.substrate keys parses cleanly", () => {
|
|
49
|
+
const memory = MemoryConfigSchema.parse({
|
|
50
|
+
substrate: { consolidation_interval_hours: 3, spread_k: 0.4 },
|
|
51
|
+
});
|
|
52
|
+
expect(memory.substrate.consolidation_interval_hours).toBe(3);
|
|
53
|
+
expect(memory.substrate.spread_k).toBe(0.4);
|
|
54
|
+
// v2 defaults are untouched by substrate keys.
|
|
55
|
+
expect(memory.v2.consolidation_interval_hours).toBe(8);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("config with both namespaces parses cleanly", () => {
|
|
59
|
+
const memory = MemoryConfigSchema.parse({
|
|
60
|
+
v2: { consolidation_interval_hours: 3 },
|
|
61
|
+
substrate: { consolidation_interval_hours: 5 },
|
|
62
|
+
});
|
|
63
|
+
expect(memory.v2.consolidation_interval_hours).toBe(3);
|
|
64
|
+
expect(memory.substrate.consolidation_interval_hours).toBe(5);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
test("full assistant config parse accepts either, both, or neither namespace", () => {
|
|
68
|
+
for (const memory of [
|
|
69
|
+
{},
|
|
70
|
+
{ v2: { max_page_chars: 4000 } },
|
|
71
|
+
{ substrate: { max_page_chars: 4000 } },
|
|
72
|
+
{ v2: { max_page_chars: 4000 }, substrate: { max_page_chars: 6000 } },
|
|
73
|
+
]) {
|
|
74
|
+
const result = AssistantConfigSchema.safeParse({ memory });
|
|
75
|
+
expect(result.success).toBe(true);
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test("hybrid-weight refinement fires only when both weights are set and mis-summed", () => {
|
|
80
|
+
// Only one weight set — no refinement at the substrate schema level; the
|
|
81
|
+
// parent memory schema validates the resolved pair against the v2 twin.
|
|
82
|
+
expect(
|
|
83
|
+
MemorySubstrateConfigSchema.safeParse({ dense_weight: 0.5 }).success,
|
|
84
|
+
).toBe(true);
|
|
85
|
+
expect(
|
|
86
|
+
MemorySubstrateConfigSchema.safeParse({ sparse_weight: 0.5 }).success,
|
|
87
|
+
).toBe(true);
|
|
88
|
+
|
|
89
|
+
// Both set and summing to 1.0 — valid.
|
|
90
|
+
expect(
|
|
91
|
+
MemorySubstrateConfigSchema.safeParse({
|
|
92
|
+
dense_weight: 0.7,
|
|
93
|
+
sparse_weight: 0.3,
|
|
94
|
+
}).success,
|
|
95
|
+
).toBe(true);
|
|
96
|
+
|
|
97
|
+
// Both set and mis-summed — one issue per contributing field.
|
|
98
|
+
const bad = MemorySubstrateConfigSchema.safeParse({
|
|
99
|
+
dense_weight: 0.7,
|
|
100
|
+
sparse_weight: 0.7,
|
|
101
|
+
});
|
|
102
|
+
expect(bad.success).toBe(false);
|
|
103
|
+
if (!bad.success) {
|
|
104
|
+
const paths = bad.error.issues.map((issue) => issue.path.join("."));
|
|
105
|
+
expect(paths.sort()).toEqual(["dense_weight", "sparse_weight"]);
|
|
106
|
+
expect(bad.error.issues[0].message).toContain(
|
|
107
|
+
"memory.substrate hybrid weights",
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
describe("resolved hybrid-weight invariant (memory schema level)", () => {
|
|
113
|
+
// Parses `memory` through both entry points that must agree: the memory
|
|
114
|
+
// slice schema and the full assistant config schema.
|
|
115
|
+
const parseBothWays = (memory: unknown) => ({
|
|
116
|
+
slice: MemoryConfigSchema.safeParse(memory),
|
|
117
|
+
full: AssistantConfigSchema.safeParse({ memory }),
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test("a lone substrate dense_weight that breaks the effective sum is rejected", () => {
|
|
121
|
+
// v2 sparse_weight defaults to 0.15 → effective sum 1.05.
|
|
122
|
+
const { slice, full } = parseBothWays({
|
|
123
|
+
substrate: { dense_weight: 0.9 },
|
|
124
|
+
});
|
|
125
|
+
for (const result of [slice, full]) {
|
|
126
|
+
expect(result.success).toBe(false);
|
|
127
|
+
if (!result.success) {
|
|
128
|
+
const issue = result.error.issues.find((candidate) =>
|
|
129
|
+
candidate.message.includes(
|
|
130
|
+
"memory hybrid weights must sum to 1.0 after memory.substrate → memory.v2 fallback",
|
|
131
|
+
),
|
|
132
|
+
);
|
|
133
|
+
expect(issue).toBeDefined();
|
|
134
|
+
expect(issue?.message).toContain("0.9000");
|
|
135
|
+
expect(issue?.message).toContain("0.1500");
|
|
136
|
+
expect(issue?.message).toContain("1.0500");
|
|
137
|
+
expect(issue?.path.slice(-2)).toEqual(["substrate", "dense_weight"]);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
test("a lone substrate sparse_weight that breaks the effective sum is rejected", () => {
|
|
143
|
+
// v2 dense_weight defaults to 0.85 → effective sum 1.35.
|
|
144
|
+
const { slice, full } = parseBothWays({
|
|
145
|
+
substrate: { sparse_weight: 0.5 },
|
|
146
|
+
});
|
|
147
|
+
for (const result of [slice, full]) {
|
|
148
|
+
expect(result.success).toBe(false);
|
|
149
|
+
if (!result.success) {
|
|
150
|
+
const issue = result.error.issues.find((candidate) =>
|
|
151
|
+
candidate.message.includes(
|
|
152
|
+
"memory hybrid weights must sum to 1.0 after memory.substrate → memory.v2 fallback",
|
|
153
|
+
),
|
|
154
|
+
);
|
|
155
|
+
expect(issue).toBeDefined();
|
|
156
|
+
expect(issue?.path.slice(-2)).toEqual(["substrate", "sparse_weight"]);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
test("a complete substrate pair summing to 1.0 is accepted", () => {
|
|
162
|
+
const { slice, full } = parseBothWays({
|
|
163
|
+
substrate: { dense_weight: 0.9, sparse_weight: 0.1 },
|
|
164
|
+
});
|
|
165
|
+
expect(slice.success).toBe(true);
|
|
166
|
+
expect(full.success).toBe(true);
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
test("a lone substrate weight matching the v2 default pair is accepted", () => {
|
|
170
|
+
// 0.85 pairs with the v2 sparse_weight default 0.15 → effective sum 1.0.
|
|
171
|
+
const { slice, full } = parseBothWays({
|
|
172
|
+
substrate: { dense_weight: 0.85 },
|
|
173
|
+
});
|
|
174
|
+
expect(slice.success).toBe(true);
|
|
175
|
+
expect(full.success).toBe(true);
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
test("a lone substrate weight pairing with an explicit v2 twin is accepted", () => {
|
|
179
|
+
const { slice, full } = parseBothWays({
|
|
180
|
+
v2: { dense_weight: 0.7, sparse_weight: 0.3 },
|
|
181
|
+
substrate: { sparse_weight: 0.3 },
|
|
182
|
+
});
|
|
183
|
+
expect(slice.success).toBe(true);
|
|
184
|
+
expect(full.success).toBe(true);
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
test("a mis-summed complete substrate pair only fires the substrate refinement", () => {
|
|
188
|
+
// Both substrate weights set → the parent check skips; only the
|
|
189
|
+
// substrate schema's own refinement reports, so the two never
|
|
190
|
+
// contradict each other.
|
|
191
|
+
const { slice, full } = parseBothWays({
|
|
192
|
+
substrate: { dense_weight: 0.7, sparse_weight: 0.7 },
|
|
193
|
+
});
|
|
194
|
+
for (const result of [slice, full]) {
|
|
195
|
+
expect(result.success).toBe(false);
|
|
196
|
+
if (!result.success) {
|
|
197
|
+
const messages = result.error.issues.map((issue) => issue.message);
|
|
198
|
+
expect(
|
|
199
|
+
messages.some((message) =>
|
|
200
|
+
message.includes("memory.substrate hybrid weights"),
|
|
201
|
+
),
|
|
202
|
+
).toBe(true);
|
|
203
|
+
expect(
|
|
204
|
+
messages.some((message) =>
|
|
205
|
+
message.includes(
|
|
206
|
+
"memory hybrid weights must sum to 1.0 after memory.substrate → memory.v2 fallback",
|
|
207
|
+
),
|
|
208
|
+
),
|
|
209
|
+
).toBe(false);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
describe("resolveSubstrateTuning", () => {
|
|
217
|
+
test("substrate unset resolves to the v2 schema defaults", () => {
|
|
218
|
+
const memory = MemoryConfigSchema.parse({});
|
|
219
|
+
const tuning = resolveSubstrateTuning(memory);
|
|
220
|
+
expect(tuning).toEqual({
|
|
221
|
+
sweep_enabled: false,
|
|
222
|
+
dense_weight: 0.85,
|
|
223
|
+
sparse_weight: 0.15,
|
|
224
|
+
min_sparse_spread: undefined,
|
|
225
|
+
full_sparse_spread: undefined,
|
|
226
|
+
bm25_k1: 1.2,
|
|
227
|
+
bm25_b: 0.4,
|
|
228
|
+
consolidation_interval_hours: 8,
|
|
229
|
+
consolidation_max_buffer_lines: 100,
|
|
230
|
+
consolidation_max_entries_per_run: 150,
|
|
231
|
+
max_page_chars: 5000,
|
|
232
|
+
consolidation_prompt_path: null,
|
|
233
|
+
spread_k: 0.5,
|
|
234
|
+
spread_hops: 2,
|
|
235
|
+
ann_candidate_limit: null,
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
test("substrate unset resolves to explicitly-set v2 values", () => {
|
|
240
|
+
const memory = MemoryConfigSchema.parse({
|
|
241
|
+
v2: {
|
|
242
|
+
sweep_enabled: true,
|
|
243
|
+
consolidation_interval_hours: 3,
|
|
244
|
+
consolidation_max_buffer_lines: null,
|
|
245
|
+
bm25_b: 0.9,
|
|
246
|
+
},
|
|
247
|
+
});
|
|
248
|
+
const tuning = resolveSubstrateTuning(memory);
|
|
249
|
+
expect(tuning.sweep_enabled).toBe(true);
|
|
250
|
+
expect(tuning.consolidation_interval_hours).toBe(3);
|
|
251
|
+
expect(tuning.consolidation_max_buffer_lines).toBeNull();
|
|
252
|
+
expect(tuning.bm25_b).toBe(0.9);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
test("a set substrate key wins over the v2 twin", () => {
|
|
256
|
+
const memory = MemoryConfigSchema.parse({
|
|
257
|
+
v2: {
|
|
258
|
+
consolidation_interval_hours: 3,
|
|
259
|
+
max_page_chars: 4000,
|
|
260
|
+
sweep_enabled: true,
|
|
261
|
+
},
|
|
262
|
+
substrate: {
|
|
263
|
+
consolidation_interval_hours: 12,
|
|
264
|
+
max_page_chars: 9000,
|
|
265
|
+
sweep_enabled: false,
|
|
266
|
+
},
|
|
267
|
+
});
|
|
268
|
+
const tuning = resolveSubstrateTuning(memory);
|
|
269
|
+
expect(tuning.consolidation_interval_hours).toBe(12);
|
|
270
|
+
expect(tuning.max_page_chars).toBe(9000);
|
|
271
|
+
expect(tuning.sweep_enabled).toBe(false);
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
test("spread_k / spread_hops map onto memory.v2.k / memory.v2.hops", () => {
|
|
275
|
+
const fallback = resolveSubstrateTuning(
|
|
276
|
+
MemoryConfigSchema.parse({ v2: { k: 0.7, hops: 4 } }),
|
|
277
|
+
);
|
|
278
|
+
expect(fallback.spread_k).toBe(0.7);
|
|
279
|
+
expect(fallback.spread_hops).toBe(4);
|
|
280
|
+
|
|
281
|
+
const overridden = resolveSubstrateTuning(
|
|
282
|
+
MemoryConfigSchema.parse({
|
|
283
|
+
v2: { k: 0.7, hops: 4 },
|
|
284
|
+
substrate: { spread_k: 0.2, spread_hops: 1 },
|
|
285
|
+
}),
|
|
286
|
+
);
|
|
287
|
+
expect(overridden.spread_k).toBe(0.2);
|
|
288
|
+
expect(overridden.spread_hops).toBe(1);
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
test("an explicit substrate null wins over a non-null v2 value", () => {
|
|
292
|
+
const memory = MemoryConfigSchema.parse({
|
|
293
|
+
v2: {
|
|
294
|
+
ann_candidate_limit: 500,
|
|
295
|
+
consolidation_max_entries_per_run: 50,
|
|
296
|
+
},
|
|
297
|
+
substrate: {
|
|
298
|
+
ann_candidate_limit: null,
|
|
299
|
+
consolidation_max_entries_per_run: null,
|
|
300
|
+
},
|
|
301
|
+
});
|
|
302
|
+
const tuning = resolveSubstrateTuning(memory);
|
|
303
|
+
expect(tuning.ann_candidate_limit).toBeNull();
|
|
304
|
+
expect(tuning.consolidation_max_entries_per_run).toBeNull();
|
|
305
|
+
});
|
|
306
|
+
});
|
|
@@ -68,7 +68,7 @@ describe("AssistantConfigSchema", () => {
|
|
|
68
68
|
expect(result.services["image-generation"].model).toBe(
|
|
69
69
|
"gemini-3.1-flash-image-preview",
|
|
70
70
|
);
|
|
71
|
-
expect(result.services["image-generation"]
|
|
71
|
+
expect(result.services["image-generation"]).not.toHaveProperty("mode");
|
|
72
72
|
expect(result.services["web-search"].provider).toBe(
|
|
73
73
|
"inference-provider-native",
|
|
74
74
|
);
|
|
@@ -99,6 +99,17 @@ describe("AssistantConfigSchema", () => {
|
|
|
99
99
|
expect(result.auditLog).toEqual({ retentionDays: 0 });
|
|
100
100
|
});
|
|
101
101
|
|
|
102
|
+
test("accepts vellum as an image generation provider", () => {
|
|
103
|
+
const result = AssistantConfigSchema.parse({
|
|
104
|
+
services: {
|
|
105
|
+
"image-generation": { provider: "vellum", model: "gpt-image-2" },
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
expect(result.services["image-generation"].provider).toBe("vellum");
|
|
110
|
+
expect(result.services["image-generation"].model).toBe("gpt-image-2");
|
|
111
|
+
});
|
|
112
|
+
|
|
102
113
|
test("accepts Tavily as a web search provider", () => {
|
|
103
114
|
const result = AssistantConfigSchema.parse({
|
|
104
115
|
services: {
|
|
@@ -928,11 +939,12 @@ describe("AssistantConfigSchema", () => {
|
|
|
928
939
|
endpointMaxExtensions: 2,
|
|
929
940
|
ackFirstDeltaTimeoutMs: 2500,
|
|
930
941
|
ackGenerationTimeoutMs: 600,
|
|
931
|
-
llmAckText: false,
|
|
932
942
|
progress: {
|
|
933
943
|
enabled: true,
|
|
934
944
|
opsThreshold: 3,
|
|
935
945
|
idleIntervalMs: 5000,
|
|
946
|
+
maxSilenceMs: 35000,
|
|
947
|
+
longOpMs: 15000,
|
|
936
948
|
minGapMs: 6000,
|
|
937
949
|
generationTimeoutMs: 1500,
|
|
938
950
|
},
|
|
@@ -174,8 +174,10 @@ describe("config set - platform connection guard for service mode paths", () =>
|
|
|
174
174
|
mockIpcResult = { ok: true, result: { ok: true } };
|
|
175
175
|
});
|
|
176
176
|
|
|
177
|
-
test("config set services.image-generation.mode
|
|
178
|
-
|
|
177
|
+
test("config set services.image-generation.mode - rejected with provider guidance, no IPC write emitted", async () => {
|
|
178
|
+
// The image-generation schema has no mode field; a raw write would be
|
|
179
|
+
// stripped at parse while the CLI reported success.
|
|
180
|
+
const { exitCode, stdout } = await runCli([
|
|
179
181
|
"node",
|
|
180
182
|
"assistant",
|
|
181
183
|
"--json",
|
|
@@ -185,16 +187,13 @@ describe("config set - platform connection guard for service mode paths", () =>
|
|
|
185
187
|
"your-own",
|
|
186
188
|
]);
|
|
187
189
|
|
|
188
|
-
expect(exitCode).toBe(
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
expect(
|
|
192
|
-
expect(
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
value: "your-own",
|
|
196
|
-
},
|
|
197
|
-
});
|
|
190
|
+
expect(exitCode).toBe(1);
|
|
191
|
+
const parsed = JSON.parse(stdout);
|
|
192
|
+
expect(parsed.ok).toBe(false);
|
|
193
|
+
expect(parsed.error).toContain("services.image-generation.provider vellum");
|
|
194
|
+
expect(mockIpcCalls.filter((c) => c.method === "config_set")).toHaveLength(
|
|
195
|
+
0,
|
|
196
|
+
);
|
|
198
197
|
});
|
|
199
198
|
|
|
200
199
|
test("config set calls.enabled true - succeeds without platform connection and parses to boolean", async () => {
|