@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
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { afterEach, beforeEach, describe, expect, mock, test } from "bun:test";
|
|
17
17
|
|
|
18
|
-
import type {
|
|
18
|
+
import type { AssistantEvent } from "../api/index.js";
|
|
19
19
|
|
|
20
20
|
// ── Captured constructor state ──────────────────────────────────────────────
|
|
21
21
|
|
|
@@ -36,7 +36,7 @@ class FakeConversation {
|
|
|
36
36
|
_id: string,
|
|
37
37
|
_provider: unknown,
|
|
38
38
|
systemPrompt: string,
|
|
39
|
-
_sendToClient: (msg:
|
|
39
|
+
_sendToClient: (msg: AssistantEvent) => void,
|
|
40
40
|
_workingDir: string,
|
|
41
41
|
_options?: unknown,
|
|
42
42
|
) {
|
|
@@ -148,7 +148,7 @@ describe("SubagentManager fork — prompt source and role decoupling", () => {
|
|
|
148
148
|
): Promise<CapturedConversationState> {
|
|
149
149
|
await manager.spawn(makeForkSpawnConfig(overrides), () => {});
|
|
150
150
|
const created = capturedConversations[0];
|
|
151
|
-
if (!created) throw new Error("Expected a subagent conversation");
|
|
151
|
+
if (!created) {throw new Error("Expected a subagent conversation");}
|
|
152
152
|
return created;
|
|
153
153
|
}
|
|
154
154
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
2
|
|
|
3
|
+
import type { AssistantEvent } from "../api/index.js";
|
|
3
4
|
import {
|
|
4
5
|
clearConversations,
|
|
5
6
|
findConversation,
|
|
6
7
|
setConversation,
|
|
7
8
|
} from "../daemon/conversation-registry.js";
|
|
8
|
-
import type { ServerMessage } from "../daemon/message-protocol.js";
|
|
9
9
|
import type { Message } from "../providers/types.js";
|
|
10
10
|
import { SubagentManager } from "../subagent/manager.js";
|
|
11
11
|
import type { SubagentConfig, SubagentState } from "../subagent/types.js";
|
|
@@ -16,7 +16,7 @@ interface FakeManagedSubagent {
|
|
|
16
16
|
abort: () => void;
|
|
17
17
|
dispose: () => void;
|
|
18
18
|
messages: Message[];
|
|
19
|
-
sendToClient: (msg:
|
|
19
|
+
sendToClient: (msg: AssistantEvent) => void;
|
|
20
20
|
persistUserMessage?: () => { id: string; deduplicated: boolean };
|
|
21
21
|
runAgentLoop?: () => Promise<void>;
|
|
22
22
|
enqueueMessage?: () => { rejected: boolean; queued: boolean };
|
|
@@ -31,7 +31,7 @@ interface FakeManagedSubagent {
|
|
|
31
31
|
subagentDeniedToolNames: Set<string>;
|
|
32
32
|
} | null;
|
|
33
33
|
state: SubagentState;
|
|
34
|
-
parentSendToClient: (msg:
|
|
34
|
+
parentSendToClient: (msg: AssistantEvent) => void;
|
|
35
35
|
retainedUntil?: number;
|
|
36
36
|
hadEnqueuedMessages?: boolean;
|
|
37
37
|
}
|
|
@@ -66,7 +66,7 @@ function injectFakeSubagent(
|
|
|
66
66
|
manager: SubagentManager,
|
|
67
67
|
subagentId: string,
|
|
68
68
|
state: SubagentState,
|
|
69
|
-
parentSendToClient?: (msg:
|
|
69
|
+
parentSendToClient?: (msg: AssistantEvent) => void,
|
|
70
70
|
conversation?: FakeManagedSubagent["conversation"],
|
|
71
71
|
): void {
|
|
72
72
|
const internals = asInternals(manager);
|
|
@@ -29,7 +29,7 @@ mock.module("../runtime/assistant-event-hub.js", () => ({
|
|
|
29
29
|
broadcastMessage: () => {},
|
|
30
30
|
}));
|
|
31
31
|
|
|
32
|
-
import type {
|
|
32
|
+
import type { AssistantEvent } from "../api/index.js";
|
|
33
33
|
import { SubagentManager } from "../subagent/manager.js";
|
|
34
34
|
import type { SubagentState } from "../subagent/types.js";
|
|
35
35
|
|
|
@@ -42,7 +42,7 @@ interface FakeManagedSubagent {
|
|
|
42
42
|
role: string;
|
|
43
43
|
content: Array<{ type: string; text: string }>;
|
|
44
44
|
}>;
|
|
45
|
-
sendToClient: (msg:
|
|
45
|
+
sendToClient: (msg: AssistantEvent) => void;
|
|
46
46
|
loadFromDb?: () => Promise<void>;
|
|
47
47
|
persistUserMessage?: () => { id: string; deduplicated: boolean };
|
|
48
48
|
runAgentLoop?: () => Promise<void>;
|
|
@@ -54,7 +54,7 @@ interface FakeManagedSubagent {
|
|
|
54
54
|
subagentDeniedToolNames: Set<string>;
|
|
55
55
|
} | null;
|
|
56
56
|
state: SubagentState;
|
|
57
|
-
parentSendToClient: (msg:
|
|
57
|
+
parentSendToClient: (msg: AssistantEvent) => void;
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
/** Type-safe accessor for SubagentManager's private internals via bracket notation. */
|
|
@@ -77,7 +77,7 @@ function injectFakeSubagent(
|
|
|
77
77
|
manager: SubagentManager,
|
|
78
78
|
subagentId: string,
|
|
79
79
|
state: SubagentState,
|
|
80
|
-
parentSendToClient?: (msg:
|
|
80
|
+
parentSendToClient?: (msg: AssistantEvent) => void,
|
|
81
81
|
): void {
|
|
82
82
|
const fakeSession: FakeManagedSubagent["conversation"] = {
|
|
83
83
|
abort: () => {},
|
|
@@ -137,8 +137,8 @@ describe("SubagentManager abort notification", () => {
|
|
|
137
137
|
const state = makeState(subagentId);
|
|
138
138
|
injectFakeSubagent(manager, subagentId, state);
|
|
139
139
|
|
|
140
|
-
const clientMessages:
|
|
141
|
-
const sendToClient = (msg:
|
|
140
|
+
const clientMessages: AssistantEvent[] = [];
|
|
141
|
+
const sendToClient = (msg: AssistantEvent) => clientMessages.push(msg);
|
|
142
142
|
|
|
143
143
|
const result = manager.abort(subagentId, sendToClient);
|
|
144
144
|
|
|
@@ -160,8 +160,8 @@ describe("SubagentManager abort notification", () => {
|
|
|
160
160
|
injectFakeSubagent(manager, subagentId, state, parentSender);
|
|
161
161
|
|
|
162
162
|
// A different sender (simulating abort from a different thread's socket).
|
|
163
|
-
const abortingSender = ((_msg:
|
|
164
|
-
msg:
|
|
163
|
+
const abortingSender = ((_msg: AssistantEvent) => {}) as (
|
|
164
|
+
msg: AssistantEvent,
|
|
165
165
|
) => void;
|
|
166
166
|
|
|
167
167
|
manager.abort(subagentId, abortingSender);
|
|
@@ -175,8 +175,8 @@ describe("SubagentManager abort notification", () => {
|
|
|
175
175
|
const manager = new SubagentManager();
|
|
176
176
|
const subagentId = "sub-1";
|
|
177
177
|
|
|
178
|
-
const clientMessages:
|
|
179
|
-
const sendToClient = (msg:
|
|
178
|
+
const clientMessages: AssistantEvent[] = [];
|
|
179
|
+
const sendToClient = (msg: AssistantEvent) => clientMessages.push(msg);
|
|
180
180
|
|
|
181
181
|
// Pass the sender as parentSendToClient so the stored sender receives the status update.
|
|
182
182
|
injectFakeSubagent(
|
|
@@ -386,7 +386,7 @@ describe("SubagentManager notifyParent (via runSubagent)", () => {
|
|
|
386
386
|
});
|
|
387
387
|
|
|
388
388
|
describe("SubagentManager abortAllForParent", () => {
|
|
389
|
-
test("aborts
|
|
389
|
+
test("aborts active children but keeps every child's state readable", () => {
|
|
390
390
|
clearCaptured();
|
|
391
391
|
const manager = new SubagentManager();
|
|
392
392
|
injectFakeSubagent(manager, "sub-1", makeState("sub-1"));
|
|
@@ -402,20 +402,79 @@ describe("SubagentManager abortAllForParent", () => {
|
|
|
402
402
|
expect(count).toBe(2); // sub-1 and sub-2, not sub-3 (already completed)
|
|
403
403
|
expect(capturedNotifications).toHaveLength(2);
|
|
404
404
|
|
|
405
|
-
//
|
|
405
|
+
// The parent conversation lives on (stop/eviction/rebuild), so every
|
|
406
|
+
// child stays tracked: aborted ones as terminal metadata, and the
|
|
407
|
+
// completed one still readable via subagent_read.
|
|
408
|
+
expect(manager.getState("sub-1")?.status).toBe("aborted");
|
|
409
|
+
expect(manager.getState("sub-2")?.status).toBe("aborted");
|
|
410
|
+
expect(manager.getState("sub-3")?.status).toBe("completed");
|
|
411
|
+
expect(manager.getChildrenOf("parent-sess-1")).toHaveLength(3);
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
test("returns 0 for unknown parent", () => {
|
|
415
|
+
const manager = new SubagentManager();
|
|
416
|
+
const count = manager.abortAllForParent("nonexistent");
|
|
417
|
+
expect(count).toBe(0);
|
|
418
|
+
});
|
|
419
|
+
});
|
|
420
|
+
|
|
421
|
+
describe("SubagentManager disposeAllForParent", () => {
|
|
422
|
+
test("aborts and removes all children — parent data is going away", () => {
|
|
423
|
+
clearCaptured();
|
|
424
|
+
const manager = new SubagentManager();
|
|
425
|
+
injectFakeSubagent(manager, "sub-1", makeState("sub-1"));
|
|
426
|
+
injectFakeSubagent(
|
|
427
|
+
manager,
|
|
428
|
+
"sub-2",
|
|
429
|
+
makeState("sub-2", { status: "completed" }),
|
|
430
|
+
);
|
|
431
|
+
|
|
432
|
+
const count = manager.disposeAllForParent("parent-sess-1", () => {});
|
|
433
|
+
|
|
434
|
+
expect(count).toBe(1); // only sub-1 was still in flight
|
|
406
435
|
expect(manager.getState("sub-1")).toBeUndefined();
|
|
407
436
|
expect(manager.getState("sub-2")).toBeUndefined();
|
|
408
|
-
expect(manager.getState("sub-3")).toBeUndefined();
|
|
409
437
|
expect(manager.getChildrenOf("parent-sess-1")).toHaveLength(0);
|
|
410
438
|
});
|
|
411
439
|
|
|
412
440
|
test("returns 0 for unknown parent", () => {
|
|
413
441
|
const manager = new SubagentManager();
|
|
414
|
-
const count = manager.
|
|
442
|
+
const count = manager.disposeAllForParent("nonexistent");
|
|
415
443
|
expect(count).toBe(0);
|
|
416
444
|
});
|
|
417
445
|
});
|
|
418
446
|
|
|
447
|
+
describe("SubagentManager disposeAllForAllParents", () => {
|
|
448
|
+
test("removes retained children across every parent — clear-all semantics", () => {
|
|
449
|
+
clearCaptured();
|
|
450
|
+
const manager = new SubagentManager();
|
|
451
|
+
// Two parents; only one would appear in the in-memory conversation store
|
|
452
|
+
// during a clear-all — the other models an evicted parent whose terminal
|
|
453
|
+
// children are still retained.
|
|
454
|
+
injectFakeSubagent(manager, "sub-a", makeState("sub-a"));
|
|
455
|
+
injectFakeSubagent(
|
|
456
|
+
manager,
|
|
457
|
+
"sub-b",
|
|
458
|
+
makeState("sub-b", {
|
|
459
|
+
config: {
|
|
460
|
+
id: "sub-b",
|
|
461
|
+
parentConversationId: "parent-evicted",
|
|
462
|
+
label: "Evicted parent child",
|
|
463
|
+
objective: "Do something",
|
|
464
|
+
},
|
|
465
|
+
status: "completed",
|
|
466
|
+
}),
|
|
467
|
+
);
|
|
468
|
+
|
|
469
|
+
manager.disposeAllForAllParents();
|
|
470
|
+
|
|
471
|
+
expect(manager.getState("sub-a")).toBeUndefined();
|
|
472
|
+
expect(manager.getState("sub-b")).toBeUndefined();
|
|
473
|
+
expect(manager.getChildrenOf("parent-sess-1")).toHaveLength(0);
|
|
474
|
+
expect(manager.getChildrenOf("parent-evicted")).toHaveLength(0);
|
|
475
|
+
});
|
|
476
|
+
});
|
|
477
|
+
|
|
419
478
|
describe("SubagentManager sharedRequestTimestamps", () => {
|
|
420
479
|
test("defaults to an empty array", () => {
|
|
421
480
|
const manager = new SubagentManager();
|
|
@@ -44,7 +44,13 @@ const capturedParentIds: string[] = [];
|
|
|
44
44
|
// Live subagent conversations, keyed by conversationId. notifyParentFromChild
|
|
45
45
|
// routes to the parent recorded here (the non-writable in-process source), so
|
|
46
46
|
// tests register a child before expecting a notification to route.
|
|
47
|
-
const liveSubagents = new Map<
|
|
47
|
+
const liveSubagents = new Map<
|
|
48
|
+
string,
|
|
49
|
+
{
|
|
50
|
+
parentConversationId: string;
|
|
51
|
+
subagentSuppressParentNotifications?: boolean;
|
|
52
|
+
}
|
|
53
|
+
>();
|
|
48
54
|
|
|
49
55
|
mock.module("../daemon/conversation-registry.js", () => ({
|
|
50
56
|
findConversation: (id: string) => {
|
|
@@ -60,9 +66,7 @@ mock.module("../daemon/conversation-registry.js", () => ({
|
|
|
60
66
|
},
|
|
61
67
|
findConversationOrSubagent: (id: string) => {
|
|
62
68
|
const live = liveSubagents.get(id);
|
|
63
|
-
return live
|
|
64
|
-
? { parentConversationId: live.parentConversationId }
|
|
65
|
-
: undefined;
|
|
69
|
+
return live ? { ...live } : undefined;
|
|
66
70
|
},
|
|
67
71
|
}));
|
|
68
72
|
|
|
@@ -321,6 +325,23 @@ describe("notifyParentFromChild", () => {
|
|
|
321
325
|
expect(lastCapturedMessage()).toContain("Test message");
|
|
322
326
|
});
|
|
323
327
|
|
|
328
|
+
test("returns false for a synchronous child that suppresses parent notifications", () => {
|
|
329
|
+
clearCaptured();
|
|
330
|
+
const conversationId = "conv-suppressed-1";
|
|
331
|
+
seedSubagent(conversationId);
|
|
332
|
+
// spawnAndAwait children carry this flag: the awaiting caller is their
|
|
333
|
+
// only parent channel, so a mid-run injection must not reach the parent.
|
|
334
|
+
const live = liveSubagents.get(conversationId);
|
|
335
|
+
if (live) {
|
|
336
|
+
live.subagentSuppressParentNotifications = true;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
expect(
|
|
340
|
+
notifyParentFromChild(conversationId, "Should not arrive", "info"),
|
|
341
|
+
).toBe(false);
|
|
342
|
+
expect(capturedMessages).toHaveLength(0);
|
|
343
|
+
});
|
|
344
|
+
|
|
324
345
|
test("labels forks as Fork", () => {
|
|
325
346
|
clearCaptured();
|
|
326
347
|
const conversationId = "conv-fork-1";
|
|
@@ -349,3 +370,26 @@ describe("notifyParentFromChild", () => {
|
|
|
349
370
|
expect(capturedParentIds).not.toContain("victim-conversation");
|
|
350
371
|
});
|
|
351
372
|
});
|
|
373
|
+
|
|
374
|
+
describe("notify_parent — model-input schema validation (LUM-2857)", () => {
|
|
375
|
+
test("rejects a non-string message", async () => {
|
|
376
|
+
const result = await executeSubagentNotifyParent(
|
|
377
|
+
{ message: 42 },
|
|
378
|
+
makeContext("conv-notify-schema-1"),
|
|
379
|
+
);
|
|
380
|
+
expect(result.isError).toBe(true);
|
|
381
|
+
expect(result.content).toContain('Invalid input for tool "notify_parent"');
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
test("degrades a malformed urgency to info instead of forwarding it", async () => {
|
|
385
|
+
const conversationId = "conv-notify-schema-2";
|
|
386
|
+
seedSubagent(conversationId);
|
|
387
|
+
const result = await executeSubagentNotifyParent(
|
|
388
|
+
{ message: "found something", urgency: 42 },
|
|
389
|
+
makeContext(conversationId),
|
|
390
|
+
);
|
|
391
|
+
expect(result.isError).toBe(false);
|
|
392
|
+
const parsed = JSON.parse(result.content) as { urgency: string };
|
|
393
|
+
expect(parsed.urgency).toBe("info");
|
|
394
|
+
});
|
|
395
|
+
});
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
15
15
|
|
|
16
|
-
import type {
|
|
16
|
+
import type { AssistantEvent } from "../api/index.js";
|
|
17
17
|
import type { Message } from "../providers/types.js";
|
|
18
18
|
|
|
19
19
|
// ── Fake Conversation ───────────────────────────────────────────────────────
|
|
@@ -36,7 +36,7 @@ interface FakeConversationConfig {
|
|
|
36
36
|
*/
|
|
37
37
|
resolveOnAbort?: boolean;
|
|
38
38
|
/** Deltas to emit through sendToClient before runAgentLoop resolves. */
|
|
39
|
-
emitDeltas?:
|
|
39
|
+
emitDeltas?: AssistantEvent[];
|
|
40
40
|
/**
|
|
41
41
|
* Invoked synchronously at the very start of runAgentLoop (after the loop has
|
|
42
42
|
* begun, so the run is past the early-terminal guard and marked "running").
|
|
@@ -54,6 +54,13 @@ let runLoopInvoked = false;
|
|
|
54
54
|
let lastPersistedUserMessage: string | undefined;
|
|
55
55
|
/** Records `setSubagentDenySideEffects` on the most recent FakeConversation. */
|
|
56
56
|
let lastDenySideEffects: boolean | undefined;
|
|
57
|
+
/**
|
|
58
|
+
* Records `setSubagentSuppressParentNotifications` on the most recent
|
|
59
|
+
* FakeConversation.
|
|
60
|
+
*/
|
|
61
|
+
let lastSuppressParentNotifications: boolean | undefined;
|
|
62
|
+
/** Records `setTrustContext` on the most recent FakeConversation. */
|
|
63
|
+
let lastTrustContext: unknown;
|
|
57
64
|
/** Options the most recent `bootstrapConversation` call received. */
|
|
58
65
|
let lastBootstrapOptions: Record<string, unknown> | undefined;
|
|
59
66
|
|
|
@@ -64,7 +71,7 @@ class FakeConversation {
|
|
|
64
71
|
conversationType = "background";
|
|
65
72
|
hasSystemPromptOverride = false;
|
|
66
73
|
|
|
67
|
-
private sendToClient: (msg:
|
|
74
|
+
private sendToClient: (msg: AssistantEvent) => void;
|
|
68
75
|
private readonly cfg: FakeConversationConfig;
|
|
69
76
|
private aborted = false;
|
|
70
77
|
private resolveAbort?: () => void;
|
|
@@ -73,7 +80,7 @@ class FakeConversation {
|
|
|
73
80
|
_id: string,
|
|
74
81
|
_provider: unknown,
|
|
75
82
|
_systemPrompt: string,
|
|
76
|
-
sendToClient: (msg:
|
|
83
|
+
sendToClient: (msg: AssistantEvent) => void,
|
|
77
84
|
_workingDir: string,
|
|
78
85
|
_options?: unknown,
|
|
79
86
|
) {
|
|
@@ -82,13 +89,15 @@ class FakeConversation {
|
|
|
82
89
|
this.messages = this.cfg.messages ?? [];
|
|
83
90
|
}
|
|
84
91
|
|
|
85
|
-
updateClient(sendToClient: (msg:
|
|
92
|
+
updateClient(sendToClient: (msg: AssistantEvent) => void) {
|
|
86
93
|
// The manager re-points sendToClient via updateClient; honor it so the
|
|
87
94
|
// wrappedSendToClient tap is the one the deltas flow through.
|
|
88
95
|
this.sendToClient = sendToClient;
|
|
89
96
|
}
|
|
90
97
|
|
|
91
|
-
setTrustContext() {
|
|
98
|
+
setTrustContext(ctx: unknown) {
|
|
99
|
+
lastTrustContext = ctx;
|
|
100
|
+
}
|
|
92
101
|
setAuthContext() {}
|
|
93
102
|
getAuthContext() {
|
|
94
103
|
return undefined;
|
|
@@ -99,6 +108,9 @@ class FakeConversation {
|
|
|
99
108
|
setSubagentDenySideEffects(deny: boolean) {
|
|
100
109
|
lastDenySideEffects = deny;
|
|
101
110
|
}
|
|
111
|
+
setSubagentSuppressParentNotifications(suppress: boolean) {
|
|
112
|
+
lastSuppressParentNotifications = suppress;
|
|
113
|
+
}
|
|
102
114
|
setPreactivatedSkillIds() {}
|
|
103
115
|
getCurrentSystemPrompt() {
|
|
104
116
|
return "system";
|
|
@@ -125,7 +137,9 @@ class FakeConversation {
|
|
|
125
137
|
this.resolveAbort = resolve;
|
|
126
138
|
});
|
|
127
139
|
}
|
|
128
|
-
if (this.cfg.resolveOnAbort)
|
|
140
|
+
if (this.cfg.resolveOnAbort) {
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
129
143
|
throw new Error("aborted");
|
|
130
144
|
}
|
|
131
145
|
if (this.cfg.runError) {
|
|
@@ -199,7 +213,7 @@ function makeConfig(overrides: Record<string, unknown> = {}) {
|
|
|
199
213
|
}
|
|
200
214
|
|
|
201
215
|
/** Statuses broadcast to the parent via `subagent_status_changed` events. */
|
|
202
|
-
function broadcastStatuses(events:
|
|
216
|
+
function broadcastStatuses(events: AssistantEvent[]): string[] {
|
|
203
217
|
return events
|
|
204
218
|
.filter((m) => m.type === "subagent_status_changed")
|
|
205
219
|
.map((m) => (m as { status: string }).status);
|
|
@@ -228,6 +242,8 @@ describe("SubagentManager.spawnAndAwait", () => {
|
|
|
228
242
|
// `undefined` across the opaque spawnAndAwait call.
|
|
229
243
|
beforeEach(() => {
|
|
230
244
|
lastDenySideEffects = undefined;
|
|
245
|
+
lastSuppressParentNotifications = undefined;
|
|
246
|
+
lastTrustContext = undefined;
|
|
231
247
|
});
|
|
232
248
|
|
|
233
249
|
test("wires denySideEffectTools onto the subagent conversation (read-only)", async () => {
|
|
@@ -251,6 +267,38 @@ describe("SubagentManager.spawnAndAwait", () => {
|
|
|
251
267
|
expect(lastDenySideEffects).toBeUndefined();
|
|
252
268
|
});
|
|
253
269
|
|
|
270
|
+
test("an explicit config trustContext lands on the subagent conversation", async () => {
|
|
271
|
+
nextConversationConfig = {};
|
|
272
|
+
|
|
273
|
+
const manager = new SubagentManager();
|
|
274
|
+
// No parent conversation is registered here, so inheritance would leave
|
|
275
|
+
// trust unset — the explicit config value must be applied regardless (the
|
|
276
|
+
// live-voice continuation path, where the parent's per-turn trust has
|
|
277
|
+
// already been cleared at spawn time).
|
|
278
|
+
await manager.spawnAndAwait(
|
|
279
|
+
makeConfig({
|
|
280
|
+
trustContext: { sourceChannel: "vellum", trustClass: "guardian" },
|
|
281
|
+
}),
|
|
282
|
+
() => {},
|
|
283
|
+
);
|
|
284
|
+
|
|
285
|
+
expect(lastTrustContext).toMatchObject({
|
|
286
|
+
sourceChannel: "vellum",
|
|
287
|
+
trustClass: "guardian",
|
|
288
|
+
});
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
test("suppresses mid-run parent notifications on the synchronous path", async () => {
|
|
292
|
+
nextConversationConfig = {};
|
|
293
|
+
|
|
294
|
+
const manager = new SubagentManager();
|
|
295
|
+
await manager.spawnAndAwait(makeConfig(), () => {});
|
|
296
|
+
|
|
297
|
+
// The awaiting caller is the child's only parent channel: notify_parent
|
|
298
|
+
// must not inject a user-role turn into the live parent mid-await.
|
|
299
|
+
expect(lastSuppressParentNotifications).toBe(true);
|
|
300
|
+
});
|
|
301
|
+
|
|
254
302
|
test("stamps the parent conversation id on the subagent's conversation", async () => {
|
|
255
303
|
nextConversationConfig = {};
|
|
256
304
|
|
|
@@ -326,14 +374,14 @@ describe("SubagentManager.spawnAndAwait", () => {
|
|
|
326
374
|
{ role: "assistant", content: [{ type: "text", text: "done" }] },
|
|
327
375
|
],
|
|
328
376
|
emitDeltas: [
|
|
329
|
-
{ type: "assistant_text_delta", text: "Hello " } as
|
|
377
|
+
{ type: "assistant_text_delta", text: "Hello " } as AssistantEvent,
|
|
330
378
|
{
|
|
331
379
|
type: "assistant_thinking_delta",
|
|
332
380
|
thinking: "(pondering) ",
|
|
333
|
-
} as
|
|
334
|
-
{ type: "assistant_text_delta", text: "world" } as
|
|
381
|
+
} as AssistantEvent,
|
|
382
|
+
{ type: "assistant_text_delta", text: "world" } as AssistantEvent,
|
|
335
383
|
// Non-delta events must not be forwarded to onText.
|
|
336
|
-
{ type: "subagent_status_changed" } as
|
|
384
|
+
{ type: "subagent_status_changed" } as AssistantEvent,
|
|
337
385
|
],
|
|
338
386
|
};
|
|
339
387
|
|
|
@@ -382,7 +430,7 @@ describe("SubagentManager.spawnAndAwait", () => {
|
|
|
382
430
|
// terminal first so this is recorded and broadcast as "aborted".
|
|
383
431
|
nextConversationConfig = { resolveOnAbort: true };
|
|
384
432
|
|
|
385
|
-
const events:
|
|
433
|
+
const events: AssistantEvent[] = [];
|
|
386
434
|
const controller = new AbortController();
|
|
387
435
|
const manager = new SubagentManager();
|
|
388
436
|
const promise = manager.spawnAndAwait(
|
|
@@ -441,7 +489,7 @@ describe("SubagentManager.spawnAndAwait", () => {
|
|
|
441
489
|
const controller = new AbortController();
|
|
442
490
|
controller.abort();
|
|
443
491
|
|
|
444
|
-
const events:
|
|
492
|
+
const events: AssistantEvent[] = [];
|
|
445
493
|
const manager = new SubagentManager();
|
|
446
494
|
await expect(
|
|
447
495
|
manager.spawnAndAwait(makeConfig(), (msg) => events.push(msg), {
|
|
@@ -1986,3 +1986,67 @@ describe("Advisor role is tool-less", () => {
|
|
|
1986
1986
|
).toBe(0);
|
|
1987
1987
|
});
|
|
1988
1988
|
});
|
|
1989
|
+
|
|
1990
|
+
// ── model-input schema validation (LUM-2855) ────────────────────────
|
|
1991
|
+
|
|
1992
|
+
describe("subagent tools — model-input schema validation", () => {
|
|
1993
|
+
test("spawn rejects a non-string label instead of spawning with it", async () => {
|
|
1994
|
+
const result = await executeSubagentSpawn(
|
|
1995
|
+
{ label: 42, objective: "do something" },
|
|
1996
|
+
makeContext("sess-schema", { sendToClient: () => {} }),
|
|
1997
|
+
);
|
|
1998
|
+
expect(result.isError).toBe(true);
|
|
1999
|
+
expect(result.content).toContain('Invalid input for tool "subagent_spawn"');
|
|
2000
|
+
expect(result.content).toContain("label");
|
|
2001
|
+
});
|
|
2002
|
+
|
|
2003
|
+
test("spawn treats explicit null label as missing (bespoke required error)", async () => {
|
|
2004
|
+
const result = await executeSubagentSpawn(
|
|
2005
|
+
{ label: null, objective: "do something" },
|
|
2006
|
+
makeContext("sess-schema", { sendToClient: () => {} }),
|
|
2007
|
+
);
|
|
2008
|
+
expect(result.isError).toBe(true);
|
|
2009
|
+
expect(result.content).toContain("required");
|
|
2010
|
+
});
|
|
2011
|
+
|
|
2012
|
+
test("status rejects a non-string subagent_id", async () => {
|
|
2013
|
+
const result = await executeSubagentStatus(
|
|
2014
|
+
{ subagent_id: 42 },
|
|
2015
|
+
makeContext("sess-schema"),
|
|
2016
|
+
);
|
|
2017
|
+
expect(result.isError).toBe(true);
|
|
2018
|
+
expect(result.content).toContain(
|
|
2019
|
+
'Invalid input for tool "subagent_status"',
|
|
2020
|
+
);
|
|
2021
|
+
});
|
|
2022
|
+
|
|
2023
|
+
test("message rejects a non-string content", async () => {
|
|
2024
|
+
const result = await executeSubagentMessage(
|
|
2025
|
+
{ subagent_id: "some-id", content: 42 },
|
|
2026
|
+
makeContext("sess-schema"),
|
|
2027
|
+
);
|
|
2028
|
+
expect(result.isError).toBe(true);
|
|
2029
|
+
expect(result.content).toContain(
|
|
2030
|
+
'Invalid input for tool "subagent_message"',
|
|
2031
|
+
);
|
|
2032
|
+
expect(result.content).toContain("content");
|
|
2033
|
+
});
|
|
2034
|
+
|
|
2035
|
+
test("read rejects a non-string label but passes malformed last_n through", async () => {
|
|
2036
|
+
const bad = await executeSubagentRead(
|
|
2037
|
+
{ label: 42 },
|
|
2038
|
+
makeContext("sess-schema"),
|
|
2039
|
+
);
|
|
2040
|
+
expect(bad.isError).toBe(true);
|
|
2041
|
+
expect(bad.content).toContain('Invalid input for tool "subagent_read"');
|
|
2042
|
+
|
|
2043
|
+
// last_n is loose passthrough — a malformed value is ignored, so the call
|
|
2044
|
+
// reaches the bespoke "required" check instead of failing validation.
|
|
2045
|
+
const passthrough = await executeSubagentRead(
|
|
2046
|
+
{ last_n: "five" },
|
|
2047
|
+
makeContext("sess-schema"),
|
|
2048
|
+
);
|
|
2049
|
+
expect(passthrough.isError).toBe(true);
|
|
2050
|
+
expect(passthrough.content).toContain("required");
|
|
2051
|
+
});
|
|
2052
|
+
});
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
2
|
|
|
3
|
+
import type { AssistantEvent } from "../api/index.js";
|
|
3
4
|
import {
|
|
4
5
|
buildSyncChangedMessage,
|
|
5
6
|
conversationMessagesSyncTag,
|
|
6
|
-
type ServerMessage,
|
|
7
7
|
SYNC_TAGS,
|
|
8
8
|
SyncChangedEventSchema,
|
|
9
9
|
} from "../daemon/message-protocol.js";
|
|
10
10
|
|
|
11
11
|
describe("sync message contract", () => {
|
|
12
|
-
test("sync_changed is assignable to
|
|
13
|
-
const message:
|
|
12
|
+
test("sync_changed is assignable to AssistantEvent", () => {
|
|
13
|
+
const message: AssistantEvent = {
|
|
14
14
|
type: "sync_changed",
|
|
15
15
|
tags: [SYNC_TAGS.assistantAvatar],
|
|
16
16
|
};
|
|
@@ -219,7 +219,10 @@ describe("Shell tool input validation", () => {
|
|
|
219
219
|
baseContext,
|
|
220
220
|
);
|
|
221
221
|
expect(result.isError).toBe(true);
|
|
222
|
-
expect(result.content).toContain(
|
|
222
|
+
expect(result.content).toContain('Invalid input for tool "bash"');
|
|
223
|
+
expect(result.content).toContain(
|
|
224
|
+
"command: Too small: expected string to have >=1 characters",
|
|
225
|
+
);
|
|
223
226
|
});
|
|
224
227
|
|
|
225
228
|
test("rejects non-string command", async () => {
|
|
@@ -228,7 +231,10 @@ describe("Shell tool input validation", () => {
|
|
|
228
231
|
baseContext,
|
|
229
232
|
);
|
|
230
233
|
expect(result.isError).toBe(true);
|
|
231
|
-
expect(result.content).toContain(
|
|
234
|
+
expect(result.content).toContain('Invalid input for tool "bash"');
|
|
235
|
+
expect(result.content).toContain(
|
|
236
|
+
"command: Invalid input: expected string, received number",
|
|
237
|
+
);
|
|
232
238
|
});
|
|
233
239
|
|
|
234
240
|
test("rejects command with null bytes", async () => {
|
|
@@ -243,7 +249,10 @@ describe("Shell tool input validation", () => {
|
|
|
243
249
|
test("rejects missing command", async () => {
|
|
244
250
|
const result = await shellTool.execute({ reason: "test" }, baseContext);
|
|
245
251
|
expect(result.isError).toBe(true);
|
|
246
|
-
expect(result.content).toContain(
|
|
252
|
+
expect(result.content).toContain('Invalid input for tool "bash"');
|
|
253
|
+
expect(result.content).toContain(
|
|
254
|
+
"command: Invalid input: expected string, received undefined",
|
|
255
|
+
);
|
|
247
256
|
});
|
|
248
257
|
|
|
249
258
|
test("executes simple command successfully", async () => {
|
|
@@ -55,6 +55,15 @@ const savedCesCredentialUrl = process.env.CES_CREDENTIAL_URL;
|
|
|
55
55
|
delete process.env.IS_CONTAINERIZED;
|
|
56
56
|
delete process.env.CES_CREDENTIAL_URL;
|
|
57
57
|
|
|
58
|
+
// A test runs daemon code in-process, so it acts as the main daemon for the
|
|
59
|
+
// event hub's publish routing (a non-daemon forwards publishes over IPC to a
|
|
60
|
+
// daemon that isn't there). Default the shared process-role slot to true; a
|
|
61
|
+
// test simulating a worker overrides it. Written directly (not via
|
|
62
|
+
// `runtime/process-role.ts`) to keep the preload free of source-module imports;
|
|
63
|
+
// the slot is typed by the ambient `VellumAssistantNamespace` global (declared
|
|
64
|
+
// in `src/vellum-assistant-namespace.d.ts`), so no import is needed to touch it.
|
|
65
|
+
(globalThis.vellumAssistant ??= {}).mainDaemonProcess = true;
|
|
66
|
+
|
|
58
67
|
// --- Phase 2: install the IPC mock (no source-module imports) ---
|
|
59
68
|
|
|
60
69
|
// Mock gateway IPC so no test accidentally connects to a real gateway socket.
|