@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
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests for the ask_question branch of the `pending_question` guardian-request
|
|
3
|
+
* resolver (`guardian-request-resolvers.ts`): a request without a
|
|
4
|
+
* `callSessionId` resolves the parked in-memory `question` interaction via the
|
|
5
|
+
* shared `resolvePendingQuestion` core, mapping the decision's answer-token /
|
|
6
|
+
* free text / deny action onto a batch submission.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { afterEach, beforeEach, describe, expect, test } from "bun:test";
|
|
10
|
+
|
|
11
|
+
import type {
|
|
12
|
+
ActorContext,
|
|
13
|
+
ResolverContext,
|
|
14
|
+
ResolverDecision,
|
|
15
|
+
} from "../approvals/guardian-request-resolvers.js";
|
|
16
|
+
import { getResolver } from "../approvals/guardian-request-resolvers.js";
|
|
17
|
+
import type { GuardianRequestWire } from "../channels/gateway-guardian-requests.js";
|
|
18
|
+
import type { QuestionPromptResult } from "../permissions/question-prompter.js";
|
|
19
|
+
import * as pendingInteractions from "../runtime/pending-interactions.js";
|
|
20
|
+
|
|
21
|
+
const resolver = getResolver("pending_question");
|
|
22
|
+
|
|
23
|
+
const actor: ActorContext = {
|
|
24
|
+
actorPrincipalId: "prin-guardian",
|
|
25
|
+
actorExternalUserId: "tg-guardian",
|
|
26
|
+
channel: "telegram",
|
|
27
|
+
guardianPrincipalId: "prin-guardian",
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
function makeRequest(
|
|
31
|
+
overrides: Partial<GuardianRequestWire> = {},
|
|
32
|
+
): GuardianRequestWire {
|
|
33
|
+
return {
|
|
34
|
+
id: "req-q1",
|
|
35
|
+
kind: "pending_question",
|
|
36
|
+
sourceType: "channel",
|
|
37
|
+
sourceChannel: "telegram",
|
|
38
|
+
sourceConversationId: "conv-1",
|
|
39
|
+
requesterExternalUserId: "tg-guardian",
|
|
40
|
+
requesterChatId: "chat-1",
|
|
41
|
+
guardianExternalUserId: "tg-guardian",
|
|
42
|
+
guardianPrincipalId: "prin-guardian",
|
|
43
|
+
callSessionId: null,
|
|
44
|
+
pendingQuestionId: null,
|
|
45
|
+
questionText: "Which fruit?",
|
|
46
|
+
requestCode: "ABC123",
|
|
47
|
+
toolName: null,
|
|
48
|
+
inputDigest: null,
|
|
49
|
+
commandPreview: null,
|
|
50
|
+
riskLevel: null,
|
|
51
|
+
activityText: null,
|
|
52
|
+
executionTarget: null,
|
|
53
|
+
requesterSignals: null,
|
|
54
|
+
requestTrigger: null,
|
|
55
|
+
status: "approved",
|
|
56
|
+
answerText: null,
|
|
57
|
+
decidedByExternalUserId: null,
|
|
58
|
+
decidedByPrincipalId: null,
|
|
59
|
+
followupState: null,
|
|
60
|
+
expiresAt: null,
|
|
61
|
+
createdAt: 0,
|
|
62
|
+
updatedAt: 0,
|
|
63
|
+
...overrides,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function makeContext(
|
|
68
|
+
decision: ResolverDecision,
|
|
69
|
+
requestOverrides: Partial<GuardianRequestWire> = {},
|
|
70
|
+
): ResolverContext {
|
|
71
|
+
return { request: makeRequest(requestOverrides), decision, actor };
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Register a parked single-question interaction like QuestionPrompter does. */
|
|
75
|
+
function registerQuestion(
|
|
76
|
+
requestId: string,
|
|
77
|
+
options: string[],
|
|
78
|
+
rpcResolve: (value: unknown) => void = () => {},
|
|
79
|
+
): void {
|
|
80
|
+
pendingInteractions.register(requestId, {
|
|
81
|
+
conversationId: "conv-1",
|
|
82
|
+
kind: "question",
|
|
83
|
+
rpcResolve,
|
|
84
|
+
metadata: { orderedIds: ["q1"], optionsById: { q1: options } },
|
|
85
|
+
questionDetails: {
|
|
86
|
+
entries: [
|
|
87
|
+
{
|
|
88
|
+
id: "q1",
|
|
89
|
+
question: "Which fruit?",
|
|
90
|
+
options: options.map((id) => ({ id, label: id })),
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
beforeEach(() => pendingInteractions.clear());
|
|
98
|
+
afterEach(() => pendingInteractions.clear());
|
|
99
|
+
|
|
100
|
+
describe("pending_question resolver — ask_question branch", () => {
|
|
101
|
+
test("an answer-option token resolves the interaction with that option", async () => {
|
|
102
|
+
const resolved: QuestionPromptResult[] = [];
|
|
103
|
+
registerQuestion("req-q1", ["apple", "banana"], (v) =>
|
|
104
|
+
resolved.push(v as QuestionPromptResult),
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
const result = await resolver!.resolve(
|
|
108
|
+
makeContext({ action: "approve_once", userText: "answer_1" }),
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
expect(result).toEqual({ ok: true, applied: true });
|
|
112
|
+
expect(resolved[0]?.entries).toEqual([
|
|
113
|
+
{ questionId: "q1", decision: "option", optionId: "banana" },
|
|
114
|
+
]);
|
|
115
|
+
expect(pendingInteractions.get("req-q1")).toBeUndefined();
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test("the skip token resolves the interaction as skipped", async () => {
|
|
119
|
+
const resolved: QuestionPromptResult[] = [];
|
|
120
|
+
registerQuestion("req-q1", ["apple", "banana"], (v) =>
|
|
121
|
+
resolved.push(v as QuestionPromptResult),
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
const result = await resolver!.resolve(
|
|
125
|
+
makeContext({ action: "reject", userText: "answer_skip" }),
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
expect(result).toEqual({ ok: true, applied: true });
|
|
129
|
+
expect(resolved[0]?.entries).toEqual([
|
|
130
|
+
{ questionId: "q1", decision: "skipped" },
|
|
131
|
+
]);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test("free text resolves as a free_text answer", async () => {
|
|
135
|
+
const resolved: QuestionPromptResult[] = [];
|
|
136
|
+
registerQuestion("req-q1", ["apple", "banana"], (v) =>
|
|
137
|
+
resolved.push(v as QuestionPromptResult),
|
|
138
|
+
);
|
|
139
|
+
|
|
140
|
+
const result = await resolver!.resolve(
|
|
141
|
+
makeContext({ action: "approve_once", userText: "a ripe mango" }),
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
expect(result).toEqual({ ok: true, applied: true });
|
|
145
|
+
expect(resolved[0]?.entries).toEqual([
|
|
146
|
+
{ questionId: "q1", decision: "free_text", text: "a ripe mango" },
|
|
147
|
+
]);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
test("a deny decision with no text skips the question", async () => {
|
|
151
|
+
const resolved: QuestionPromptResult[] = [];
|
|
152
|
+
registerQuestion("req-q1", ["apple", "banana"], (v) =>
|
|
153
|
+
resolved.push(v as QuestionPromptResult),
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
const result = await resolver!.resolve(makeContext({ action: "reject" }));
|
|
157
|
+
|
|
158
|
+
expect(result).toEqual({ ok: true, applied: true });
|
|
159
|
+
expect(resolved[0]?.entries).toEqual([
|
|
160
|
+
{ questionId: "q1", decision: "skipped" },
|
|
161
|
+
]);
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
test("an out-of-range option index fails without consuming the interaction", async () => {
|
|
165
|
+
registerQuestion("req-q1", ["apple", "banana"]);
|
|
166
|
+
|
|
167
|
+
const result = await resolver!.resolve(
|
|
168
|
+
makeContext({ action: "approve_once", userText: "answer_9" }),
|
|
169
|
+
);
|
|
170
|
+
|
|
171
|
+
expect(result).toEqual({
|
|
172
|
+
ok: false,
|
|
173
|
+
reason: "question_option_index_out_of_range",
|
|
174
|
+
});
|
|
175
|
+
expect(pendingInteractions.get("req-q1")).toBeDefined();
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
test("a missing interaction reports no_pending_question_interaction", async () => {
|
|
179
|
+
const result = await resolver!.resolve(
|
|
180
|
+
makeContext({ action: "approve_once", userText: "answer_0" }),
|
|
181
|
+
);
|
|
182
|
+
|
|
183
|
+
expect(result).toEqual({
|
|
184
|
+
ok: false,
|
|
185
|
+
reason: "no_pending_question_interaction",
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
test("a multi-question interaction is refused (cards are single-question)", async () => {
|
|
190
|
+
pendingInteractions.register("req-q1", {
|
|
191
|
+
conversationId: "conv-1",
|
|
192
|
+
kind: "question",
|
|
193
|
+
rpcResolve: () => {},
|
|
194
|
+
metadata: {
|
|
195
|
+
orderedIds: ["q1", "q2"],
|
|
196
|
+
optionsById: { q1: ["a"], q2: ["b"] },
|
|
197
|
+
},
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
const result = await resolver!.resolve(
|
|
201
|
+
makeContext({ action: "approve_once", userText: "answer_0" }),
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
expect(result).toEqual({ ok: false, reason: "question_batch_not_single" });
|
|
205
|
+
expect(pendingInteractions.get("req-q1")).toBeDefined();
|
|
206
|
+
});
|
|
207
|
+
});
|
|
@@ -14,14 +14,14 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { describe, expect, test } from "bun:test";
|
|
16
16
|
|
|
17
|
-
import type {
|
|
17
|
+
import type { AssistantEventEnvelope } from "../api/index.js";
|
|
18
18
|
import {
|
|
19
19
|
AssistantEventHub,
|
|
20
20
|
assistantEventHub,
|
|
21
21
|
broadcastMessage,
|
|
22
22
|
} from "../runtime/assistant-event-hub.js";
|
|
23
23
|
|
|
24
|
-
function makeSyncChangedEvent(originClientId?: string):
|
|
24
|
+
function makeSyncChangedEvent(originClientId?: string): AssistantEventEnvelope {
|
|
25
25
|
return {
|
|
26
26
|
id: "evt_test_sync",
|
|
27
27
|
conversationId: undefined,
|
|
@@ -37,9 +37,9 @@ function makeSyncChangedEvent(originClientId?: string): AssistantEvent {
|
|
|
37
37
|
describe("AssistantEventHub — self-echo suppression (excludeClientId)", () => {
|
|
38
38
|
test("skips the named client and delivers to every other client", async () => {
|
|
39
39
|
const hub = new AssistantEventHub();
|
|
40
|
-
const receivedA:
|
|
41
|
-
const receivedB:
|
|
42
|
-
const receivedC:
|
|
40
|
+
const receivedA: AssistantEventEnvelope[] = [];
|
|
41
|
+
const receivedB: AssistantEventEnvelope[] = [];
|
|
42
|
+
const receivedC: AssistantEventEnvelope[] = [];
|
|
43
43
|
|
|
44
44
|
hub.subscribe({
|
|
45
45
|
type: "client",
|
|
@@ -82,8 +82,8 @@ describe("AssistantEventHub — self-echo suppression (excludeClientId)", () =>
|
|
|
82
82
|
|
|
83
83
|
test("delivers to every subscriber when excludeClientId is omitted", async () => {
|
|
84
84
|
const hub = new AssistantEventHub();
|
|
85
|
-
const receivedA:
|
|
86
|
-
const receivedB:
|
|
85
|
+
const receivedA: AssistantEventEnvelope[] = [];
|
|
86
|
+
const receivedB: AssistantEventEnvelope[] = [];
|
|
87
87
|
|
|
88
88
|
hub.subscribe({
|
|
89
89
|
type: "client",
|
|
@@ -112,7 +112,7 @@ describe("AssistantEventHub — self-echo suppression (excludeClientId)", () =>
|
|
|
112
112
|
|
|
113
113
|
test("excludeClientId does not match process-type subscribers", async () => {
|
|
114
114
|
const hub = new AssistantEventHub();
|
|
115
|
-
const receivedProcess:
|
|
115
|
+
const receivedProcess: AssistantEventEnvelope[] = [];
|
|
116
116
|
|
|
117
117
|
// A process subscriber sits in the same hub as a client whose id
|
|
118
118
|
// matches `excludeClientId`. It must never be suppressed because
|
|
@@ -134,8 +134,8 @@ describe("AssistantEventHub — self-echo suppression (excludeClientId)", () =>
|
|
|
134
134
|
|
|
135
135
|
test("excludeClientId composes with conversation-scoped subscribers", async () => {
|
|
136
136
|
const hub = new AssistantEventHub();
|
|
137
|
-
const receivedA:
|
|
138
|
-
const receivedB:
|
|
137
|
+
const receivedA: AssistantEventEnvelope[] = [];
|
|
138
|
+
const receivedB: AssistantEventEnvelope[] = [];
|
|
139
139
|
|
|
140
140
|
hub.subscribe({
|
|
141
141
|
type: "client",
|
|
@@ -159,7 +159,7 @@ describe("AssistantEventHub — self-echo suppression (excludeClientId)", () =>
|
|
|
159
159
|
});
|
|
160
160
|
|
|
161
161
|
// Scoped event for sess_x; both clients filter to sess_x; exclude A.
|
|
162
|
-
const event:
|
|
162
|
+
const event: AssistantEventEnvelope = {
|
|
163
163
|
id: "evt_scoped",
|
|
164
164
|
conversationId: "sess_x",
|
|
165
165
|
emittedAt: "2026-05-03T00:00:00.000Z",
|
|
@@ -179,8 +179,8 @@ describe("AssistantEventHub — self-echo suppression (excludeClientId)", () =>
|
|
|
179
179
|
|
|
180
180
|
describe("broadcastMessage — derives excludeClientId from sync_changed.originClientId", () => {
|
|
181
181
|
test("skips the originating client when originClientId is present", async () => {
|
|
182
|
-
const receivedA:
|
|
183
|
-
const receivedB:
|
|
182
|
+
const receivedA: AssistantEventEnvelope[] = [];
|
|
183
|
+
const receivedB: AssistantEventEnvelope[] = [];
|
|
184
184
|
|
|
185
185
|
const subA = assistantEventHub.subscribe({
|
|
186
186
|
type: "client",
|
|
@@ -221,8 +221,8 @@ describe("broadcastMessage — derives excludeClientId from sync_changed.originC
|
|
|
221
221
|
});
|
|
222
222
|
|
|
223
223
|
test("fans out to every client when originClientId is absent", async () => {
|
|
224
|
-
const receivedA:
|
|
225
|
-
const receivedB:
|
|
224
|
+
const receivedA: AssistantEventEnvelope[] = [];
|
|
225
|
+
const receivedB: AssistantEventEnvelope[] = [];
|
|
226
226
|
|
|
227
227
|
const subA = assistantEventHub.subscribe({
|
|
228
228
|
type: "client",
|
|
@@ -260,7 +260,7 @@ describe("broadcastMessage — derives excludeClientId from sync_changed.originC
|
|
|
260
260
|
});
|
|
261
261
|
|
|
262
262
|
test("ignores an empty-string originClientId (treats as absent)", async () => {
|
|
263
|
-
const receivedA:
|
|
263
|
+
const receivedA: AssistantEventEnvelope[] = [];
|
|
264
264
|
|
|
265
265
|
const subA = assistantEventHub.subscribe({
|
|
266
266
|
type: "client",
|
|
@@ -13,10 +13,12 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import { describe, expect, test } from "bun:test";
|
|
15
15
|
|
|
16
|
-
import type {
|
|
16
|
+
import type { AssistantEventEnvelope } from "../api/index.js";
|
|
17
17
|
import { AssistantEventHub } from "../runtime/assistant-event-hub.js";
|
|
18
18
|
|
|
19
|
-
function makeEvent(
|
|
19
|
+
function makeEvent(
|
|
20
|
+
overrides: Partial<AssistantEventEnvelope> = {},
|
|
21
|
+
): AssistantEventEnvelope {
|
|
20
22
|
return {
|
|
21
23
|
id: "evt_test",
|
|
22
24
|
conversationId: "sess_web",
|
|
@@ -35,8 +37,8 @@ function makeEvent(overrides: Partial<AssistantEvent> = {}): AssistantEvent {
|
|
|
35
37
|
describe("AssistantEventHub — targeted delivery (targetClientId)", () => {
|
|
36
38
|
test("delivers only to the named client, bypassing conversation filter", async () => {
|
|
37
39
|
const hub = new AssistantEventHub();
|
|
38
|
-
const receivedA:
|
|
39
|
-
const receivedB:
|
|
40
|
+
const receivedA: AssistantEventEnvelope[] = [];
|
|
41
|
+
const receivedB: AssistantEventEnvelope[] = [];
|
|
40
42
|
|
|
41
43
|
// client-a is subscribed to "sess_macos" — different from the event's "sess_web"
|
|
42
44
|
hub.subscribe({
|
|
@@ -75,8 +77,8 @@ describe("AssistantEventHub — targeted delivery (targetClientId)", () => {
|
|
|
75
77
|
|
|
76
78
|
test("does not deliver to a client with a different clientId", async () => {
|
|
77
79
|
const hub = new AssistantEventHub();
|
|
78
|
-
const receivedA:
|
|
79
|
-
const receivedB:
|
|
80
|
+
const receivedA: AssistantEventEnvelope[] = [];
|
|
81
|
+
const receivedB: AssistantEventEnvelope[] = [];
|
|
80
82
|
|
|
81
83
|
hub.subscribe({
|
|
82
84
|
type: "client",
|
|
@@ -106,7 +108,7 @@ describe("AssistantEventHub — targeted delivery (targetClientId)", () => {
|
|
|
106
108
|
|
|
107
109
|
test("targeted delivery with wrong capability does not deliver", async () => {
|
|
108
110
|
const hub = new AssistantEventHub();
|
|
109
|
-
const receivedA:
|
|
111
|
+
const receivedA: AssistantEventEnvelope[] = [];
|
|
110
112
|
|
|
111
113
|
// client-a only has host_file capability, NOT host_bash
|
|
112
114
|
hub.subscribe({
|
|
@@ -130,7 +132,7 @@ describe("AssistantEventHub — targeted delivery (targetClientId)", () => {
|
|
|
130
132
|
|
|
131
133
|
test("targeted delivery with matching capability delivers", async () => {
|
|
132
134
|
const hub = new AssistantEventHub();
|
|
133
|
-
const receivedA:
|
|
135
|
+
const receivedA: AssistantEventEnvelope[] = [];
|
|
134
136
|
|
|
135
137
|
hub.subscribe({
|
|
136
138
|
type: "client",
|
|
@@ -152,7 +154,7 @@ describe("AssistantEventHub — targeted delivery (targetClientId)", () => {
|
|
|
152
154
|
|
|
153
155
|
test("process-type subscriber is never matched by targetClientId", async () => {
|
|
154
156
|
const hub = new AssistantEventHub();
|
|
155
|
-
const received:
|
|
157
|
+
const received: AssistantEventEnvelope[] = [];
|
|
156
158
|
|
|
157
159
|
hub.subscribe({
|
|
158
160
|
type: "process",
|
|
@@ -173,8 +175,8 @@ describe("AssistantEventHub — targeted delivery (targetClientId)", () => {
|
|
|
173
175
|
describe("AssistantEventHub — untargeted capability targeting is unchanged", () => {
|
|
174
176
|
test("targetCapability without targetClientId still applies conversation scoping", async () => {
|
|
175
177
|
const hub = new AssistantEventHub();
|
|
176
|
-
const receivedA:
|
|
177
|
-
const receivedB:
|
|
178
|
+
const receivedA: AssistantEventEnvelope[] = [];
|
|
179
|
+
const receivedB: AssistantEventEnvelope[] = [];
|
|
178
180
|
|
|
179
181
|
hub.subscribe({
|
|
180
182
|
type: "client",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, test } from "bun:test";
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type { AssistantEventEnvelope } from "../api/index.js";
|
|
4
4
|
import {
|
|
5
5
|
AssistantEventHub,
|
|
6
6
|
broadcastMessage,
|
|
@@ -12,7 +12,9 @@ import {
|
|
|
12
12
|
} from "../runtime/assistant-stream-state.js";
|
|
13
13
|
import * as pendingInteractions from "../runtime/pending-interactions.js";
|
|
14
14
|
|
|
15
|
-
function makeEvent(
|
|
15
|
+
function makeEvent(
|
|
16
|
+
overrides: Partial<AssistantEventEnvelope> = {},
|
|
17
|
+
): AssistantEventEnvelope {
|
|
16
18
|
return {
|
|
17
19
|
id: "evt_test",
|
|
18
20
|
conversationId: "sess_1",
|
|
@@ -31,7 +33,7 @@ function makeEvent(overrides: Partial<AssistantEvent> = {}): AssistantEvent {
|
|
|
31
33
|
describe("AssistantEventHub — fanout", () => {
|
|
32
34
|
test("delivers event to a single matching subscriber", async () => {
|
|
33
35
|
const hub = new AssistantEventHub();
|
|
34
|
-
const received:
|
|
36
|
+
const received: AssistantEventEnvelope[] = [];
|
|
35
37
|
|
|
36
38
|
hub.subscribe({
|
|
37
39
|
type: "process",
|
|
@@ -75,8 +77,8 @@ describe("AssistantEventHub — fanout", () => {
|
|
|
75
77
|
|
|
76
78
|
test("conversationId filter further restricts delivery", async () => {
|
|
77
79
|
const hub = new AssistantEventHub();
|
|
78
|
-
const receivedA:
|
|
79
|
-
const receivedB:
|
|
80
|
+
const receivedA: AssistantEventEnvelope[] = [];
|
|
81
|
+
const receivedB: AssistantEventEnvelope[] = [];
|
|
80
82
|
|
|
81
83
|
hub.subscribe({
|
|
82
84
|
type: "process",
|
|
@@ -101,7 +103,7 @@ describe("AssistantEventHub — fanout", () => {
|
|
|
101
103
|
|
|
102
104
|
test("subscriber without conversationId filter receives all conversations", async () => {
|
|
103
105
|
const hub = new AssistantEventHub();
|
|
104
|
-
const received:
|
|
106
|
+
const received: AssistantEventEnvelope[] = [];
|
|
105
107
|
|
|
106
108
|
hub.subscribe({
|
|
107
109
|
type: "process",
|
|
@@ -159,7 +161,7 @@ describe("AssistantEventHub — fanout", () => {
|
|
|
159
161
|
describe("AssistantEventHub — unsubscribe cleanup", () => {
|
|
160
162
|
test("dispose stops event delivery", async () => {
|
|
161
163
|
const hub = new AssistantEventHub();
|
|
162
|
-
const received:
|
|
164
|
+
const received: AssistantEventEnvelope[] = [];
|
|
163
165
|
|
|
164
166
|
const s = hub.subscribe({
|
|
165
167
|
type: "process",
|
|
@@ -234,8 +236,8 @@ describe("AssistantEventHub — unsubscribe cleanup", () => {
|
|
|
234
236
|
|
|
235
237
|
test("disposing one subscription does not affect others", async () => {
|
|
236
238
|
const hub = new AssistantEventHub();
|
|
237
|
-
const received1:
|
|
238
|
-
const received2:
|
|
239
|
+
const received1: AssistantEventEnvelope[] = [];
|
|
240
|
+
const received2: AssistantEventEnvelope[] = [];
|
|
239
241
|
|
|
240
242
|
const s1 = hub.subscribe({
|
|
241
243
|
type: "process",
|
|
@@ -341,7 +343,7 @@ describe("AssistantEventHub — exception isolation", () => {
|
|
|
341
343
|
describe("AssistantEventHub — re-entrancy / snapshot isolation", () => {
|
|
342
344
|
test("subscriber added during publish does not receive the in-flight event", async () => {
|
|
343
345
|
const hub = new AssistantEventHub();
|
|
344
|
-
const lateReceived:
|
|
346
|
+
const lateReceived: AssistantEventEnvelope[] = [];
|
|
345
347
|
|
|
346
348
|
hub.subscribe({
|
|
347
349
|
type: "process",
|
|
@@ -363,7 +365,7 @@ describe("AssistantEventHub — re-entrancy / snapshot isolation", () => {
|
|
|
363
365
|
|
|
364
366
|
test("subscriber that disposes itself mid-publish does not affect remaining subscribers", async () => {
|
|
365
367
|
const hub = new AssistantEventHub();
|
|
366
|
-
const received:
|
|
368
|
+
const received: AssistantEventEnvelope[] = [];
|
|
367
369
|
let s: ReturnType<typeof hub.subscribe>;
|
|
368
370
|
|
|
369
371
|
// eslint-disable-next-line prefer-const
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
2
|
|
|
3
|
-
import type {
|
|
3
|
+
import type { AssistantEventEnvelope } from "../api/index.js";
|
|
4
4
|
import {
|
|
5
5
|
formatSseFrame,
|
|
6
6
|
formatSseHeartbeat,
|
|
@@ -8,9 +8,9 @@ import {
|
|
|
8
8
|
|
|
9
9
|
// ── Type / shape tests ────────────────────────────────────────────────────────
|
|
10
10
|
|
|
11
|
-
describe("
|
|
11
|
+
describe("AssistantEventEnvelope shape", () => {
|
|
12
12
|
test("accepts a minimal valid event", () => {
|
|
13
|
-
const event:
|
|
13
|
+
const event: AssistantEventEnvelope = {
|
|
14
14
|
id: "evt_001",
|
|
15
15
|
emittedAt: "2026-02-18T21:20:00.000Z",
|
|
16
16
|
message: {
|
|
@@ -27,7 +27,7 @@ describe("AssistantEvent shape", () => {
|
|
|
27
27
|
});
|
|
28
28
|
|
|
29
29
|
test("accepts a full event with conversationId", () => {
|
|
30
|
-
const event:
|
|
30
|
+
const event: AssistantEventEnvelope = {
|
|
31
31
|
id: "evt_002",
|
|
32
32
|
conversationId: "conv_456",
|
|
33
33
|
emittedAt: "2026-02-18T21:20:00.000Z",
|
|
@@ -45,7 +45,7 @@ describe("AssistantEvent shape", () => {
|
|
|
45
45
|
// ── SSE framing tests ─────────────────────────────────────────────────────────
|
|
46
46
|
|
|
47
47
|
describe("formatSseFrame", () => {
|
|
48
|
-
const baseEvent:
|
|
48
|
+
const baseEvent: AssistantEventEnvelope = {
|
|
49
49
|
id: "evt_003",
|
|
50
50
|
conversationId: "sess_xyz",
|
|
51
51
|
emittedAt: "2026-02-18T00:00:00.000Z",
|
|
@@ -73,7 +73,7 @@ describe("formatSseFrame", () => {
|
|
|
73
73
|
const dataLine = frame.split("\n").find((l) => l.startsWith("data: "))!;
|
|
74
74
|
const parsed = JSON.parse(
|
|
75
75
|
dataLine.slice("data: ".length),
|
|
76
|
-
) as
|
|
76
|
+
) as AssistantEventEnvelope;
|
|
77
77
|
|
|
78
78
|
expect(parsed.id).toBe(baseEvent.id);
|
|
79
79
|
expect(parsed.conversationId).toBe(baseEvent.conversationId);
|
|
@@ -82,13 +82,16 @@ describe("formatSseFrame", () => {
|
|
|
82
82
|
});
|
|
83
83
|
|
|
84
84
|
test("id line uses the event id verbatim", () => {
|
|
85
|
-
const event:
|
|
85
|
+
const event: AssistantEventEnvelope = {
|
|
86
|
+
...baseEvent,
|
|
87
|
+
id: "unique-evt-id-xyz",
|
|
88
|
+
};
|
|
86
89
|
const frame = formatSseFrame(event);
|
|
87
90
|
expect(frame).toContain("id: unique-evt-id-xyz\n");
|
|
88
91
|
});
|
|
89
92
|
|
|
90
93
|
test("strips newline characters from event.id to prevent SSE frame injection", () => {
|
|
91
|
-
const event:
|
|
94
|
+
const event: AssistantEventEnvelope = {
|
|
92
95
|
...baseEvent,
|
|
93
96
|
id: 'foo\ndata: {"injected":true}',
|
|
94
97
|
};
|
|
@@ -113,7 +116,7 @@ describe("formatSseFrame", () => {
|
|
|
113
116
|
});
|
|
114
117
|
|
|
115
118
|
test("seq lands in the JSON payload (envelope) when set, never in SSE id", () => {
|
|
116
|
-
const event:
|
|
119
|
+
const event: AssistantEventEnvelope = {
|
|
117
120
|
...baseEvent,
|
|
118
121
|
id: "uuid-event-id",
|
|
119
122
|
seq: 42,
|
|
@@ -7,7 +7,7 @@ import { describe, expect, test } from "bun:test";
|
|
|
7
7
|
* Guard tests for assistant feature flags.
|
|
8
8
|
*
|
|
9
9
|
* 1. Key format validation: ensure production code uses the canonical
|
|
10
|
-
* simple kebab-case format (e.g., "browser", "
|
|
10
|
+
* simple kebab-case format (e.g., "browser", "contacts"), not the
|
|
11
11
|
* legacy `skills.<id>.enabled` format.
|
|
12
12
|
*
|
|
13
13
|
* 2. Declaration coverage: ensure all assistant-scope flag keys in the
|
|
@@ -123,7 +123,7 @@ describe("assistant feature flag guard", () => {
|
|
|
123
123
|
if (violations.length > 0) {
|
|
124
124
|
const message = [
|
|
125
125
|
"Found production files using the legacy `skills.<id>.enabled` key format.",
|
|
126
|
-
'New code must use the canonical simple kebab-case format (e.g., "browser", "
|
|
126
|
+
'New code must use the canonical simple kebab-case format (e.g., "browser", "contacts").',
|
|
127
127
|
'See AGENTS.md "Assistant Feature Flags" for the convention.',
|
|
128
128
|
"",
|
|
129
129
|
"Violations:",
|
|
@@ -153,7 +153,7 @@ describe("assistant feature flag guard", () => {
|
|
|
153
153
|
if (violations.length > 0) {
|
|
154
154
|
const message = [
|
|
155
155
|
"Found assistant-scope keys in the unified registry that do not match the canonical format.",
|
|
156
|
-
'Expected format: simple kebab-case (e.g., "browser", "
|
|
156
|
+
'Expected format: simple kebab-case (e.g., "browser", "contacts")',
|
|
157
157
|
"",
|
|
158
158
|
"Violations:",
|
|
159
159
|
...violations.map((k) => ` - ${k}`),
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Guard tests for assistant feature flag conventions:
|
|
3
3
|
*
|
|
4
4
|
* 1. Key format: all feature flag keys used in production code must use
|
|
5
|
-
* simple kebab-case format (e.g., "browser", "
|
|
5
|
+
* simple kebab-case format (e.g., "browser", "contacts"). Any remaining
|
|
6
6
|
* `skills.<id>.enabled` usage outside of migration/backward-compat code is
|
|
7
7
|
* flagged — including template literal forms like `skills.${skillId}.enabled`.
|
|
8
8
|
*
|
|
@@ -312,64 +312,6 @@ describe("assistant ID boundary", () => {
|
|
|
312
312
|
// surfaces invites callers to pass external IDs into daemon scoping.
|
|
313
313
|
// -------------------------------------------------------------------------
|
|
314
314
|
|
|
315
|
-
test("message contract types do not contain assistantId for guardian requests", () => {
|
|
316
|
-
const contractPath = join(
|
|
317
|
-
import.meta.dir,
|
|
318
|
-
"..",
|
|
319
|
-
"daemon",
|
|
320
|
-
"message-types",
|
|
321
|
-
"integrations.ts",
|
|
322
|
-
);
|
|
323
|
-
const content = readFileSync(contractPath, "utf-8");
|
|
324
|
-
|
|
325
|
-
// Extract the interface blocks for the request types and verify
|
|
326
|
-
// none of them declare an assistantId property.
|
|
327
|
-
const requestTypeNames = ["ChannelVerificationSessionRequest"];
|
|
328
|
-
|
|
329
|
-
for (const typeName of requestTypeNames) {
|
|
330
|
-
// Find the interface/type block — match from the type name to the next
|
|
331
|
-
// closing brace at the same indentation level. We use a simple heuristic:
|
|
332
|
-
// find the line declaring the type, then scan forward to the closing '}'.
|
|
333
|
-
const typeIndex = content.indexOf(typeName);
|
|
334
|
-
expect(
|
|
335
|
-
typeIndex,
|
|
336
|
-
`Expected to find ${typeName} in message contract`,
|
|
337
|
-
).toBeGreaterThan(-1);
|
|
338
|
-
|
|
339
|
-
// Extract from the type declaration to the next '}' line
|
|
340
|
-
const blockStart = content.indexOf("{", typeIndex);
|
|
341
|
-
if (blockStart === -1) continue;
|
|
342
|
-
let braceDepth = 0;
|
|
343
|
-
let blockEnd = blockStart;
|
|
344
|
-
for (let i = blockStart; i < content.length; i++) {
|
|
345
|
-
if (content[i] === "{") braceDepth++;
|
|
346
|
-
if (content[i] === "}") braceDepth--;
|
|
347
|
-
if (braceDepth === 0) {
|
|
348
|
-
blockEnd = i + 1;
|
|
349
|
-
break;
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
const block = content.slice(blockStart, blockEnd);
|
|
353
|
-
|
|
354
|
-
// The block should not contain an assistantId property declaration
|
|
355
|
-
// (matches "assistantId?" or "assistantId:" on a non-comment line)
|
|
356
|
-
const lines = block.split("\n");
|
|
357
|
-
for (const line of lines) {
|
|
358
|
-
const trimmed = line.trim();
|
|
359
|
-
if (
|
|
360
|
-
trimmed.startsWith("//") ||
|
|
361
|
-
trimmed.startsWith("*") ||
|
|
362
|
-
trimmed.startsWith("/*")
|
|
363
|
-
)
|
|
364
|
-
continue;
|
|
365
|
-
expect(
|
|
366
|
-
/\bassistantId\s*[?:]/.test(trimmed),
|
|
367
|
-
`${typeName} must not declare an assistantId property. Found: "${trimmed}"`,
|
|
368
|
-
).toBe(false);
|
|
369
|
-
}
|
|
370
|
-
}
|
|
371
|
-
});
|
|
372
|
-
|
|
373
315
|
test("guardian outbound param interfaces do not contain assistantId", () => {
|
|
374
316
|
const actionsPath = join(
|
|
375
317
|
import.meta.dir,
|