@vellumai/assistant 0.10.12 → 0.11.0-staging.1
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 +246 -10
- 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__/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-history-web-search.test.ts +1 -1
- package/src/__tests__/conversation-key-store-disk-view.test.ts +5 -5
- 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__/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__/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 +6 -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 +583 -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-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 +399 -0
- 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/approvals/AGENTS.md +2 -0
- package/src/approvals/guardian-request-resolvers.ts +118 -24
- package/src/calls/__tests__/voice-control-protocol.test.ts +57 -0
- package/src/calls/__tests__/voice-session-bridge.test.ts +158 -4
- 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 +156 -58
- 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/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/image-studio/tools/media-generate-image.ts +13 -7
- package/src/config/feature-flag-cache.ts +6 -16
- package/src/config/feature-flag-registry.json +14 -30
- 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-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 +4 -4
- 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 +13 -13
- 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-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 +218 -422
- 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 +650 -333
- 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 +85 -9
- package/src/permissions/checker.ts +17 -22
- 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 +236 -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/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/schema/infrastructure.ts +11 -0
- package/src/persistence/steps.ts +7 -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/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/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/upgrade-broadcast-routes.ts +4 -5
- 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__/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/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/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/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/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
|
@@ -27,7 +27,9 @@ mock.module("../../daemon/conversation-registry.js", () => ({
|
|
|
27
27
|
let lastStartArgs: Record<string, unknown> | null = null;
|
|
28
28
|
let startThrows: Error | null = null;
|
|
29
29
|
const startMock = mock((opts: Record<string, unknown>) => {
|
|
30
|
-
if (startThrows)
|
|
30
|
+
if (startThrows) {
|
|
31
|
+
throw startThrows;
|
|
32
|
+
}
|
|
31
33
|
lastStartArgs = opts;
|
|
32
34
|
return { runId: "run-123" };
|
|
33
35
|
});
|
|
@@ -36,7 +38,9 @@ const abortMock = mock(() => {});
|
|
|
36
38
|
const listMock = mock(() => [] as unknown[]);
|
|
37
39
|
let resumeThrows: Error | null = null;
|
|
38
40
|
const resumeMock = mock((runId: string) => {
|
|
39
|
-
if (resumeThrows)
|
|
41
|
+
if (resumeThrows) {
|
|
42
|
+
throw resumeThrows;
|
|
43
|
+
}
|
|
40
44
|
return { runId };
|
|
41
45
|
});
|
|
42
46
|
|
|
@@ -421,3 +425,51 @@ describe("manage_workflows", () => {
|
|
|
421
425
|
expect(abortMock).toHaveBeenCalledWith("mine");
|
|
422
426
|
});
|
|
423
427
|
});
|
|
428
|
+
|
|
429
|
+
// ── model-input schema validation (LUM-2855) ────────────────────────
|
|
430
|
+
|
|
431
|
+
describe("workflow tools — model-input schema validation", () => {
|
|
432
|
+
test("run_workflow rejects a non-string script", async () => {
|
|
433
|
+
const result = await executeRunWorkflow({ script: 42 }, makeContext());
|
|
434
|
+
expect(result.isError).toBe(true);
|
|
435
|
+
expect(result.content).toContain('Invalid input for tool "run_workflow"');
|
|
436
|
+
expect(result.content).toContain("script");
|
|
437
|
+
expect(startMock).not.toHaveBeenCalled();
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
test("run_workflow treats explicit null script/name as omitted (bespoke exactly-one error)", async () => {
|
|
441
|
+
const result = await executeRunWorkflow(
|
|
442
|
+
{ script: null, name: null },
|
|
443
|
+
makeContext(),
|
|
444
|
+
);
|
|
445
|
+
expect(result.isError).toBe(true);
|
|
446
|
+
expect(result.content).toContain("exactly one");
|
|
447
|
+
});
|
|
448
|
+
|
|
449
|
+
test("run_workflow passes args through unvalidated (workflow runtime accepts any JSON)", async () => {
|
|
450
|
+
const result = await executeRunWorkflow(
|
|
451
|
+
{ script: "export const meta = {}", args: ["positional"] },
|
|
452
|
+
makeContext(),
|
|
453
|
+
);
|
|
454
|
+
expect(result.isError).toBe(false);
|
|
455
|
+
expect(lastStartArgs?.args).toEqual(["positional"]);
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
test("manage_workflows rejects a non-string run_id", async () => {
|
|
459
|
+
const result = await executeManageWorkflows(
|
|
460
|
+
{ action: "status", run_id: 42 },
|
|
461
|
+
makeContext(),
|
|
462
|
+
);
|
|
463
|
+
expect(result.isError).toBe(true);
|
|
464
|
+
expect(result.content).toContain(
|
|
465
|
+
'Invalid input for tool "manage_workflows"',
|
|
466
|
+
);
|
|
467
|
+
expect(result.content).toContain("run_id");
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
test("manage_workflows keeps the bespoke unknown-action error", async () => {
|
|
471
|
+
const result = await executeManageWorkflows({ action: 42 }, makeContext());
|
|
472
|
+
expect(result.isError).toBe(true);
|
|
473
|
+
expect(result.content).toContain("Unknown action");
|
|
474
|
+
});
|
|
475
|
+
});
|
|
@@ -15,13 +15,37 @@
|
|
|
15
15
|
* of truth the model reads when generating the `script`.
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
|
+
import { z } from "zod";
|
|
19
|
+
|
|
18
20
|
import { findConversation } from "../../daemon/conversation-registry.js";
|
|
19
21
|
import { FALLBACK_TURN_TRUST } from "../../daemon/trust-context.js";
|
|
20
22
|
import type { TrustContext } from "../../daemon/trust-context-types.js";
|
|
21
23
|
import { CapabilityManifestSchema } from "../../workflows/capabilities.js";
|
|
22
24
|
import { getWorkflowRunManager } from "../../workflows/run-manager.js";
|
|
25
|
+
import {
|
|
26
|
+
invalidToolInputResult,
|
|
27
|
+
nullAsOmitted,
|
|
28
|
+
} from "../shared/zod-tool-schema.js";
|
|
23
29
|
import type { ToolContext, ToolExecutionResult } from "../types.js";
|
|
24
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Model-input schema, `safeParse`d at the top of {@link executeRunWorkflow}.
|
|
33
|
+
* Same in-tool pattern and TOOLS.json drift guard as the other bundled-skill
|
|
34
|
+
* tools — see the schema block in `tools/document/document-tool.ts` for the
|
|
35
|
+
* framework.
|
|
36
|
+
*
|
|
37
|
+
* `args` (the workflow runtime accepts any JSON value) and `capabilities`
|
|
38
|
+
* (`CapabilityManifestSchema` is the single validation authority, and
|
|
39
|
+
* `executor.ts` reads it pre-execution for the requireFreshApproval
|
|
40
|
+
* promotion) are deliberately UNDECLARED — loose passthrough. The
|
|
41
|
+
* exactly-one-of script/name rule stays a bespoke check below.
|
|
42
|
+
*/
|
|
43
|
+
export const runWorkflowInputSchema = z.looseObject({
|
|
44
|
+
script: nullAsOmitted(z.string()),
|
|
45
|
+
name: nullAsOmitted(z.string()),
|
|
46
|
+
label: nullAsOmitted(z.string()),
|
|
47
|
+
});
|
|
48
|
+
|
|
25
49
|
/**
|
|
26
50
|
* Resolve the {@link TrustContext} to forward to the run's leaves. Prefer the
|
|
27
51
|
* originating conversation's per-turn snapshot (the same context the live turn
|
|
@@ -33,7 +57,9 @@ function resolveTrustContext(context: ToolContext): TrustContext {
|
|
|
33
57
|
const conversation = findConversation(context.conversationId);
|
|
34
58
|
const fromConversation =
|
|
35
59
|
conversation?.currentTurnTrustContext ?? conversation?.trustContext;
|
|
36
|
-
if (fromConversation)
|
|
60
|
+
if (fromConversation) {
|
|
61
|
+
return fromConversation;
|
|
62
|
+
}
|
|
37
63
|
return { ...FALLBACK_TURN_TRUST, trustClass: context.trustClass };
|
|
38
64
|
}
|
|
39
65
|
|
|
@@ -41,8 +67,11 @@ export async function executeRunWorkflow(
|
|
|
41
67
|
input: Record<string, unknown>,
|
|
42
68
|
context: ToolContext,
|
|
43
69
|
): Promise<ToolExecutionResult> {
|
|
44
|
-
const
|
|
45
|
-
|
|
70
|
+
const parsedInput = runWorkflowInputSchema.safeParse(input);
|
|
71
|
+
if (!parsedInput.success) {
|
|
72
|
+
return invalidToolInputResult("run_workflow", parsedInput.error);
|
|
73
|
+
}
|
|
74
|
+
const { script, name, label } = parsedInput.data;
|
|
46
75
|
|
|
47
76
|
// Exactly one of script/name is required.
|
|
48
77
|
if ((script == null) === (name == null)) {
|
|
@@ -54,7 +83,6 @@ export async function executeRunWorkflow(
|
|
|
54
83
|
}
|
|
55
84
|
|
|
56
85
|
const args = (input.args as Record<string, unknown> | undefined) ?? {};
|
|
57
|
-
const label = input.label as string | undefined;
|
|
58
86
|
const trustContext = resolveTrustContext(context);
|
|
59
87
|
|
|
60
88
|
try {
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { lstatSync, readlinkSync } from "node:fs";
|
|
2
|
+
import { dirname, resolve } from "node:path";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Follow a trailing symlink chain manually so a DANGLING link reports its
|
|
6
|
+
* destination. `realpathSync` throws on a link whose destination does not
|
|
7
|
+
* exist, which makes canonicalization fall back to the benign link path —
|
|
8
|
+
* but a write through the link creates the destination, so containment and
|
|
9
|
+
* security checks must see it. The bound sits above every supported
|
|
10
|
+
* platform's own traversal limit (Linux follows at most 40 links per
|
|
11
|
+
* resolution, macOS 32), so any chain this loop cannot exhaust is one the
|
|
12
|
+
* filesystem itself refuses to follow (ELOOP) — the eventual operation
|
|
13
|
+
* fails rather than writing through an unchecked destination.
|
|
14
|
+
*/
|
|
15
|
+
export function resolveTrailingLinkTarget(path: string): string {
|
|
16
|
+
let current = path;
|
|
17
|
+
for (let depth = 0; depth < 64; depth++) {
|
|
18
|
+
let linkTarget: string;
|
|
19
|
+
try {
|
|
20
|
+
if (!lstatSync(current).isSymbolicLink()) {
|
|
21
|
+
return current;
|
|
22
|
+
}
|
|
23
|
+
linkTarget = readlinkSync(current);
|
|
24
|
+
} catch {
|
|
25
|
+
return current;
|
|
26
|
+
}
|
|
27
|
+
current = resolve(dirname(current), linkTarget);
|
|
28
|
+
}
|
|
29
|
+
return current;
|
|
30
|
+
}
|
package/src/util/log-redact.ts
CHANGED
|
@@ -11,15 +11,19 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import { memoizePluginPatternDerivation } from "../security/plugin-secret-patterns.js";
|
|
14
|
-
import {
|
|
14
|
+
import { REDACTION_PREFIX_PATTERNS } from "../security/secret-patterns.js";
|
|
15
15
|
|
|
16
16
|
// ---------------------------------------------------------------------------
|
|
17
|
-
// Sensitive-value patterns (derived from shared
|
|
17
|
+
// Sensitive-value patterns (derived from shared REDACTION_PREFIX_PATTERNS)
|
|
18
18
|
// ---------------------------------------------------------------------------
|
|
19
19
|
|
|
20
20
|
const BEARER_RE = /Bearer [A-Za-z0-9._\-]+/g;
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
// This serializer redacts by replacing the matched span in place, so it uses
|
|
23
|
+
// the bounded whole-block private-key matcher (via REDACTION_PREFIX_PATTERNS):
|
|
24
|
+
// the match must cover header → body → footer or the key body would survive
|
|
25
|
+
// redaction. The body bound keeps it O(n) on large serialized strings.
|
|
26
|
+
const STATIC_API_KEY_PATTERNS: RegExp[] = REDACTION_PREFIX_PATTERNS.map(
|
|
23
27
|
(p) => new RegExp(p.regex.source, "g"),
|
|
24
28
|
);
|
|
25
29
|
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The single shape of `globalThis.vellumAssistant` — the per-process namespace
|
|
3
|
+
* that holds the assistant's process-global singletons.
|
|
4
|
+
*
|
|
5
|
+
* Several modules keep process-global state on `globalThis.vellumAssistant.*`
|
|
6
|
+
* (see the slots below). Each such slot is read/written by a production module
|
|
7
|
+
* AND, independently, by a test helper in `src/__tests__/` that must NOT import
|
|
8
|
+
* that production module (importing it would run its load-time side effects
|
|
9
|
+
* before the test preload establishes the per-process workspace override — the
|
|
10
|
+
* coupling behind the May 2026 DB-ghost incidents). This file is how both sides
|
|
11
|
+
* agree on the shape without a runtime import between them.
|
|
12
|
+
*
|
|
13
|
+
* It is an **ambient** declaration (no top-level `import`/`export`), so
|
|
14
|
+
* `VellumAssistantNamespace`, the slot types, and the `vellumAssistant` binding
|
|
15
|
+
* are global — every module and test helper refers to them by name with zero
|
|
16
|
+
* imports, and nothing here reaches into a `src/` module even at the type
|
|
17
|
+
* level. Referring to these types therefore never adds anything to any file's
|
|
18
|
+
* runtime import graph, so the test-machinery isolation invariant holds.
|
|
19
|
+
*
|
|
20
|
+
* Adding a slot: declare its value type here, add the optional property to
|
|
21
|
+
* `VellumAssistantNamespace`, and have the owning module + its test helper
|
|
22
|
+
* reference these globals instead of declaring their own copies.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/** Slot value: the encrypted credential store path override. Managed by `security/store-path-override.ts`. */
|
|
26
|
+
interface VellumStorePathOverride {
|
|
27
|
+
storePath: string | null;
|
|
28
|
+
storeKeyPath: string | null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/** Which assistant DB connection a singleton slot holds. */
|
|
32
|
+
type VellumDbSlotKey =
|
|
33
|
+
| "main"
|
|
34
|
+
| "main-readonly"
|
|
35
|
+
| "logs"
|
|
36
|
+
| "memory"
|
|
37
|
+
| "telemetry";
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Slot value: one lazily-opened DB connection and the closer that drops it.
|
|
41
|
+
* `db` is `unknown` so this shape never has to name a Drizzle type; callers in
|
|
42
|
+
* `persistence/db-connection.ts` narrow it via `getStoredDb<T>()`.
|
|
43
|
+
*/
|
|
44
|
+
interface VellumDbSlot {
|
|
45
|
+
db: unknown;
|
|
46
|
+
closer: (() => void) | null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/** Slot value: the assistant DB connection singletons, keyed by connection. Managed by `persistence/db-singleton.ts`. */
|
|
50
|
+
type VellumDbSlots = Record<VellumDbSlotKey, VellumDbSlot>;
|
|
51
|
+
|
|
52
|
+
/** Slot value: the resolved feature-flag override cache. Managed by `config/feature-flag-cache.ts`. */
|
|
53
|
+
interface VellumFeatureFlagCache {
|
|
54
|
+
overrides: Record<string, boolean | string> | null;
|
|
55
|
+
fromGateway: boolean;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/** The per-process `globalThis.vellumAssistant` namespace. */
|
|
59
|
+
interface VellumAssistantNamespace {
|
|
60
|
+
/**
|
|
61
|
+
* Whether this OS process is the main assistant daemon. Set once by the
|
|
62
|
+
* daemon entrypoint; absent elsewhere. See `runtime/process-role.ts`.
|
|
63
|
+
*/
|
|
64
|
+
mainDaemonProcess?: boolean;
|
|
65
|
+
/** See `security/store-path-override.ts`. */
|
|
66
|
+
storePathOverride?: VellumStorePathOverride;
|
|
67
|
+
/** See `persistence/db-singleton.ts`. */
|
|
68
|
+
dbSingletons?: VellumDbSlots;
|
|
69
|
+
/** See `config/feature-flag-cache.ts`. */
|
|
70
|
+
featureFlagCache?: VellumFeatureFlagCache;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Types `globalThis.vellumAssistant`. Undefined until the first slot accessor
|
|
75
|
+
* seeds it (`globalThis.vellumAssistant ??= {}`). Must be `var`: only `var`
|
|
76
|
+
* declarations at global scope become typed properties of `globalThis`
|
|
77
|
+
* (`let`/`const` do not), so this is the one idiomatic way to type the binding.
|
|
78
|
+
*/
|
|
79
|
+
// eslint-disable-next-line no-var
|
|
80
|
+
declare var vellumAssistant: VellumAssistantNamespace | undefined;
|
|
@@ -2,6 +2,7 @@ import { and, asc, desc, eq, gte, lte } from "drizzle-orm";
|
|
|
2
2
|
import { v4 as uuid } from "uuid";
|
|
3
3
|
|
|
4
4
|
import { getDb } from "../persistence/db-connection.js";
|
|
5
|
+
import { isLifecycleQuiesced } from "../persistence/lifecycle-quiesce.js";
|
|
5
6
|
import { rawChanges } from "../persistence/raw-query.js";
|
|
6
7
|
import { watcherEvents, watchers } from "../persistence/schema/index.js";
|
|
7
8
|
import { truncate } from "../util/truncate.js";
|
|
@@ -158,6 +159,13 @@ export function deleteWatcher(id: string): boolean {
|
|
|
158
159
|
* to 'polling' using optimistic locking on the current nextPollAt.
|
|
159
160
|
*/
|
|
160
161
|
export function claimDueWatchers(now: number): Watcher[] {
|
|
162
|
+
// Drain gate: while a quiesce lease is active, claim nothing — a watcher
|
|
163
|
+
// poll runs provider requests that create no row the drain snapshot can
|
|
164
|
+
// see, so it must not start at all. Fail-open via the lease read.
|
|
165
|
+
if (isLifecycleQuiesced()) {
|
|
166
|
+
return [];
|
|
167
|
+
}
|
|
168
|
+
|
|
161
169
|
const db = getDb();
|
|
162
170
|
const candidates = db
|
|
163
171
|
.select()
|
|
@@ -472,6 +472,105 @@ describe("runLeaf — tool path", () => {
|
|
|
472
472
|
expect(countConversations()).toBe(before);
|
|
473
473
|
});
|
|
474
474
|
|
|
475
|
+
test("rejects out-of-workspace paths for sandbox file tools", async () => {
|
|
476
|
+
// Leaf tool calls bypass the ToolExecutor permission lane, so the file
|
|
477
|
+
// tools' out-of-workspace host fallback must be unreachable from a leaf.
|
|
478
|
+
const calls: Array<Record<string, unknown>> = [];
|
|
479
|
+
const fileRead: Tool = {
|
|
480
|
+
name: "file_read",
|
|
481
|
+
description: "Tool file_read",
|
|
482
|
+
category: "filesystem",
|
|
483
|
+
defaultRiskLevel: "low" as never,
|
|
484
|
+
executionTarget: "sandbox",
|
|
485
|
+
input_schema: { type: "object", properties: {}, required: [] },
|
|
486
|
+
async execute(
|
|
487
|
+
input: Record<string, unknown>,
|
|
488
|
+
): Promise<ToolExecutionResult> {
|
|
489
|
+
calls.push(input);
|
|
490
|
+
return { content: "read ok", isError: false };
|
|
491
|
+
},
|
|
492
|
+
};
|
|
493
|
+
|
|
494
|
+
responseQueue = [
|
|
495
|
+
{
|
|
496
|
+
content: [
|
|
497
|
+
{
|
|
498
|
+
type: "tool_use",
|
|
499
|
+
name: "file_read",
|
|
500
|
+
id: "tu-1",
|
|
501
|
+
input: { path: "/etc/hosts" },
|
|
502
|
+
},
|
|
503
|
+
],
|
|
504
|
+
model: "test",
|
|
505
|
+
usage: { inputTokens: 5, outputTokens: 2 },
|
|
506
|
+
stopReason: "tool_use",
|
|
507
|
+
},
|
|
508
|
+
{
|
|
509
|
+
content: [{ type: "text", text: "done" }],
|
|
510
|
+
model: "test",
|
|
511
|
+
usage: { inputTokens: 2, outputTokens: 1 },
|
|
512
|
+
stopReason: "end_turn",
|
|
513
|
+
},
|
|
514
|
+
];
|
|
515
|
+
|
|
516
|
+
const result = await runLeaf({
|
|
517
|
+
prompt: "read the file",
|
|
518
|
+
tools: [fileRead],
|
|
519
|
+
trustContext,
|
|
520
|
+
});
|
|
521
|
+
expect(result.output).toBe("done");
|
|
522
|
+
// The workspace-bound guard fired before execute — the tool never ran.
|
|
523
|
+
expect(calls).toEqual([]);
|
|
524
|
+
});
|
|
525
|
+
|
|
526
|
+
test("in-workspace file tool paths still execute from a leaf", async () => {
|
|
527
|
+
const calls: Array<Record<string, unknown>> = [];
|
|
528
|
+
const fileRead: Tool = {
|
|
529
|
+
name: "file_read",
|
|
530
|
+
description: "Tool file_read",
|
|
531
|
+
category: "filesystem",
|
|
532
|
+
defaultRiskLevel: "low" as never,
|
|
533
|
+
executionTarget: "sandbox",
|
|
534
|
+
input_schema: { type: "object", properties: {}, required: [] },
|
|
535
|
+
async execute(
|
|
536
|
+
input: Record<string, unknown>,
|
|
537
|
+
): Promise<ToolExecutionResult> {
|
|
538
|
+
calls.push(input);
|
|
539
|
+
return { content: "read ok", isError: false };
|
|
540
|
+
},
|
|
541
|
+
};
|
|
542
|
+
|
|
543
|
+
responseQueue = [
|
|
544
|
+
{
|
|
545
|
+
content: [
|
|
546
|
+
{
|
|
547
|
+
type: "tool_use",
|
|
548
|
+
name: "file_read",
|
|
549
|
+
id: "tu-1",
|
|
550
|
+
input: { path: "notes.txt" },
|
|
551
|
+
},
|
|
552
|
+
],
|
|
553
|
+
model: "test",
|
|
554
|
+
usage: { inputTokens: 5, outputTokens: 2 },
|
|
555
|
+
stopReason: "tool_use",
|
|
556
|
+
},
|
|
557
|
+
{
|
|
558
|
+
content: [{ type: "text", text: "done" }],
|
|
559
|
+
model: "test",
|
|
560
|
+
usage: { inputTokens: 2, outputTokens: 1 },
|
|
561
|
+
stopReason: "end_turn",
|
|
562
|
+
},
|
|
563
|
+
];
|
|
564
|
+
|
|
565
|
+
const result = await runLeaf({
|
|
566
|
+
prompt: "read the file",
|
|
567
|
+
tools: [fileRead],
|
|
568
|
+
trustContext,
|
|
569
|
+
});
|
|
570
|
+
expect(result.output).toBe("done");
|
|
571
|
+
expect(calls).toEqual([{ path: "notes.txt" }]);
|
|
572
|
+
});
|
|
573
|
+
|
|
475
574
|
test("a leaf with no schema and an empty tool set runs the tool path (no throw)", async () => {
|
|
476
575
|
// An empty resolved tool set with no schema must NOT fall through to the
|
|
477
576
|
// schema path (where schemaToInputSchema(undefined) throws) — it runs the
|
|
@@ -702,8 +801,11 @@ describe("runLeaf — persona path", () => {
|
|
|
702
801
|
}>;
|
|
703
802
|
expect(messages[0]?.content[0]?.text).not.toBe(MEMORY_BLOCK_TEXT);
|
|
704
803
|
} finally {
|
|
705
|
-
if (savedAuth === undefined)
|
|
706
|
-
|
|
804
|
+
if (savedAuth === undefined) {
|
|
805
|
+
delete process.env.DISABLE_HTTP_AUTH;
|
|
806
|
+
} else {
|
|
807
|
+
process.env.DISABLE_HTTP_AUTH = savedAuth;
|
|
808
|
+
}
|
|
707
809
|
}
|
|
708
810
|
});
|
|
709
811
|
});
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
* `tool_choice` provider call whose synthetic tool's input schema is the
|
|
25
25
|
* caller's Zod schema. The returned tool input is Zod-validated and returned
|
|
26
26
|
* as `output`. Copies the proven pattern from `memory/v2/router.ts` and
|
|
27
|
-
* `memory/graph/extraction.ts`.
|
|
27
|
+
* `memory/v1/graph/extraction.ts`.
|
|
28
28
|
* - **Tool path** (`tools` provided, no `schema`): a real {@link AgentLoop} with
|
|
29
29
|
* a minimal task-scoped system prompt and a tool-executor restricted to the
|
|
30
30
|
* supplied registry tools. No conversation is bootstrapped — the loop runs
|
|
@@ -42,11 +42,13 @@ import { randomUUID } from "node:crypto";
|
|
|
42
42
|
import { z } from "zod";
|
|
43
43
|
|
|
44
44
|
import { type AgentEvent, AgentLoop } from "../agent/loop.js";
|
|
45
|
+
import type { AssistantEvent } from "../api/index.js";
|
|
45
46
|
import { getEffectiveProfile } from "../config/default-profile-catalog.js";
|
|
46
47
|
import { getConfig } from "../config/loader.js";
|
|
47
|
-
import
|
|
48
|
+
import { isMemoryEnabled } from "../config/memory-v3-gate.js";
|
|
48
49
|
import { isPersonalMemoryAllowed } from "../daemon/trust-context.js";
|
|
49
50
|
import type { TrustContext } from "../daemon/trust-context-types.js";
|
|
51
|
+
import { isOutOfWorkspaceFileInvocation } from "../permissions/workspace-policy.js";
|
|
50
52
|
import { ConversationGraphMemory } from "../plugins/defaults/memory/graph/conversation-graph-memory.js";
|
|
51
53
|
import { buildSystemPrompt } from "../prompts/system-prompt.js";
|
|
52
54
|
import {
|
|
@@ -128,21 +130,31 @@ async function resolveLeafContext(
|
|
|
128
130
|
* persona leaf still gets the assistant's identity system prompt but NO personal
|
|
129
131
|
* memory. Without this, a workflow launched by an untrusted actor whose manifest
|
|
130
132
|
* grants `persona` could exfiltrate private memory in its output.
|
|
133
|
+
*
|
|
134
|
+
* On a v3-live assistant a persona leaf receives no injected memory at all:
|
|
135
|
+
* `prepareMemory`'s v2 route is gated on `isV2InjectionEngineActive` (v3 live
|
|
136
|
+
* suppresses it), the v1 retriever short-circuits to empty under the
|
|
137
|
+
* concept-page substrate, and v3 orchestration is conversation-turn-scoped so
|
|
138
|
+
* it does not run for workflow leaves.
|
|
131
139
|
*/
|
|
132
140
|
async function injectPersonaMemory(
|
|
133
141
|
opts: RunLeafOptions,
|
|
134
142
|
messages: Message[],
|
|
135
143
|
): Promise<Message[]> {
|
|
136
|
-
if (!isPersonalMemoryAllowed(opts.trustContext))
|
|
144
|
+
if (!isPersonalMemoryAllowed(opts.trustContext)) {
|
|
145
|
+
return messages;
|
|
146
|
+
}
|
|
137
147
|
|
|
138
148
|
const config = getConfig();
|
|
139
|
-
if (config
|
|
149
|
+
if (!isMemoryEnabled(config)) {
|
|
150
|
+
return messages;
|
|
151
|
+
}
|
|
140
152
|
|
|
141
153
|
const ephemeralConversationId = `workflow-leaf:${randomUUID()}`;
|
|
142
154
|
const graphMemory = new ConversationGraphMemory(ephemeralConversationId);
|
|
143
155
|
// The memory pipeline broadcasts retrieval progress to the shared event hub
|
|
144
156
|
// (matching the main-agent hook); a leaf has no per-turn event callback.
|
|
145
|
-
const onEvent = (msg:
|
|
157
|
+
const onEvent = (msg: AssistantEvent): void => {
|
|
146
158
|
broadcastMessage(msg);
|
|
147
159
|
};
|
|
148
160
|
// `prepareMemory` requires a non-aborting signal; reuse the caller's when
|
|
@@ -525,6 +537,17 @@ async function executeLeafTool(
|
|
|
525
537
|
};
|
|
526
538
|
}
|
|
527
539
|
|
|
540
|
+
// Leaf tool calls bypass the ToolExecutor's permission lane, so the file
|
|
541
|
+
// tools' out-of-workspace host fallback must not be reachable from here:
|
|
542
|
+
// the manifest consent covers workspace-scoped operation only, and leaves
|
|
543
|
+
// reject host tools outright. Keep the leaf workspace-bound.
|
|
544
|
+
if (isOutOfWorkspaceFileInvocation(name, input, ctx.workingDir)) {
|
|
545
|
+
return {
|
|
546
|
+
content: `Tool "${name}" may only access paths inside the workspace when invoked from a workflow leaf.`,
|
|
547
|
+
isError: true,
|
|
548
|
+
};
|
|
549
|
+
}
|
|
550
|
+
|
|
528
551
|
const toolContext: ToolContext = {
|
|
529
552
|
conversationId: ctx.ephemeralConversationId,
|
|
530
553
|
workingDir: ctx.workingDir,
|
|
@@ -552,7 +575,9 @@ async function executeLeafTool(
|
|
|
552
575
|
function finalAssistantText(history: Message[]): string {
|
|
553
576
|
for (let i = history.length - 1; i >= 0; i--) {
|
|
554
577
|
const msg = history[i];
|
|
555
|
-
if (msg.role !== "assistant")
|
|
578
|
+
if (msg.role !== "assistant") {
|
|
579
|
+
continue;
|
|
580
|
+
}
|
|
556
581
|
const text = msg.content
|
|
557
582
|
.filter(
|
|
558
583
|
(b): b is Extract<typeof b, { type: "text" }> => b.type === "text",
|
|
@@ -4,8 +4,8 @@ import type { WorkspaceMigration } from "./types.js";
|
|
|
4
4
|
* Audit-only entry for the v2 concept-page schema upgrade introduced in PR
|
|
5
5
|
* #29823 (summary_dense / summary_sparse named vectors). The destructive
|
|
6
6
|
* collection rebuild and reembed enqueue both run inside the daemon at
|
|
7
|
-
* Qdrant init time — see `
|
|
8
|
-
* `assistant/src/plugins/defaults/memory/
|
|
7
|
+
* Qdrant init time — see `maybeRebuildConceptCollection` in
|
|
8
|
+
* `assistant/src/plugins/defaults/memory/substrate/boot-maintenance.ts`. The "exactly-once" fence is
|
|
9
9
|
* per-collection schema introspection, not per-workspace checkpoint, so
|
|
10
10
|
* users who wipe Qdrant separately still get re-rebuilt without resetting
|
|
11
11
|
* any workspace flag.
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { existsSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
import type { WorkspaceMigration } from "./types.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Fold `services["image-generation"].mode` into the provider field.
|
|
8
|
+
*
|
|
9
|
+
* Configs written by older versions carry two axes: `mode: "managed"` routes
|
|
10
|
+
* generation through the Vellum platform runtime proxy while `provider`
|
|
11
|
+
* names the backend the proxy fronts (gemini or openai). The schema treats
|
|
12
|
+
* `provider` as the only axis, with `"vellum"` meaning managed and the
|
|
13
|
+
* backend derived from the selected model's prefix at request time, so this
|
|
14
|
+
* migration rewrites every managed service to `provider: "vellum"`. There is
|
|
15
|
+
* no per-provider exemption: the stored backend value under managed mode is
|
|
16
|
+
* itself derived from the model on every model write, so replacing it loses
|
|
17
|
+
* nothing — `model` is preserved verbatim and keeps routing the managed
|
|
18
|
+
* request to the same backend.
|
|
19
|
+
*
|
|
20
|
+
* Idempotent: a config with no `mode` key is left untouched.
|
|
21
|
+
*/
|
|
22
|
+
export const imageGenerationModeToProviderMigration: WorkspaceMigration = {
|
|
23
|
+
id: "134-image-generation-mode-to-provider",
|
|
24
|
+
description:
|
|
25
|
+
"Fold services.image-generation mode into provider (managed -> provider: vellum)",
|
|
26
|
+
run(workspaceDir: string): void {
|
|
27
|
+
const configPath = join(workspaceDir, "config.json");
|
|
28
|
+
if (!existsSync(configPath)) {
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
let config: Record<string, unknown>;
|
|
33
|
+
try {
|
|
34
|
+
const raw = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
35
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
config = raw as Record<string, unknown>;
|
|
39
|
+
} catch {
|
|
40
|
+
return; // Malformed JSON — skip
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const services = readObj(config, "services");
|
|
44
|
+
if (!services) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const service = readObj(services, "image-generation");
|
|
49
|
+
if (!service || !("mode" in service)) {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (service.mode === "managed") {
|
|
54
|
+
service.provider = "vellum";
|
|
55
|
+
} else if (!("provider" in service)) {
|
|
56
|
+
// An explicit non-managed mode with no persisted provider resolves to
|
|
57
|
+
// the gemini schema default. Pin that choice: with `mode` gone, an
|
|
58
|
+
// absent provider leaf would otherwise be context-filled to "vellum"
|
|
59
|
+
// on platform deployments, silently flipping a your-own config to
|
|
60
|
+
// managed billing.
|
|
61
|
+
service.provider = "gemini";
|
|
62
|
+
}
|
|
63
|
+
delete service.mode;
|
|
64
|
+
|
|
65
|
+
// Write-then-rename keeps the migration rerunnable: a crash mid-write
|
|
66
|
+
// must not leave a truncated config.json that a retry reads as malformed
|
|
67
|
+
// and "completes" past, quarantining the user's unrelated settings.
|
|
68
|
+
const tmpPath = `${configPath}.tmp`;
|
|
69
|
+
writeFileSync(tmpPath, JSON.stringify(config, null, 2) + "\n");
|
|
70
|
+
renameSync(tmpPath, configPath);
|
|
71
|
+
},
|
|
72
|
+
down(workspaceDir: string): void {
|
|
73
|
+
const configPath = join(workspaceDir, "config.json");
|
|
74
|
+
if (!existsSync(configPath)) {
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
let config: Record<string, unknown>;
|
|
79
|
+
try {
|
|
80
|
+
const raw = JSON.parse(readFileSync(configPath, "utf-8"));
|
|
81
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
config = raw as Record<string, unknown>;
|
|
85
|
+
} catch {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const services = readObj(config, "services");
|
|
90
|
+
if (!services) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const service = readObj(services, "image-generation");
|
|
95
|
+
if (!service || "mode" in service) {
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Schemas that predate this migration accept provider "vellum" alongside
|
|
100
|
+
// mode "managed", so the managed pair round-trips exactly. The backend
|
|
101
|
+
// provider a managed service holds before `run()` is not recoverable —
|
|
102
|
+
// `run()` overwrites it with "vellum". That value is derived from the
|
|
103
|
+
// model prefix, so it re-derives on the next model write.
|
|
104
|
+
service.mode = service.provider === "vellum" ? "managed" : "your-own";
|
|
105
|
+
|
|
106
|
+
// Write-then-rename keeps the migration rerunnable: a crash mid-write
|
|
107
|
+
// must not leave a truncated config.json that a retry reads as malformed
|
|
108
|
+
// and "completes" past, quarantining the user's unrelated settings.
|
|
109
|
+
const tmpPath = `${configPath}.tmp`;
|
|
110
|
+
writeFileSync(tmpPath, JSON.stringify(config, null, 2) + "\n");
|
|
111
|
+
renameSync(tmpPath, configPath);
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
// ---------------------------------------------------------------------------
|
|
116
|
+
// Helpers (self-contained per migration AGENTS.md)
|
|
117
|
+
// ---------------------------------------------------------------------------
|
|
118
|
+
|
|
119
|
+
function readObj(
|
|
120
|
+
parent: Record<string, unknown>,
|
|
121
|
+
key: string,
|
|
122
|
+
): Record<string, unknown> | undefined {
|
|
123
|
+
const value = parent[key];
|
|
124
|
+
if (value == null || typeof value !== "object" || Array.isArray(value)) {
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
return value as Record<string, unknown>;
|
|
128
|
+
}
|