@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
|
@@ -75,9 +75,19 @@ const GuardianQuestionPayloadBaseSchema = z.object({
|
|
|
75
75
|
export const PendingQuestionPayloadSchema =
|
|
76
76
|
GuardianQuestionPayloadBaseSchema.extend({
|
|
77
77
|
requestKind: z.literal("pending_question"),
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
/** Present only for voice-call questions; absent for ask_question prompts. */
|
|
79
|
+
callSessionId: z.string().min(1).optional(),
|
|
80
|
+
activeGuardianRequestCount: z.number().optional(),
|
|
80
81
|
toolName: z.string().optional(),
|
|
82
|
+
/**
|
|
83
|
+
* Structured answer options for an ask_question prompt (2–4 entries).
|
|
84
|
+
* When present, the broadcaster renders them as tappable option actions
|
|
85
|
+
* (see {@link buildQuestionOptionActionId}); absent payloads render as
|
|
86
|
+
* plain text with request-code reply instructions.
|
|
87
|
+
*/
|
|
88
|
+
options: z
|
|
89
|
+
.array(z.object({ id: z.string().min(1), label: z.string().min(1) }))
|
|
90
|
+
.optional(),
|
|
81
91
|
});
|
|
82
92
|
|
|
83
93
|
/**
|
|
@@ -221,6 +231,51 @@ export function buildToolApprovalSourceView(
|
|
|
221
231
|
};
|
|
222
232
|
}
|
|
223
233
|
|
|
234
|
+
// ── Answer-option action tokens ─────────────────────────────────────────
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Action-id scheme for answer-mode option buttons on a `pending_question`
|
|
238
|
+
* card. The broadcaster builds card actions with these ids (so every channel
|
|
239
|
+
* adapter renders them without knowing they're question options), the reply
|
|
240
|
+
* router recognizes a tapped id as an answer selection rather than an
|
|
241
|
+
* approval action, and the question resolver maps the index back to the
|
|
242
|
+
* pending interaction's option. Index-based (not the raw option id) so the
|
|
243
|
+
* channel callback stays small and the LLM-supplied option id never rides
|
|
244
|
+
* the wire.
|
|
245
|
+
*/
|
|
246
|
+
export const QUESTION_SKIP_ACTION_ID = "answer_skip";
|
|
247
|
+
|
|
248
|
+
/** Action id for the option at `index` on a question card. */
|
|
249
|
+
export function buildQuestionOptionActionId(index: number): string {
|
|
250
|
+
return `answer_${index}`;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export type QuestionAnswerSelection =
|
|
254
|
+
| { kind: "option"; index: number }
|
|
255
|
+
| { kind: "skip" };
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Parse an action token from a question card. Returns `null` for anything
|
|
259
|
+
* that is not an answer-option token (including ordinary approval actions),
|
|
260
|
+
* so callers can fall through to approval handling.
|
|
261
|
+
*/
|
|
262
|
+
export function parseQuestionAnswerActionId(
|
|
263
|
+
token: string,
|
|
264
|
+
): QuestionAnswerSelection | null {
|
|
265
|
+
if (token === QUESTION_SKIP_ACTION_ID) {
|
|
266
|
+
return { kind: "skip" };
|
|
267
|
+
}
|
|
268
|
+
const match = /^answer_(\d+)$/.exec(token);
|
|
269
|
+
if (!match) {
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
const index = Number(match[1]);
|
|
273
|
+
if (!Number.isInteger(index) || index < 0) {
|
|
274
|
+
return null;
|
|
275
|
+
}
|
|
276
|
+
return { kind: "option", index };
|
|
277
|
+
}
|
|
278
|
+
|
|
224
279
|
interface GuardianRequestModeInput {
|
|
225
280
|
kind: unknown;
|
|
226
281
|
toolName?: unknown;
|
|
@@ -159,6 +159,7 @@ const EVENT_CATEGORY_MAP: Record<string, FeedItemCategory> = {
|
|
|
159
159
|
"guardian.question": "security",
|
|
160
160
|
"guardian.channel_activation": "security",
|
|
161
161
|
"ingress.access_request": "security",
|
|
162
|
+
"telegram.webhook_health_alert": "system",
|
|
162
163
|
};
|
|
163
164
|
|
|
164
165
|
function deriveCategory(signal: NotificationSignal): FeedItemCategory {
|
|
@@ -269,6 +270,9 @@ const NOTEWORTHY_EVENT_NAMES: ReadonlySet<string> = new Set([
|
|
|
269
270
|
"guardian.channel_activation",
|
|
270
271
|
"ingress.access_request",
|
|
271
272
|
"credential.health_alert",
|
|
273
|
+
// A dark messaging channel is inbox-worthy: the guardian may be waiting on
|
|
274
|
+
// replies that are silently queueing at Telegram.
|
|
275
|
+
"telegram.webhook_health_alert",
|
|
272
276
|
]);
|
|
273
277
|
|
|
274
278
|
function deriveNoteworthy(signal: NotificationSignal): boolean {
|
|
@@ -25,6 +25,7 @@ export const NOTIFICATION_SOURCE_CHANNELS = [
|
|
|
25
25
|
{ id: "email", description: "Email channel" },
|
|
26
26
|
{ id: "platform", description: "Platform-managed channel" },
|
|
27
27
|
{ id: "a2a", description: "Agent-to-agent protocol channel" },
|
|
28
|
+
{ id: "discord", description: "Discord channel" },
|
|
28
29
|
{ id: "scheduler", description: "Scheduled task runner (reminders, cron)" },
|
|
29
30
|
{ id: "watcher", description: "File/event watcher subsystem" },
|
|
30
31
|
] as const;
|
|
@@ -82,10 +83,6 @@ export const NOTIFICATION_SOURCE_EVENT_NAMES = [
|
|
|
82
83
|
id: "ingress.trusted_contact.guardian_decision",
|
|
83
84
|
description: "Guardian decided on trusted contact request",
|
|
84
85
|
},
|
|
85
|
-
{
|
|
86
|
-
id: "ingress.trusted_contact.denied",
|
|
87
|
-
description: "Trusted contact request denied",
|
|
88
|
-
},
|
|
89
86
|
{
|
|
90
87
|
id: "ingress.trusted_contact.verification_sent",
|
|
91
88
|
description: "Verification sent to trusted contact",
|
|
@@ -125,6 +122,11 @@ export const NOTIFICATION_SOURCE_EVENT_NAMES = [
|
|
|
125
122
|
description:
|
|
126
123
|
"OAuth credential health issue detected (expired, revoked, missing scopes)",
|
|
127
124
|
},
|
|
125
|
+
{
|
|
126
|
+
id: "telegram.webhook_health_alert",
|
|
127
|
+
description:
|
|
128
|
+
"Telegram webhook is not delivering (unregistered, or failing per getWebhookInfo)",
|
|
129
|
+
},
|
|
128
130
|
] as const;
|
|
129
131
|
|
|
130
132
|
export type NotificationSourceEventName =
|
|
@@ -31,10 +31,9 @@ const TrustedContactIdentitySchema = z.object({
|
|
|
31
31
|
});
|
|
32
32
|
|
|
33
33
|
/**
|
|
34
|
-
* Payload for `ingress.trusted_contact.guardian_decision`
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* emits `guardian_decision` with `decision: "approved"` (identical shape).
|
|
34
|
+
* Payload for `ingress.trusted_contact.guardian_decision` — the guardian's
|
|
35
|
+
* verdict on an access request. `decision` distinguishes the deny path from
|
|
36
|
+
* an approve (identical shape).
|
|
38
37
|
*/
|
|
39
38
|
export const TrustedContactDecisionPayloadSchema =
|
|
40
39
|
TrustedContactIdentitySchema.extend({
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared vellum-card conversation pin for guardian-request producers.
|
|
3
|
+
*
|
|
4
|
+
* Guardian cards (access requests, tool grants, tool approvals, questions)
|
|
5
|
+
* that know their originating conversation pass this affinity fragment to
|
|
6
|
+
* `emitNotificationSignal` so the in-app (vellum) card lands inside that
|
|
7
|
+
* conversation instead of one the decision engine picks. The metadata mirrors
|
|
8
|
+
* the target's `source` because `pairDeliveryWithConversation` reuses a
|
|
9
|
+
* conversation only when its source matches the signal's (inbound
|
|
10
|
+
* conversations default to "user"); a stale/missing target falls back to a
|
|
11
|
+
* fresh conversation via the same pairing path.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { getConversation } from "../persistence/conversation-crud.js";
|
|
15
|
+
|
|
16
|
+
export interface VellumCardAffinity {
|
|
17
|
+
conversationAffinityHint: { vellum: string };
|
|
18
|
+
conversationMetadata: { source: string };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Build the emit-signal affinity fragment pinning the vellum card to
|
|
23
|
+
* `destinationConversationId`, or `undefined` when the producer has no
|
|
24
|
+
* originating conversation (callers spread the result:
|
|
25
|
+
* `...(buildVellumCardAffinity(id) ?? {})`).
|
|
26
|
+
*/
|
|
27
|
+
export function buildVellumCardAffinity(
|
|
28
|
+
destinationConversationId: string | undefined,
|
|
29
|
+
): VellumCardAffinity | undefined {
|
|
30
|
+
if (!destinationConversationId) {
|
|
31
|
+
return undefined;
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
conversationAffinityHint: { vellum: destinationConversationId },
|
|
35
|
+
conversationMetadata: {
|
|
36
|
+
source: getConversation(destinationConversationId)?.source ?? "user",
|
|
37
|
+
},
|
|
38
|
+
};
|
|
39
|
+
}
|
package/src/oauth/AGENTS.md
CHANGED
|
@@ -39,7 +39,7 @@ The `logoUrl` field in `seed-providers.ts` is the source of truth for a provider
|
|
|
39
39
|
|
|
40
40
|
For brands Simple Icons doesn't host (e.g. Salesforce, which Simple Icons removed for trademark reasons), use the `glincker/thesvg` source via jsDelivr — `https://cdn.jsdelivr.net/gh/glincker/thesvg@main/public/icons/<key>/default.svg`. The recognised `logoUrl` prefixes are enforced by `oauth-provider-seed-logos.test.ts`; if you need a third source, extend that allowlist.
|
|
41
41
|
|
|
42
|
-
### 5. Secret patterns (if applicable) —
|
|
42
|
+
### 5. Secret patterns (if applicable) — `packages/service-contracts/src/secret-detection.ts`
|
|
43
43
|
|
|
44
44
|
If the provider issues API keys with a recognizable prefix (e.g. `acme_sk_`), add a `PREFIX_PATTERNS` entry. OAuth-only services with opaque access tokens do not need one. See `../security/AGENTS.md` for details.
|
|
45
45
|
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
collapseChannelThresholdForContact,
|
|
5
|
+
effectiveChannelCellThreshold,
|
|
6
|
+
} from "./channel-permission-query.js";
|
|
7
|
+
|
|
8
|
+
describe("collapseChannelThresholdForContact", () => {
|
|
9
|
+
test.each([
|
|
10
|
+
["none", "none"],
|
|
11
|
+
["low", "low"],
|
|
12
|
+
["medium", "low"],
|
|
13
|
+
["high", "low"],
|
|
14
|
+
] as const)("%s collapses to %s", (input, expected) => {
|
|
15
|
+
expect(collapseChannelThresholdForContact(input)).toBe(expected);
|
|
16
|
+
});
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
describe("effectiveChannelCellThreshold", () => {
|
|
20
|
+
const resolved = (threshold: "none" | "low" | "medium" | "high") => ({
|
|
21
|
+
ok: true as const,
|
|
22
|
+
resolved: { threshold },
|
|
23
|
+
});
|
|
24
|
+
const noCell = { ok: true as const, resolved: null };
|
|
25
|
+
const failed = { ok: false as const };
|
|
26
|
+
|
|
27
|
+
test("a transport failure authorizes nothing, for every contact type", () => {
|
|
28
|
+
for (const contactType of [
|
|
29
|
+
"guardian",
|
|
30
|
+
"trusted_contact",
|
|
31
|
+
"unverified_contact",
|
|
32
|
+
"unknown",
|
|
33
|
+
] as const) {
|
|
34
|
+
expect(
|
|
35
|
+
effectiveChannelCellThreshold(failed, contactType, "low"),
|
|
36
|
+
).toBeUndefined();
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test("a contact's resolved cell is collapsed", () => {
|
|
41
|
+
expect(
|
|
42
|
+
effectiveChannelCellThreshold(resolved("high"), "trusted_contact", "low"),
|
|
43
|
+
).toBe("low");
|
|
44
|
+
expect(
|
|
45
|
+
effectiveChannelCellThreshold(resolved("none"), "trusted_contact", "low"),
|
|
46
|
+
).toBe("none");
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
test("a contact with no cell gets the caller-derived room default", () => {
|
|
50
|
+
expect(
|
|
51
|
+
effectiveChannelCellThreshold(noCell, "trusted_contact", "low"),
|
|
52
|
+
).toBe("low");
|
|
53
|
+
expect(
|
|
54
|
+
effectiveChannelCellThreshold(noCell, "trusted_contact", "none"),
|
|
55
|
+
).toBe("none");
|
|
56
|
+
expect(
|
|
57
|
+
effectiveChannelCellThreshold(noCell, "trusted_contact", undefined),
|
|
58
|
+
).toBeUndefined();
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
test("guardian queries pass through raw and ignore the room default", () => {
|
|
62
|
+
expect(
|
|
63
|
+
effectiveChannelCellThreshold(resolved("high"), "guardian", "low"),
|
|
64
|
+
).toBe("high");
|
|
65
|
+
expect(
|
|
66
|
+
effectiveChannelCellThreshold(noCell, "guardian", "low"),
|
|
67
|
+
).toBeUndefined();
|
|
68
|
+
});
|
|
69
|
+
});
|
|
@@ -13,10 +13,25 @@ import {
|
|
|
13
13
|
isChannelConversationType,
|
|
14
14
|
isTrustClass,
|
|
15
15
|
type ResolveChannelPermissionRequest,
|
|
16
|
+
type ResolvedChannelPermission,
|
|
17
|
+
type RiskThreshold,
|
|
16
18
|
} from "@vellumai/gateway-client";
|
|
17
19
|
|
|
18
20
|
import type { PolicyContext } from "./types.js";
|
|
19
21
|
|
|
22
|
+
/**
|
|
23
|
+
* The fields a cell query is derived from — a subset of {@link PolicyContext}
|
|
24
|
+
* so a caller holding only a turn's channel coordinates (the sensitive-tool
|
|
25
|
+
* gate, which runs before a policy context exists) can build the same query.
|
|
26
|
+
*/
|
|
27
|
+
export type ChannelPermissionCoordinates = Pick<
|
|
28
|
+
PolicyContext,
|
|
29
|
+
| "sourceChannel"
|
|
30
|
+
| "trustClass"
|
|
31
|
+
| "channelConversationType"
|
|
32
|
+
| "channelExternalId"
|
|
33
|
+
>;
|
|
34
|
+
|
|
20
35
|
/**
|
|
21
36
|
* Build the permission-matrix cell query for a permission decision: the
|
|
22
37
|
* channel coordinates of the turn plus the actor's contact-type. Returns
|
|
@@ -26,7 +41,7 @@ import type { PolicyContext } from "./types.js";
|
|
|
26
41
|
* from the conversation override / global defaults as before.
|
|
27
42
|
*/
|
|
28
43
|
export function buildChannelPermissionCellQuery(
|
|
29
|
-
policyContext?:
|
|
44
|
+
policyContext?: ChannelPermissionCoordinates,
|
|
30
45
|
): ResolveChannelPermissionRequest | undefined {
|
|
31
46
|
const adapter = policyContext?.sourceChannel;
|
|
32
47
|
const trustClass = policyContext?.trustClass;
|
|
@@ -44,3 +59,60 @@ export function buildChannelPermissionCellQuery(
|
|
|
44
59
|
contactType: trustClass,
|
|
45
60
|
};
|
|
46
61
|
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Collapse a threshold to the two levels a channel distinguishes for
|
|
65
|
+
* non-guardian contact types: `none` is itself, everything else is `low`.
|
|
66
|
+
* Applied to stored cells and to the global default a cell-less room
|
|
67
|
+
* inherits alike; the picker applies the same collapse for display (web
|
|
68
|
+
* `channelTierBehavesAs`), so a room can never behave wider than the level
|
|
69
|
+
* displayed for it.
|
|
70
|
+
*/
|
|
71
|
+
export function collapseChannelThresholdForContact(
|
|
72
|
+
threshold: RiskThreshold,
|
|
73
|
+
): RiskThreshold {
|
|
74
|
+
return threshold === "none" ? "none" : "low";
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* The threshold a cell resolution actually authorizes for a contact type.
|
|
79
|
+
* The single rule every cell consumer applies — the sensitive-tool gate,
|
|
80
|
+
* the threshold cascade, and the pre-prompt refresh — kept in this leaf
|
|
81
|
+
* module so tests that stub the IPC lookup still exercise it.
|
|
82
|
+
*
|
|
83
|
+
* For non-guardian contact types, a resolved cell authorizes its collapsed
|
|
84
|
+
* threshold ({@link collapseChannelThresholdForContact}), and a successful
|
|
85
|
+
* walk with no cell at any level authorizes `noCellDefault` — the room
|
|
86
|
+
* default the caller derives from the owner's global setting, already
|
|
87
|
+
* collapsed. Callers that cannot derive one pass `undefined`, which keeps
|
|
88
|
+
* the caller's fail-safe path in charge.
|
|
89
|
+
*
|
|
90
|
+
* Guardian queries pass through untouched — a resolved cell keeps its raw
|
|
91
|
+
* threshold and no-cell returns `undefined` (fall through to the global
|
|
92
|
+
* thresholds): the channel setting governs other people in the room, never
|
|
93
|
+
* the guardian's own lane.
|
|
94
|
+
*
|
|
95
|
+
* A transport failure (`ok: false`) is `undefined`: an unreachable gateway
|
|
96
|
+
* must never widen what a channel actor may do.
|
|
97
|
+
*/
|
|
98
|
+
export function effectiveChannelCellThreshold(
|
|
99
|
+
cell:
|
|
100
|
+
| {
|
|
101
|
+
ok: true;
|
|
102
|
+
resolved: Pick<ResolvedChannelPermission, "threshold"> | null;
|
|
103
|
+
}
|
|
104
|
+
| { ok: false },
|
|
105
|
+
contactType: ResolveChannelPermissionRequest["contactType"],
|
|
106
|
+
noCellDefault: RiskThreshold | undefined,
|
|
107
|
+
): RiskThreshold | undefined {
|
|
108
|
+
if (!cell.ok) {
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
if (contactType === "guardian") {
|
|
112
|
+
return cell.resolved?.threshold;
|
|
113
|
+
}
|
|
114
|
+
if (!cell.resolved) {
|
|
115
|
+
return noCellDefault;
|
|
116
|
+
}
|
|
117
|
+
return collapseChannelThresholdForContact(cell.resolved.threshold);
|
|
118
|
+
}
|
|
@@ -15,12 +15,14 @@ mock.module("../config/assistant-feature-flags.js", () => ({
|
|
|
15
15
|
}));
|
|
16
16
|
|
|
17
17
|
// `buildPolicyContext` (used by the integration tests below) precomputes the
|
|
18
|
-
// proc-to-skills gate via `
|
|
19
|
-
//
|
|
20
|
-
let
|
|
18
|
+
// proc-to-skills gate via `isV3TierActive`. Drive it through this slot so a
|
|
19
|
+
// test can put the production threading path in the active / inactive state.
|
|
20
|
+
let mockV3TierActive = true;
|
|
21
21
|
mock.module("../config/memory-v3-gate.js", () => ({
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
isMemoryEnabled: (config?: { memory?: { enabled?: boolean } }) =>
|
|
23
|
+
config?.memory?.enabled !== false,
|
|
24
|
+
isV3TierActive: () => mockV3TierActive,
|
|
25
|
+
isMemoryV3Live: () => mockV3TierActive,
|
|
24
26
|
usesConceptPageMemory: (memory?: {
|
|
25
27
|
enabled?: boolean;
|
|
26
28
|
v2?: { enabled?: boolean };
|
|
@@ -115,10 +117,14 @@ mock.module("./trust-store.js", () => ({
|
|
|
115
117
|
onRulesChanged: () => {},
|
|
116
118
|
}));
|
|
117
119
|
|
|
118
|
-
// Mock workspace policy.
|
|
120
|
+
// Mock workspace policy. Spread the real module so pure path helpers
|
|
121
|
+
// (resolveSandboxBase) keep their real behavior for param building.
|
|
122
|
+
const realWorkspacePolicy = await import("./workspace-policy.js");
|
|
119
123
|
let mockIsPathWithinWorkspaceRoot = true;
|
|
120
124
|
mock.module("./workspace-policy.js", () => ({
|
|
125
|
+
...realWorkspacePolicy,
|
|
121
126
|
isWorkspaceScopedInvocation: () => false,
|
|
127
|
+
isOutOfWorkspaceFileInvocation: () => false,
|
|
122
128
|
isPathWithinWorkspaceRoot: () => mockIsPathWithinWorkspaceRoot,
|
|
123
129
|
}));
|
|
124
130
|
|
|
@@ -143,9 +149,13 @@ mock.module("../tools/network/url-safety.js", () => ({
|
|
|
143
149
|
import type { ClassificationResult } from "./ipc-risk-types.js";
|
|
144
150
|
|
|
145
151
|
let mockIpcClassifyRiskResult: ClassificationResult | undefined;
|
|
152
|
+
let lastClassifyRiskParams: Record<string, unknown> | undefined;
|
|
146
153
|
|
|
147
154
|
mock.module("../ipc/gateway-client.js", () => ({
|
|
148
|
-
ipcClassifyRisk: async () =>
|
|
155
|
+
ipcClassifyRisk: async (params: Record<string, unknown>) => {
|
|
156
|
+
lastClassifyRiskParams = params;
|
|
157
|
+
return mockIpcClassifyRiskResult;
|
|
158
|
+
},
|
|
149
159
|
ipcCall: async () => undefined,
|
|
150
160
|
ipcCallPersistent: async () => undefined,
|
|
151
161
|
resetPersistentClient: () => {},
|
|
@@ -155,6 +165,7 @@ mock.module("../ipc/gateway-client.js", () => ({
|
|
|
155
165
|
|
|
156
166
|
import {
|
|
157
167
|
mkdtempSync,
|
|
168
|
+
realpathSync,
|
|
158
169
|
rmSync,
|
|
159
170
|
symlinkSync,
|
|
160
171
|
unlinkSync,
|
|
@@ -180,9 +191,10 @@ describe("Permission Checker (gateway IPC)", () => {
|
|
|
180
191
|
beforeEach(() => {
|
|
181
192
|
mockIsContainerized = false;
|
|
182
193
|
mockIpcClassifyRiskResult = undefined;
|
|
194
|
+
lastClassifyRiskParams = undefined;
|
|
183
195
|
mockCachedThreshold = "low";
|
|
184
196
|
mockRefreshedThreshold = null;
|
|
185
|
-
|
|
197
|
+
mockV3TierActive = true;
|
|
186
198
|
thresholdCallLog.length = 0;
|
|
187
199
|
});
|
|
188
200
|
|
|
@@ -246,6 +258,70 @@ describe("Permission Checker (gateway IPC)", () => {
|
|
|
246
258
|
);
|
|
247
259
|
});
|
|
248
260
|
|
|
261
|
+
test("sends canonicalized boundary params for sandbox file tools", async () => {
|
|
262
|
+
mockIpcClassifyRiskResult = {
|
|
263
|
+
risk: "medium",
|
|
264
|
+
reason: "File write outside the workspace",
|
|
265
|
+
matchType: "registry",
|
|
266
|
+
scopeOptions: [],
|
|
267
|
+
};
|
|
268
|
+
const workingDir = mkdtempSync(join(tmpdir(), "checker-boundary-"));
|
|
269
|
+
try {
|
|
270
|
+
await classifyRisk(
|
|
271
|
+
"file_write",
|
|
272
|
+
{ path: "/tmp/checker-boundary-outside.txt" },
|
|
273
|
+
workingDir,
|
|
274
|
+
);
|
|
275
|
+
expect(lastClassifyRiskParams?.isContainerized).toBe(false);
|
|
276
|
+
// The boundary is canonicalized so the gateway compares canonical
|
|
277
|
+
// against canonical (macOS tmpdir lives behind a /var symlink).
|
|
278
|
+
expect(lastClassifyRiskParams?.resolvedWorkingDir).toBe(
|
|
279
|
+
realpathSync(workingDir),
|
|
280
|
+
);
|
|
281
|
+
} finally {
|
|
282
|
+
rmSync(workingDir, { recursive: true, force: true });
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
test("classifies a dangling symlink by its destination", async () => {
|
|
287
|
+
mockIpcClassifyRiskResult = {
|
|
288
|
+
risk: "medium",
|
|
289
|
+
reason: "File write outside the workspace",
|
|
290
|
+
matchType: "registry",
|
|
291
|
+
scopeOptions: [],
|
|
292
|
+
};
|
|
293
|
+
const workingDir = realpathSync(
|
|
294
|
+
mkdtempSync(join(tmpdir(), "checker-dangling-")),
|
|
295
|
+
);
|
|
296
|
+
const outside = realpathSync(
|
|
297
|
+
mkdtempSync(join(tmpdir(), "checker-dangling-out-")),
|
|
298
|
+
);
|
|
299
|
+
try {
|
|
300
|
+
const destination = join(outside, "not-yet.txt");
|
|
301
|
+
symlinkSync(destination, join(workingDir, "dangle"));
|
|
302
|
+
await classifyRisk("file_write", { path: "dangle" }, workingDir);
|
|
303
|
+
// The destination does not exist, but a write through the link
|
|
304
|
+
// creates it — classification must see the destination.
|
|
305
|
+
expect(lastClassifyRiskParams?.resolvedPath).toBe(destination);
|
|
306
|
+
} finally {
|
|
307
|
+
rmSync(workingDir, { recursive: true, force: true });
|
|
308
|
+
rmSync(outside, { recursive: true, force: true });
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
test("omits the canonicalized boundary for host file tools", async () => {
|
|
313
|
+
mockIpcClassifyRiskResult = {
|
|
314
|
+
risk: "medium",
|
|
315
|
+
reason: "Host file write (default)",
|
|
316
|
+
matchType: "registry",
|
|
317
|
+
scopeOptions: [],
|
|
318
|
+
};
|
|
319
|
+
await classifyRisk("host_file_write", {
|
|
320
|
+
path: "/tmp/checker-boundary-host.txt",
|
|
321
|
+
});
|
|
322
|
+
expect(lastClassifyRiskParams?.resolvedWorkingDir).toBeUndefined();
|
|
323
|
+
});
|
|
324
|
+
|
|
249
325
|
test("caches results for identical inputs", async () => {
|
|
250
326
|
mockIpcClassifyRiskResult = {
|
|
251
327
|
risk: "low",
|
|
@@ -1085,7 +1161,7 @@ describe("Permission Checker (gateway IPC)", () => {
|
|
|
1085
1161
|
// Same retrospective ToolContext, but the feature is inactive (flag off
|
|
1086
1162
|
// or v3 not live). buildPolicyContext stamps `procToSkillsActive: false`,
|
|
1087
1163
|
// so the grant is dead and the high-risk scaffold prompts.
|
|
1088
|
-
|
|
1164
|
+
mockV3TierActive = false;
|
|
1089
1165
|
mockIpcClassifyRiskResult = {
|
|
1090
1166
|
risk: "high",
|
|
1091
1167
|
reason: "Skill scaffold",
|
|
@@ -53,6 +53,7 @@ import {
|
|
|
53
53
|
import {
|
|
54
54
|
isPathWithinWorkspaceRoot,
|
|
55
55
|
isWorkspaceScopedInvocation,
|
|
56
|
+
resolveSandboxBase,
|
|
56
57
|
} from "./workspace-policy.js";
|
|
57
58
|
|
|
58
59
|
// ── Risk classification cache ────────────────────────────────────────────────
|
|
@@ -155,7 +156,7 @@ function fileToolFsStateKey(
|
|
|
155
156
|
return undefined;
|
|
156
157
|
}
|
|
157
158
|
const resolved = resolveFileToolPaths(toolName, input, workingDir);
|
|
158
|
-
return `${resolved.resolvedPath ?? ""}\0${resolved.resolvedTransferDestPath ?? ""}`;
|
|
159
|
+
return `${resolved.resolvedPath ?? ""}\0${resolved.resolvedTransferDestPath ?? ""}\0${resolved.resolvedWorkingDir ?? ""}`;
|
|
159
160
|
}
|
|
160
161
|
|
|
161
162
|
/** Clear the risk classification cache. Called when trust rules change. Exported for test setup. */
|
|
@@ -210,7 +211,7 @@ function resolveSkillIdAndHash(
|
|
|
210
211
|
* registry (`getToolOwner(name)`) rather than read from the `Tool` object,
|
|
211
212
|
* since ownership lives on the registry, not on the tool itself.
|
|
212
213
|
*/
|
|
213
|
-
function isToolOwnerSkillBundled(tool: Tool | undefined): boolean {
|
|
214
|
+
export function isToolOwnerSkillBundled(tool: Tool | undefined): boolean {
|
|
214
215
|
if (!tool) {
|
|
215
216
|
return false;
|
|
216
217
|
}
|
|
@@ -389,25 +390,6 @@ function buildFileContext(): FileContext {
|
|
|
389
390
|
* filesystem this process cannot see (e.g. host_file paths proxied to a remote
|
|
390
391
|
* client), so this never regresses below today's lexical behavior.
|
|
391
392
|
*/
|
|
392
|
-
// The Docker sandbox mounts the workspace at /workspace, and the model emits
|
|
393
|
-
// container-scoped paths (e.g. "/workspace/tools/evil.ts") even on local turns.
|
|
394
|
-
// Mirror the gateway's resolveSandboxPath remap so the symlink-resolved path we
|
|
395
|
-
// forward lines up with the gateway's lexical fallback and the protected dirs.
|
|
396
|
-
const CONTAINER_WORKSPACE_PREFIX = "/workspace/";
|
|
397
|
-
const CONTAINER_WORKSPACE_EXACT = "/workspace";
|
|
398
|
-
|
|
399
|
-
function resolveSandboxBase(rawPath: string, workingDir: string): string {
|
|
400
|
-
let effectivePath = rawPath;
|
|
401
|
-
if (!rawPath.startsWith(workingDir + "/") && rawPath !== workingDir) {
|
|
402
|
-
if (rawPath.startsWith(CONTAINER_WORKSPACE_PREFIX)) {
|
|
403
|
-
effectivePath = rawPath.slice(CONTAINER_WORKSPACE_PREFIX.length);
|
|
404
|
-
} else if (rawPath === CONTAINER_WORKSPACE_EXACT) {
|
|
405
|
-
effectivePath = ".";
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
return resolve(workingDir, effectivePath);
|
|
409
|
-
}
|
|
410
|
-
|
|
411
393
|
function resolveClassificationPath(
|
|
412
394
|
filePath: string,
|
|
413
395
|
workingDir: string,
|
|
@@ -441,6 +423,13 @@ interface FileToolResolution {
|
|
|
441
423
|
effectiveWorkingDir: string;
|
|
442
424
|
isHostTool: boolean;
|
|
443
425
|
resolvedPath?: string;
|
|
426
|
+
/**
|
|
427
|
+
* Symlink-canonicalized working dir for sandbox file tools, paired with
|
|
428
|
+
* `resolvedPath` so the gateway's workspace-boundary check compares
|
|
429
|
+
* canonical against canonical (a symlinked workspace prefix, e.g. macOS
|
|
430
|
+
* /var → /private/var, must not read as an escape). Unset for host tools.
|
|
431
|
+
*/
|
|
432
|
+
resolvedWorkingDir?: string;
|
|
444
433
|
transferSandboxDestPath?: string;
|
|
445
434
|
transferSandboxWorkingDir?: string;
|
|
446
435
|
resolvedTransferDestPath?: string;
|
|
@@ -490,6 +479,9 @@ function resolveFileToolPaths(
|
|
|
490
479
|
effectiveWorkingDir,
|
|
491
480
|
isHostTool,
|
|
492
481
|
),
|
|
482
|
+
resolvedWorkingDir: isHostTool
|
|
483
|
+
? undefined
|
|
484
|
+
: resolveRealPath(effectiveWorkingDir),
|
|
493
485
|
transferSandboxDestPath,
|
|
494
486
|
transferSandboxWorkingDir,
|
|
495
487
|
// The to_sandbox destination is a workspace write — symlink-resolve it too
|
|
@@ -573,7 +565,9 @@ function buildClassifyRiskParams(
|
|
|
573
565
|
tool: toolName,
|
|
574
566
|
path: resolved.filePath,
|
|
575
567
|
resolvedPath: resolved.resolvedPath,
|
|
568
|
+
resolvedWorkingDir: resolved.resolvedWorkingDir,
|
|
576
569
|
workingDir: resolved.effectiveWorkingDir,
|
|
570
|
+
isContainerized: getIsContainerized(),
|
|
577
571
|
fileContext: buildFileContext(),
|
|
578
572
|
transferSandboxDestPath: resolved.transferSandboxDestPath,
|
|
579
573
|
transferSandboxWorkingDir: resolved.transferSandboxWorkingDir,
|
|
@@ -797,7 +791,8 @@ export async function classifyRisk(
|
|
|
797
791
|
// prompt. The grant resolves these tools to ALLOW non-interactively, and ONLY
|
|
798
792
|
// when all of these hold:
|
|
799
793
|
// - procedural-memory-as-skills is active (`policyContext.procToSkillsActive`,
|
|
800
|
-
// precomputed by buildPolicyContext:
|
|
794
|
+
// precomputed by buildPolicyContext: the v3 tier is active — memory is on
|
|
795
|
+
// and memory-v3 is live),
|
|
801
796
|
// - the turn is the retrospective background source — guardian trust, `vellum`
|
|
802
797
|
// source channel, `memory_retrospective` origin (set in
|
|
803
798
|
// memory-retrospective-job.ts).
|
|
@@ -50,7 +50,7 @@ mock.module("../runtime/confirmation-request-guardian-bridge.js", () => ({
|
|
|
50
50
|
},
|
|
51
51
|
}));
|
|
52
52
|
|
|
53
|
-
import type {
|
|
53
|
+
import type { AssistantEvent } from "../api/index.js";
|
|
54
54
|
import { createGuardianRequestForConfirmation } from "./confirmation-guardian-request.js";
|
|
55
55
|
|
|
56
56
|
const MSG = {
|
|
@@ -59,7 +59,7 @@ const MSG = {
|
|
|
59
59
|
toolName: "Bash",
|
|
60
60
|
input: { command: "ls" },
|
|
61
61
|
riskLevel: "medium",
|
|
62
|
-
} as unknown as
|
|
62
|
+
} as unknown as AssistantEvent & { type: "confirmation_request" };
|
|
63
63
|
|
|
64
64
|
describe("createGuardianRequestForConfirmation", () => {
|
|
65
65
|
beforeEach(() => {
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* therefore the emitters — stays cheap and free of import-time side effects.
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
import type {
|
|
20
|
+
import type { ConfirmationRequestEvent } from "../api/index.js";
|
|
21
21
|
import { IntegrityError } from "../util/errors.js";
|
|
22
22
|
import { getLogger } from "../util/logger.js";
|
|
23
23
|
|
|
@@ -30,7 +30,7 @@ const log = getLogger("confirmation-guardian-request");
|
|
|
30
30
|
* never thrown.
|
|
31
31
|
*/
|
|
32
32
|
export async function createGuardianRequestForConfirmation(
|
|
33
|
-
msg:
|
|
33
|
+
msg: ConfirmationRequestEvent,
|
|
34
34
|
conversationId: string,
|
|
35
35
|
opts?: {
|
|
36
36
|
/**
|