@vellumai/assistant 0.10.12 → 0.11.0-staging.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -1
- package/ARCHITECTURE.md +4 -5
- package/README.md +1 -1
- package/docs/architecture/memory.md +60 -23
- package/docs/error-handling.md +3 -3
- package/docs/guardian-request-flow.md +112 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +9 -1
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +449 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/channels.ts +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +468 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/app.d.ts +28 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/app.d.ts.map +1 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/index.d.ts +2 -2
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/index.d.ts.map +1 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/index.js.map +1 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/message.d.ts +2 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/message.d.ts.map +1 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/package.json +1 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +9 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +449 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/channels.ts +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +468 -0
- package/node_modules/@vellumai/gateway-client/package.json +1 -1
- package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +6 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +34 -0
- package/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +9 -1
- package/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +449 -0
- package/node_modules/@vellumai/service-contracts/src/channels.ts +1 -0
- package/node_modules/@vellumai/service-contracts/src/secret-detection.ts +468 -0
- package/openapi.yaml +264 -14
- package/package.json +2 -2
- package/src/__tests__/acp-session.test.ts +3 -3
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +3 -0
- package/src/__tests__/anthropic-provider.test.ts +40 -0
- package/src/__tests__/app-conversation-ids-backfill.test.ts +33 -2
- package/src/__tests__/app-conversation-ids.test.ts +204 -0
- package/src/__tests__/approval-cascade.test.ts +5 -5
- package/src/__tests__/approval-routes-http.test.ts +3 -3
- package/src/__tests__/ask-question-resolver.test.ts +207 -0
- package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +16 -16
- package/src/__tests__/assistant-event-hub-targeted.test.ts +13 -11
- package/src/__tests__/assistant-event-hub.test.ts +13 -11
- package/src/__tests__/assistant-event.test.ts +12 -9
- package/src/__tests__/assistant-feature-flag-guard.test.ts +3 -3
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +1 -1
- package/src/__tests__/assistant-id-boundary-guard.test.ts +0 -58
- package/src/__tests__/assistant-stream-state.test.ts +17 -7
- package/src/__tests__/avatar-identity-sync.test.ts +3 -3
- package/src/__tests__/background-workers-disk-pressure.test.ts +1 -0
- package/src/__tests__/call-conversation-messages.test.ts +134 -18
- package/src/__tests__/call-start-guardian-guard.test.ts +27 -0
- package/src/__tests__/channel-approvals.test.ts +0 -27
- package/src/__tests__/channel-guardian.test.ts +85 -512
- package/src/__tests__/channel-readiness-slack-remote.test.ts +151 -3
- package/src/__tests__/channel-retry-sweep.test.ts +88 -1
- package/src/__tests__/channel-setup-panel-ack.test.ts +12 -9
- package/src/__tests__/chat-reveal-guard-priming.test.ts +31 -34
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +2 -2
- package/src/__tests__/compaction-events.test.ts +8 -8
- package/src/__tests__/config-loader-platform-defaults.test.ts +54 -28
- package/src/__tests__/config-model-image-provider.test.ts +20 -0
- package/src/__tests__/config-schema-memory-substrate.test.ts +306 -0
- package/src/__tests__/config-schema.test.ts +14 -2
- package/src/__tests__/config-set-platform-guard.test.ts +11 -12
- package/src/__tests__/config-sounds-sync.test.ts +4 -4
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +5 -0
- package/src/__tests__/context-search-memory-source.test.ts +1 -1
- package/src/__tests__/context-search-memory-v2-source.test.ts +6 -6
- package/src/__tests__/context-token-estimator.test.ts +54 -1
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +12 -3
- package/src/__tests__/conversation-agent-loop-fatal-cleanup.test.ts +13 -4
- package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +4 -4
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +10 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +22 -13
- package/src/__tests__/conversation-agent-loop.test.ts +39 -30
- package/src/__tests__/conversation-confirmation-signals.test.ts +14 -14
- package/src/__tests__/conversation-evictor.test.ts +49 -0
- package/src/__tests__/conversation-fork-crud.test.ts +1 -1
- package/src/__tests__/conversation-group-tools.test.ts +279 -0
- package/src/__tests__/conversation-history-web-search.test.ts +1 -1
- package/src/__tests__/conversation-key-store-disk-view.test.ts +5 -5
- package/src/__tests__/conversation-lineage.test.ts +235 -0
- package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +5 -5
- package/src/__tests__/conversation-message-sync-tags.test.ts +4 -4
- package/src/__tests__/conversation-queue.test.ts +81 -81
- package/src/__tests__/conversation-routes-enabled-plugins.test.ts +8 -1
- package/src/__tests__/conversation-routes-hidden-queue.test.ts +8 -1
- package/src/__tests__/conversation-routes-slash-commands.test.ts +10 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +29 -2
- package/src/__tests__/conversation-slash-queue.test.ts +11 -11
- package/src/__tests__/conversation-slash-unknown.test.ts +2 -2
- package/src/__tests__/conversation-speed-override.test.ts +2 -2
- package/src/__tests__/conversation-summarize-route.test.ts +9 -0
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +18 -16
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +17 -17
- package/src/__tests__/conversation-surfaces-app-open.test.ts +7 -4
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +7 -7
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +9 -9
- package/src/__tests__/conversation-surfaces-standalone.test.ts +12 -12
- package/src/__tests__/conversation-surfaces-state-update.test.ts +8 -5
- package/src/__tests__/conversation-surfaces-table-action.test.ts +6 -3
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +46 -46
- package/src/__tests__/conversation-sync-tags.test.ts +5 -5
- package/src/__tests__/conversation-wait-for-idle.test.ts +2 -2
- package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -4
- package/src/__tests__/conversation-workspace-injection.test.ts +0 -3
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -3
- package/src/__tests__/copy-composer-tc-templates.test.ts +3 -131
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/daemon-assistant-events.test.ts +14 -15
- package/src/__tests__/db-test-helpers.ts +13 -27
- package/src/__tests__/disk-pressure-routes.test.ts +12 -3
- package/src/__tests__/document-tool-security.test.ts +95 -0
- package/src/__tests__/drain-kick-guard.test.ts +232 -0
- package/src/__tests__/dynamic-skill-background-guard.test.ts +19 -6
- package/src/__tests__/emit-event-signal.test.ts +5 -6
- package/src/__tests__/encrypted-store-test-helpers.ts +10 -20
- package/src/__tests__/events-tail-route.test.ts +6 -4
- package/src/__tests__/feature-flag-test-helpers.ts +10 -20
- package/src/__tests__/file-edit-tool.test.ts +24 -4
- package/src/__tests__/file-list-tool.test.ts +2 -1
- package/src/__tests__/file-read-tool.test.ts +62 -10
- package/src/__tests__/file-write-tool.test.ts +24 -5
- package/src/__tests__/followup-tools.test.ts +58 -0
- package/src/__tests__/gateway-threshold-reader-mock.ts +99 -0
- package/src/__tests__/graph-extraction-event-date.test.ts +1 -1
- package/src/__tests__/guardian-question-mode.test.ts +42 -3
- package/src/__tests__/guardian-reply-router-answer-mode.test.ts +283 -0
- package/src/__tests__/guardian-vellum-destination-pinning.test.ts +221 -0
- package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
- package/src/__tests__/heartbeat-service.test.ts +1 -0
- package/src/__tests__/helpers/native-web-search-harness.ts +10 -10
- package/src/__tests__/host-browser-proxy.test.ts +1 -1
- package/src/__tests__/host-file-edit-tool.test.ts +3 -3
- package/src/__tests__/host-file-read-tool.test.ts +2 -2
- package/src/__tests__/host-file-write-tool.test.ts +7 -3
- package/src/__tests__/host-shell-tool.test.ts +17 -5
- package/src/__tests__/host-transfer-pending-interactions.test.ts +8 -8
- package/src/__tests__/image-credentials.test.ts +65 -8
- package/src/__tests__/injection-block.test.ts +4 -4
- package/src/__tests__/injector-chain.test.ts +1 -1
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +2 -2
- package/src/__tests__/injector-registry-order-guard.test.ts +4 -9
- package/src/__tests__/injector-v3-suppression.test.ts +6 -4
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +27 -28
- package/src/__tests__/list-messages-page-latest.test.ts +2 -2
- package/src/__tests__/llm-usage-store.test.ts +67 -4
- package/src/__tests__/log-redact.test.ts +18 -0
- package/src/__tests__/managed-profile-guard.test.ts +27 -0
- package/src/__tests__/managed-skill-lifecycle.test.ts +2 -2
- package/src/__tests__/media-generate-image.test.ts +62 -11
- package/src/__tests__/memory-identity-context-parity.test.ts +1 -1
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +9 -1
- package/src/__tests__/memory-retrieval-hook.test.ts +4 -4
- package/src/__tests__/notification-decision-strategy.test.ts +115 -11
- package/src/__tests__/notification-deep-link.test.ts +12 -12
- package/src/__tests__/notification-vellum-adapter.test.ts +8 -8
- package/src/__tests__/outbound-slack-persistence.test.ts +8 -8
- package/src/__tests__/path-policy.test.ts +315 -0
- package/src/__tests__/pending-interactions-resolved-event.test.ts +6 -6
- package/src/__tests__/persistence-layering-guard.test.ts +2 -2
- package/src/__tests__/pkb-autoinject.test.ts +1 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +1 -0
- package/src/__tests__/platform-callback-registration.test.ts +10 -10
- package/src/__tests__/plugin-event-hub-facade.test.ts +22 -15
- package/src/__tests__/plugin-import-boundary-guard.test.ts +15 -15
- package/src/__tests__/processing-flag-persist-failure.test.ts +0 -4
- package/src/__tests__/provider-platform-proxy-integration.test.ts +0 -1
- package/src/__tests__/rebuild-index-graph-nodes.test.ts +1 -1
- package/src/__tests__/request-secret-standalone-channel-gate.test.ts +5 -5
- package/src/__tests__/require-fresh-approval.test.ts +38 -38
- package/src/__tests__/resolve-app-id.test.ts +32 -0
- package/src/__tests__/run-due-schedules.test.ts +72 -1
- package/src/__tests__/runtime-events-sse-parity.test.ts +11 -10
- package/src/__tests__/runtime-events-sse.test.ts +1 -1
- package/src/__tests__/schedule-routes.test.ts +44 -5
- package/src/__tests__/schedule-store.test.ts +3 -3
- package/src/__tests__/schedule-tools.test.ts +176 -0
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +3 -3
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +3 -3
- package/src/__tests__/secret-response-routing.test.ts +3 -3
- package/src/__tests__/secret-routes-platform-proxy.test.ts +4 -7
- package/src/__tests__/secret-scanner.test.ts +36 -0
- package/src/__tests__/send-endpoint-busy.test.ts +7 -7
- package/src/__tests__/slack-required-scopes-mirror.test.ts +81 -0
- package/src/__tests__/starter-task-flow.test.ts +26 -3
- package/src/__tests__/subagent-call-site-routing.test.ts +2 -2
- package/src/__tests__/subagent-disposal.test.ts +40 -11
- package/src/__tests__/subagent-fork-notifications.test.ts +4 -4
- package/src/__tests__/subagent-fork-prompt-role.test.ts +3 -3
- package/src/__tests__/subagent-fork-spawn.test.ts +4 -4
- package/src/__tests__/subagent-manager-notify.test.ts +73 -14
- package/src/__tests__/subagent-notify-parent.test.ts +48 -4
- package/src/__tests__/subagent-spawn-and-await.test.ts +62 -14
- package/src/__tests__/subagent-tools.test.ts +64 -0
- package/src/__tests__/sync-message-contract.test.ts +3 -3
- package/src/__tests__/terminal-tools.test.ts +12 -3
- package/src/__tests__/test-preload.ts +9 -0
- package/src/__tests__/tool-approval-handler.test.ts +587 -43
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +7 -4
- package/src/__tests__/tool-executor.test.ts +116 -0
- package/src/__tests__/tool-grant-request-escalation.test.ts +5 -0
- package/src/__tests__/tool-preview-lifecycle.test.ts +32 -29
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +5 -5
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
- package/src/__tests__/tool-start-timestamp.test.ts +4 -4
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +9 -22
- package/src/__tests__/ui-choice-copy-surfaces.test.ts +13 -13
- package/src/__tests__/ui-work-result-surface.test.ts +3 -3
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +6 -6
- package/src/__tests__/voice-session-bridge.test.ts +44 -44
- package/src/__tests__/workspace-migration-134-image-generation-mode-to-provider.test.ts +284 -0
- package/src/__tests__/workspace-policy.test.ts +482 -2
- package/src/acp/__tests__/client-handler.test.ts +3 -3
- package/src/acp/__tests__/session-manager-persistence.test.ts +10 -10
- package/src/acp/__tests__/session-manager-resume.test.ts +7 -7
- package/src/acp/client-handler.ts +3 -3
- package/src/acp/session-manager.ts +8 -8
- package/src/api/events/subagent-event.ts +2 -2
- package/src/api/responses/memory-v2-activation-log.ts +2 -2
- package/src/api/responses/subagent-detail.ts +13 -0
- package/src/approvals/AGENTS.md +2 -0
- package/src/approvals/guardian-request-resolvers.ts +118 -24
- package/src/apps/app-store.ts +95 -4
- package/src/calls/__tests__/voice-control-protocol.test.ts +57 -0
- package/src/calls/__tests__/voice-session-bridge.test.ts +229 -7
- package/src/calls/__tests__/voice-triage-escalate.test.ts +3 -4
- package/src/calls/call-controller.ts +27 -27
- package/src/calls/call-conversation-messages.ts +58 -18
- package/src/calls/voice-control-protocol.ts +56 -0
- package/src/calls/voice-session-bridge.ts +178 -65
- package/src/calls/voice-triage-escalate.ts +2 -3
- package/src/channels/config.ts +8 -0
- package/src/channels/types.ts +1 -0
- package/src/cli/commands/config.ts +49 -13
- package/src/cli/commands/memory/index.help.ts +4 -2
- package/src/cli/commands/memory/memory-retrospective.ts +5 -0
- package/src/cli/commands/webhooks.help.ts +9 -4
- package/src/cli/lib/bundled-marketplace.json +12 -0
- package/src/cli.ts +2 -109
- package/src/config/__tests__/deployment-context-defaults.test.ts +9 -0
- package/src/config/__tests__/substrate-twin-shadowing.test.ts +191 -0
- package/src/config/assistant-feature-flags.ts +1 -1
- package/src/config/bundled-skills/conversation-groups/SKILL.md +29 -0
- package/src/config/bundled-skills/conversation-groups/TOOLS.json +58 -0
- package/src/config/bundled-skills/conversation-groups/tools/group-create.ts +12 -0
- package/src/config/bundled-skills/conversation-groups/tools/group-list.ts +12 -0
- package/src/config/bundled-skills/conversation-groups/tools/move-to-group.ts +12 -0
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +13 -7
- package/src/config/bundled-skills/schedule/SKILL.md +2 -0
- package/src/config/feature-flag-cache.ts +6 -16
- package/src/config/feature-flag-registry.json +14 -38
- package/src/config/loader.ts +7 -1
- package/src/config/memory-tier.ts +15 -10
- package/src/config/memory-v3-gate.test.ts +278 -1
- package/src/config/memory-v3-gate.ts +88 -26
- package/src/config/raw-config-utils.ts +1 -1
- package/src/config/schemas/__tests__/live-voice.test.ts +27 -16
- package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
- package/src/config/schemas/live-voice.ts +33 -7
- package/src/config/schemas/llm.ts +1 -0
- package/src/config/schemas/memory-retrospective.ts +13 -0
- package/src/config/schemas/memory-substrate.ts +183 -0
- package/src/config/schemas/memory-v2.ts +3 -2
- package/src/config/schemas/memory-v3.ts +11 -4
- package/src/config/schemas/memory.ts +35 -1
- package/src/config/schemas/services.ts +10 -2
- package/src/config/substrate-twin-shadowing.ts +195 -0
- package/src/config/webhook-routing.ts +67 -0
- package/src/context/compactor.ts +10 -3
- package/src/context/token-estimator.ts +21 -0
- package/src/daemon/__tests__/channel-ui-capability.test.ts +85 -0
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +3 -3
- package/src/daemon/__tests__/embedding-reconcile.test.ts +3 -3
- package/src/daemon/__tests__/inference-profile-notification.test.ts +3 -6
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +5 -5
- package/src/daemon/__tests__/web-search-status-text.test.ts +2 -2
- package/src/daemon/channel-ui-capability.ts +70 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +4 -4
- package/src/daemon/conversation-agent-loop.ts +12 -5
- package/src/daemon/conversation-evictor.ts +26 -4
- package/src/daemon/conversation-launch.ts +11 -14
- package/src/daemon/conversation-lineage.ts +76 -0
- package/src/daemon/conversation-messaging.ts +14 -14
- package/src/daemon/conversation-notifiers.ts +2 -2
- package/src/daemon/conversation-process.ts +133 -21
- package/src/daemon/conversation-queue-manager.ts +7 -7
- package/src/daemon/conversation-runtime-assembly.ts +16 -0
- package/src/daemon/conversation-store.ts +11 -3
- package/src/daemon/conversation-surfaces.ts +8 -14
- package/src/daemon/conversation-tool-setup.ts +13 -7
- package/src/daemon/conversation-usage.ts +12 -11
- package/src/daemon/conversation.ts +38 -15
- package/src/daemon/disk-pressure-guard.ts +5 -12
- package/src/daemon/embedding-reconcile.ts +14 -9
- package/src/daemon/handlers/config-channels.ts +40 -134
- package/src/daemon/handlers/config-model.ts +15 -7
- package/src/daemon/handlers/conversations.ts +4 -2
- package/src/daemon/handlers/shared.ts +29 -0
- package/src/daemon/host-proxy-base.ts +4 -4
- package/src/daemon/lifecycle.ts +13 -0
- package/src/daemon/message-protocol.ts +8 -144
- package/src/daemon/message-types/computer-use.ts +0 -12
- package/src/daemon/message-types/conversations.ts +9 -345
- package/src/daemon/message-types/host-app-control.ts +0 -9
- package/src/daemon/message-types/host-browser.ts +0 -7
- package/src/daemon/message-types/host-ui-snapshot.ts +0 -7
- package/src/daemon/message-types/messages.ts +0 -48
- package/src/daemon/message-types/notifications.ts +0 -7
- package/src/daemon/message-types/skills.ts +0 -5
- package/src/daemon/message-types/surfaces.ts +0 -9
- package/src/daemon/message-types/sync.ts +0 -2
- package/src/daemon/process-message.ts +5 -5
- package/src/daemon/skill-memory-refresh.ts +5 -5
- package/src/daemon/tool-side-effects.ts +32 -16
- package/src/daemon/trust-context.ts +1 -1
- package/src/daemon/wake-conversation-ops.ts +4 -4
- package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +100 -7
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +67 -0
- package/src/heartbeat/heartbeat-run-store.ts +81 -4
- package/src/heartbeat/heartbeat-service.ts +32 -1
- package/src/home/__tests__/feed-writer.test.ts +7 -7
- package/src/home/__tests__/home-content-refresh.test.ts +3 -0
- package/src/home/__tests__/suggested-prompts.test.ts +1 -0
- package/src/home/feed-writer.ts +6 -13
- package/src/home/home-content-refresh.ts +6 -9
- package/src/home/relationship-state-writer.ts +5 -12
- package/src/home/suggested-prompts-cache.ts +6 -19
- package/src/ipc/__tests__/events-publish-client.test.ts +67 -0
- package/src/ipc/events-publish-client.ts +44 -0
- package/src/ipc/routes/__tests__/conversation-sync-ipc-routes.test.ts +2 -2
- package/src/ipc/routes/__tests__/events-ipc-routes.test.ts +38 -9
- package/src/ipc/routes/events-ipc-routes.ts +11 -31
- package/src/live-voice/__tests__/front-decision.test.ts +4 -176
- package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +276 -68
- package/src/live-voice/__tests__/live-voice-continuation-fork-hydration.test.ts +286 -0
- package/src/live-voice/__tests__/live-voice-events.test.ts +6 -3
- package/src/live-voice/__tests__/live-voice-progress.test.ts +185 -46
- package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +24 -59
- package/src/live-voice/__tests__/live-voice-tts-session.test.ts +38 -54
- package/src/live-voice/__tests__/live-voice-vad.test.ts +1154 -636
- package/src/live-voice/front-decision.ts +5 -155
- package/src/live-voice/live-voice-metrics.ts +4 -1
- package/src/live-voice/live-voice-session.ts +1288 -439
- package/src/live-voice/progress-phrases.ts +17 -0
- package/src/live-voice/protocol.ts +15 -0
- package/src/media/app-icon-generator.ts +15 -8
- package/src/media/avatar-router.ts +9 -5
- package/src/media/image-credentials.ts +42 -10
- package/src/media/image-service.ts +1 -13
- package/src/media/types.ts +26 -3
- package/src/notifications/AGENTS.md +2 -0
- package/src/notifications/__tests__/broadcaster.test.ts +95 -0
- package/src/notifications/adapters/macos.ts +3 -3
- package/src/notifications/broadcaster.ts +57 -0
- package/src/notifications/copy-composer.ts +0 -15
- package/src/notifications/decision-engine.ts +21 -22
- package/src/notifications/guardian-question-mode.ts +57 -2
- package/src/notifications/home-feed-side-effect.ts +4 -0
- package/src/notifications/signal.ts +6 -4
- package/src/notifications/trusted-contact-payloads.ts +3 -4
- package/src/notifications/vellum-card-affinity.ts +39 -0
- package/src/oauth/AGENTS.md +1 -1
- package/src/permissions/channel-permission-query.test.ts +69 -0
- package/src/permissions/channel-permission-query.ts +73 -1
- package/src/permissions/checker.test.ts +298 -15
- package/src/permissions/checker.ts +102 -36
- package/src/permissions/confirmation-guardian-request.test.ts +2 -2
- package/src/permissions/confirmation-guardian-request.ts +2 -2
- package/src/permissions/gateway-threshold-reader.test.ts +224 -17
- package/src/permissions/gateway-threshold-reader.ts +82 -10
- package/src/permissions/ipc-risk-types.ts +8 -0
- package/src/permissions/prompter.ts +5 -5
- package/src/permissions/question-guardian-request.test.ts +222 -0
- package/src/permissions/question-guardian-request.ts +179 -0
- package/src/permissions/question-prompter.test.ts +8 -8
- package/src/permissions/question-prompter.ts +18 -0
- package/src/permissions/secret-prompter.ts +2 -4
- package/src/permissions/workspace-policy.ts +269 -34
- package/src/persistence/__tests__/lifecycle-quiesce.test.ts +82 -0
- package/src/persistence/__tests__/message-content-file.test.ts +58 -3
- package/src/persistence/conversation-crud.ts +93 -0
- package/src/persistence/conversation-key-store.ts +63 -0
- package/src/persistence/conversation-parent.ts +27 -0
- package/src/persistence/db-async-query.ts +1 -1
- package/src/persistence/db-singleton.ts +14 -27
- package/src/persistence/delivery-crud.ts +45 -0
- package/src/persistence/embeddings/embedding-backend.ts +2 -1
- package/src/persistence/embeddings/embedding-identity.ts +7 -3
- package/src/persistence/job-utils.ts +32 -27
- package/src/persistence/jobs-store.ts +92 -3
- package/src/persistence/lifecycle-quiesce.ts +80 -0
- package/src/persistence/llm-usage-store.ts +45 -8
- package/src/persistence/message-content-file.ts +4 -4
- package/src/persistence/migrations/336-move-memory-v2-activation-logs-to-memory-db.ts +1 -1
- package/src/persistence/migrations/351-schedule-skill-script-handoff.ts +39 -0
- package/src/persistence/migrations/352-drop-schedule-skill-script-handoff.test.ts +83 -0
- package/src/persistence/migrations/352-drop-schedule-skill-script-handoff.ts +36 -0
- package/src/persistence/migrations/353-add-llm-usage-conversation-type.test.ts +110 -0
- package/src/persistence/migrations/353-add-llm-usage-conversation-type.ts +49 -0
- package/src/persistence/migrations/354-backfill-app-conversation-lineage.ts +41 -0
- package/src/persistence/schema/infrastructure.ts +11 -0
- package/src/persistence/steps.ts +9 -1
- package/src/plugin-api/__tests__/publish-event-forwarding.test.ts +113 -0
- package/src/plugin-api/__tests__/publish-event.test.ts +57 -0
- package/src/plugin-api/conversation-turn.ts +4 -4
- package/src/plugin-api/event-hub-facade.ts +15 -6
- package/src/plugin-api/index.ts +10 -4
- package/src/plugin-api/publish-event.ts +36 -0
- package/src/plugins/AGENTS.md +2 -0
- package/src/plugins/defaults/compaction/window-manager.ts +9 -0
- package/src/plugins/defaults/index.ts +9 -13
- package/src/plugins/defaults/memory/AGENTS.md +775 -0
- package/src/plugins/defaults/memory/__tests__/capability-seed-embed-gate.test.ts +186 -0
- package/src/plugins/defaults/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +1 -1
- package/src/plugins/defaults/memory/__tests__/indexer-tier-dispatch.test.ts +129 -0
- package/src/plugins/defaults/memory/__tests__/jobs-worker-quiesce-gate.test.ts +91 -0
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v1-graph-substrate-noop.test.ts +342 -0
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +9 -1
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-schedule.test.ts +36 -1
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-sweep-defer.test.ts +9 -1
- package/src/plugins/defaults/memory/__tests__/memory-log-stores-degraded.test.ts +2 -2
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +44 -10
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +151 -10
- package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +1155 -0
- package/src/plugins/defaults/memory/__tests__/memory-v2-activation-log-store.test.ts +1 -1
- package/src/plugins/defaults/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -3
- package/src/plugins/defaults/memory/__tests__/tools-delete-memory-page.test.ts +1 -1
- package/src/plugins/defaults/memory/context-search/sources/memory-v2.ts +71 -35
- package/src/plugins/defaults/memory/context-search/sources/memory.ts +5 -1
- package/src/plugins/defaults/memory/fork-conversation-memory.ts +4 -4
- package/src/plugins/defaults/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +80 -10
- package/src/plugins/defaults/memory/graph/__tests__/handle-remember-v2.test.ts +1 -1
- package/src/plugins/defaults/memory/graph/capability-seed.ts +24 -10
- package/src/plugins/defaults/memory/graph/conversation-graph-memory.ts +123 -49
- package/src/plugins/defaults/memory/graph/graph-search.ts +6 -118
- package/src/plugins/defaults/memory/graph/in-context-tracker.test.ts +173 -0
- package/src/plugins/defaults/memory/graph/in-context-tracker.ts +109 -0
- package/src/plugins/defaults/memory/graph/store.ts +1 -0
- package/src/plugins/defaults/memory/graph/tool-handlers.test.ts +1 -1
- package/src/plugins/defaults/memory/graph/tool-handlers.ts +5 -2
- package/src/plugins/defaults/memory/graph-topology/__tests__/build-memory-graph.test.ts +1 -1
- package/src/plugins/defaults/memory/graph-topology/build-memory-graph.ts +6 -9
- package/src/plugins/defaults/memory/hooks/__tests__/user-prompt-submit.test.ts +30 -16
- package/src/plugins/defaults/memory/hooks/user-prompt-submit.ts +18 -14
- package/src/plugins/defaults/memory/indexer.ts +146 -89
- package/src/plugins/defaults/memory/injectors.ts +86 -41
- package/src/plugins/defaults/memory/job-handlers.ts +130 -39
- package/src/plugins/defaults/memory/jobs/__tests__/embed-concept-page.test.ts +2 -2
- package/src/plugins/defaults/memory/jobs/embed-concept-page.ts +22 -10
- package/src/plugins/defaults/memory/jobs-worker.ts +279 -208
- package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +4 -2
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +40 -3
- package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +99 -11
- package/src/plugins/defaults/memory/src/__tests__/memory-v2-routes.test.ts +5 -3
- package/src/plugins/defaults/memory/src/__tests__/memory-v2-simulate-route.test.ts +3 -4
- package/src/plugins/defaults/memory/src/memory-graph-routes.ts +2 -1
- package/src/plugins/defaults/memory/src/memory-item-routes.test.ts +7 -5
- package/src/plugins/defaults/memory/src/memory-item-routes.ts +51 -19
- package/src/plugins/defaults/memory/src/memory-v2-routes.ts +31 -20
- package/src/plugins/defaults/memory/startup.ts +58 -21
- package/src/plugins/defaults/memory/substrate/__tests__/boot-maintenance.test.ts +335 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/cli-command-store.test.ts +14 -8
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/consolidation-job.test.ts +51 -21
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/edge-index.test.ts +1 -1
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/frontmatter-sweep.test.ts +3 -3
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/page-index.test.ts +1 -1
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/page-store.test.ts +1 -1
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/prompts-consolidation.test.ts +2 -2
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/qdrant.test.ts +23 -14
- package/src/plugins/defaults/memory/substrate/__tests__/reembed-job.test.ts +262 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sim.test.ts +9 -12
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/skill-content.test.ts +2 -2
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/skill-store.test.ts +9 -9
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sparse-bm25.test.ts +12 -5
- package/src/plugins/defaults/memory/substrate/__tests__/spread.test.ts +276 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/static-context.test.ts +17 -8
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sweep-job.test.ts +9 -9
- package/src/plugins/defaults/memory/{v3/substrate/memory-v2-startup.ts → substrate/boot-maintenance.ts} +43 -24
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/cli-command-store.ts +13 -8
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/consolidation-job.ts +51 -27
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/constants.ts +1 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/edge-index.ts +28 -9
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/frontmatter-sweep.ts +14 -7
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/injected-block-slugs.ts +9 -3
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/page-index.ts +29 -10
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/page-store.ts +35 -12
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/prompts/consolidation.ts +14 -8
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/prompts/sweep.ts +4 -1
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/qdrant.ts +96 -36
- package/src/plugins/defaults/memory/substrate/reembed-job.ts +54 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/sim.ts +26 -15
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/skill-content.ts +1 -1
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/skill-store.ts +13 -8
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/sparse-bm25.ts +27 -10
- package/src/plugins/defaults/memory/substrate/spread.ts +165 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/static-context.ts +12 -7
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/sweep-job.ts +20 -15
- package/src/plugins/defaults/memory/substrate/tuning.ts +93 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/types.ts +7 -4
- package/src/plugins/defaults/memory/tools.test.ts +1 -1
- package/src/plugins/defaults/memory/tools.ts +1 -1
- package/src/plugins/defaults/memory/v1/README.md +5 -0
- package/src/plugins/defaults/memory/{__tests__ → v1/__tests__}/filing-jobs.test.ts +4 -4
- package/src/plugins/defaults/memory/{filing-jobs.ts → v1/filing-jobs.ts} +3 -3
- package/src/plugins/defaults/memory/{graph → v1/graph}/bootstrap.test.ts +68 -6
- package/src/plugins/defaults/memory/{graph → v1/graph}/bootstrap.ts +40 -21
- package/src/plugins/defaults/memory/{graph → v1/graph}/consolidation.ts +14 -14
- package/src/plugins/defaults/memory/{graph → v1/graph}/decay.test.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/decay.ts +3 -3
- package/src/plugins/defaults/memory/{graph → v1/graph}/extraction-job.ts +5 -5
- package/src/plugins/defaults/memory/{graph → v1/graph}/extraction.test.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/extraction.ts +20 -14
- package/src/plugins/defaults/memory/{graph → v1/graph}/graph-search.test.ts +3 -3
- package/src/plugins/defaults/memory/v1/graph/graph-search.ts +123 -0
- package/src/plugins/defaults/memory/{graph → v1/graph}/injection.test.ts +1 -118
- package/src/plugins/defaults/memory/{graph → v1/graph}/injection.ts +9 -111
- package/src/plugins/defaults/memory/{graph → v1/graph}/narrative.ts +6 -6
- package/src/plugins/defaults/memory/{graph → v1/graph}/pattern-scan.ts +5 -5
- package/src/plugins/defaults/memory/{graph → v1/graph}/retriever.test.ts +135 -42
- package/src/plugins/defaults/memory/{graph → v1/graph}/retriever.ts +40 -22
- package/src/plugins/defaults/memory/{graph → v1/graph}/scoring.test.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/scoring.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/serendipity.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/triggers.test.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/triggers.ts +1 -1
- package/src/plugins/defaults/memory/{identity-context.ts → v1/identity-context.ts} +4 -4
- package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/backfill.ts +6 -6
- package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/embedding.test.ts +6 -6
- package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/embedding.ts +6 -6
- package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/index-maintenance.ts +8 -8
- package/src/plugins/defaults/memory/{jobs → v1/jobs}/embed-pkb-file.test.ts +7 -7
- package/src/plugins/defaults/memory/{jobs → v1/jobs}/embed-pkb-file.ts +5 -5
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/autoinject.ts +1 -1
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/context.ts +2 -2
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-index.test.ts +3 -3
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-index.ts +2 -2
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-reconcile.test.ts +3 -3
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-reconcile.ts +2 -2
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-search.test.ts +3 -3
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-search.ts +6 -6
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/types.ts +3 -5
- package/src/plugins/defaults/memory/{pkb-schedule.ts → v1/pkb-schedule.ts} +2 -2
- package/src/plugins/defaults/memory/{search/semantic.ts → v1/semantic-search.ts} +1 -1
- package/src/plugins/defaults/memory/v2/__tests__/activation-store.test.ts +1 -1
- package/src/plugins/defaults/memory/v2/__tests__/activation.test.ts +11 -274
- package/src/plugins/defaults/memory/v2/__tests__/backfill-jobs.test.ts +9 -131
- package/src/plugins/defaults/memory/v2/__tests__/harness-compare.test.ts +1 -1
- package/src/plugins/defaults/memory/v2/__tests__/harness-oracle.test.ts +1 -1
- package/src/plugins/defaults/memory/v2/__tests__/harness-replay-input.test.ts +1 -1
- package/src/plugins/defaults/memory/v2/__tests__/injection.test.ts +14 -10
- package/src/plugins/defaults/memory/v2/__tests__/reranker.test.ts +7 -5
- package/src/plugins/defaults/memory/v2/__tests__/router.test.ts +12 -6
- package/src/plugins/defaults/memory/{memory-v2-activation-log-store.ts → v2/activation-log-store.ts} +2 -2
- package/src/plugins/defaults/memory/v2/activation-store.ts +22 -8
- package/src/plugins/defaults/memory/v2/activation.ts +30 -163
- package/src/plugins/defaults/memory/v2/backfill-jobs.ts +7 -54
- package/src/plugins/defaults/memory/{memory-v2-concept-frequency.ts → v2/concept-frequency.ts} +3 -3
- package/src/plugins/defaults/memory/v2/harness/oracle.ts +1 -1
- package/src/plugins/defaults/memory/v2/harness/replay-input.ts +2 -2
- package/src/plugins/defaults/memory/v2/harness/retriever.ts +1 -1
- package/src/plugins/defaults/memory/v2/injection.ts +36 -26
- package/src/plugins/defaults/memory/v2/migration.ts +2 -2
- package/src/plugins/defaults/memory/{rerank-local.ts → v2/rerank-local.ts} +44 -18
- package/src/plugins/defaults/memory/v2/reranker.ts +29 -11
- package/src/plugins/defaults/memory/v2/router.ts +38 -15
- package/src/plugins/defaults/memory/v3/__tests__/candidate-match.test.ts +5 -3
- package/src/plugins/defaults/memory/v3/__tests__/carry-integration.test.ts +21 -8
- package/src/plugins/defaults/memory/v3/__tests__/edge.test.ts +1 -1
- package/src/plugins/defaults/memory/v3/__tests__/live-integration.test.ts +1 -1
- package/src/plugins/defaults/memory/v3/__tests__/maintain-job.test.ts +4 -1
- package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +181 -3
- package/src/plugins/defaults/memory/v3/__tests__/selection-log-store.test.ts +3 -0
- package/src/plugins/defaults/memory/v3/__tests__/shadow-integration.test.ts +14 -5
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +40 -50
- package/src/plugins/defaults/memory/v3/__tests__/tuning-profile.test.ts +1 -0
- package/src/plugins/defaults/memory/v3/candidate-match.ts +2 -2
- package/src/plugins/defaults/memory/v3/capabilities.ts +6 -4
- package/src/plugins/defaults/memory/v3/card.ts +25 -9
- package/src/plugins/defaults/memory/v3/edge.ts +52 -18
- package/src/plugins/defaults/memory/v3/gate.ts +4 -4
- package/src/plugins/defaults/memory/v3/injector.ts +10 -3
- package/src/plugins/defaults/memory/v3/maintain-job.ts +3 -3
- package/src/plugins/defaults/memory/v3/orchestrate.ts +100 -18
- package/src/plugins/defaults/memory/v3/page-content.ts +26 -10
- package/src/plugins/defaults/memory/v3/prune.ts +40 -16
- package/src/plugins/defaults/memory/v3/selection-log-store.ts +34 -12
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +9 -13
- package/src/plugins/defaults/memory/v3/span-query.test.ts +86 -0
- package/src/plugins/defaults/memory/v3/span-query.ts +71 -0
- package/src/plugins/defaults/memory/v3/tuning-profile.ts +3 -0
- package/src/plugins/defaults/memory/v3/types.ts +4 -1
- package/src/plugins/defaults/memory/v3-eval/eval-packets.ts +2 -2
- package/src/plugins/defaults/memory/validation.ts +1 -1
- package/src/plugins/defaults/memory/worker.ts +2 -1
- package/src/plugins/defaults/platform-hosted/__tests__/reengage.test.ts +104 -12
- package/src/plugins/defaults/platform-hosted/routes/reengage.ts +104 -12
- package/src/plugins/types.ts +2 -2
- package/src/prompts/sections.ts +4 -16
- package/src/providers/__tests__/registry-native-web-search.test.ts +47 -2
- package/src/providers/anthropic/client.ts +15 -6
- package/src/providers/content-block-schema.ts +26 -0
- package/src/providers/inference/__tests__/connections-credential-normalize.test.ts +87 -0
- package/src/providers/inference/adapter-factory.ts +6 -0
- package/src/providers/inference/connections.ts +30 -14
- package/src/providers/model-catalog.ts +77 -0
- package/src/providers/openai/__tests__/chat-completions-input-audio.test.ts +260 -0
- package/src/providers/openai/chat-completions-provider.ts +65 -17
- package/src/providers/openai/input-audio.ts +76 -0
- package/src/providers/openrouter/client.ts +0 -2
- package/src/providers/platform-proxy/constants.ts +4 -0
- package/src/providers/poolside/client.ts +42 -0
- package/src/providers/registry.ts +40 -8
- package/src/providers/retry.ts +2 -0
- package/src/providers/types.ts +39 -1
- package/src/providers/vercel-ai-gateway/client.ts +0 -2
- package/src/runtime/AGENTS.md +7 -5
- package/src/runtime/__tests__/question-request-guardian-bridge.test.ts +173 -0
- package/src/runtime/__tests__/question-resolution.test.ts +111 -0
- package/src/runtime/access-request-helper.ts +7 -15
- package/src/runtime/assistant-event-hub.ts +43 -31
- package/src/runtime/assistant-event-publish-options.ts +31 -0
- package/src/runtime/assistant-event.ts +19 -30
- package/src/runtime/assistant-stream-state.ts +4 -4
- package/src/runtime/channel-approvals.ts +0 -25
- package/src/runtime/channel-readiness-service.ts +99 -40
- package/src/runtime/channel-retry-sweep.ts +38 -15
- package/src/runtime/confirmation-request-guardian-bridge.ts +4 -0
- package/src/runtime/guardian-reply-router.ts +108 -0
- package/src/runtime/http-server.ts +8 -0
- package/src/runtime/http-types.ts +2 -2
- package/src/runtime/process-role.ts +42 -0
- package/src/runtime/question-request-guardian-bridge.ts +184 -0
- package/src/runtime/question-resolution.ts +153 -0
- package/src/runtime/routes/__tests__/bookmark-routes.test.ts +6 -2
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +1 -1
- package/src/runtime/routes/__tests__/subagents-routes.test.ts +250 -0
- package/src/runtime/routes/__tests__/webhook-routes.test.ts +201 -0
- package/src/runtime/routes/acp-routes.ts +2 -2
- package/src/runtime/routes/bookmark-routes.ts +3 -15
- package/src/runtime/routes/canned-message-complete.ts +2 -2
- package/src/runtime/routes/consolidation-routes.ts +8 -2
- package/src/runtime/routes/conversation-list-routes.ts +3 -19
- package/src/runtime/routes/conversation-management-routes.ts +1 -5
- package/src/runtime/routes/conversation-query-routes.ts +52 -8
- package/src/runtime/routes/conversation-routes.ts +36 -22
- package/src/runtime/routes/credential-request-routes.ts +0 -1
- package/src/runtime/routes/filing-routes.ts +7 -7
- package/src/runtime/routes/global-search-routes.ts +1 -1
- package/src/runtime/routes/guardian-approval-prompt.ts +2 -2
- package/src/runtime/routes/image-generation-routes.ts +12 -9
- package/src/runtime/routes/inbound-message-handler.ts +17 -0
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +50 -0
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +19 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +4 -4
- package/src/runtime/routes/inbound-stages/inbound-content-prep.test.ts +129 -0
- package/src/runtime/routes/inbound-stages/inbound-content-prep.ts +141 -9
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/lifecycle-routes.ts +199 -0
- package/src/runtime/routes/platform-routes.ts +3 -8
- package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +7 -7
- package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +5 -5
- package/src/runtime/routes/question-routes.ts +34 -87
- package/src/runtime/routes/secret-routes.ts +11 -1
- package/src/runtime/routes/settings-routes.ts +8 -18
- package/src/runtime/routes/subagents-routes.ts +35 -8
- package/src/runtime/routes/upgrade-broadcast-routes.ts +4 -5
- package/src/runtime/routes/webhook-routes.ts +89 -30
- package/src/runtime/routes/workspace-routes.test.ts +7 -4
- package/src/runtime/slack-reply-session.test.ts +12 -12
- package/src/runtime/slack-reply-session.ts +17 -17
- package/src/runtime/sync/sync-publisher.test.ts +7 -5
- package/src/runtime/tool-grant-request-helper.ts +4 -0
- package/src/schedule/schedule-store.ts +70 -0
- package/src/schedule/scheduler.ts +27 -0
- package/src/security/AGENTS.md +1 -1
- package/src/security/credential-key.ts +17 -0
- package/src/security/secret-ingress.ts +14 -105
- package/src/security/secret-patterns.ts +8 -139
- package/src/security/secret-scanner.ts +8 -3
- package/src/security/store-path-override.ts +6 -16
- package/src/sequence/store.ts +8 -0
- package/src/signals/emit-event.ts +5 -10
- package/src/signals/event-stream.ts +20 -10
- package/src/subagent/manager.ts +76 -25
- package/src/subagent/notify.ts +8 -0
- package/src/subagent/types.ts +13 -3
- package/src/telegram/__tests__/webhook-health.test.ts +442 -0
- package/src/telegram/webhook-health.ts +478 -0
- package/src/telemetry/AGENTS.md +6 -0
- package/src/telemetry/memory-corpus-size.test.ts +129 -0
- package/src/telemetry/memory-corpus-size.ts +184 -0
- package/src/telemetry/memory-tier-reporter.test.ts +67 -2
- package/src/telemetry/memory-tier-reporter.ts +30 -3
- package/src/tools/__tests__/conversation-group-tool-input-schemas.test.ts +61 -0
- package/src/tools/__tests__/document-tool-input-schemas.test.ts +103 -0
- package/src/tools/__tests__/followup-call-acp-tool-input-schemas.test.ts +125 -0
- package/src/tools/__tests__/schedule-tool-input-schemas.test.ts +83 -0
- package/src/tools/__tests__/subagent-workflow-tool-input-schemas.test.ts +116 -0
- package/src/tools/__tests__/tool-input-schemas.test.ts +192 -0
- package/src/tools/__tests__/tool-schema-drift-harness.ts +142 -0
- package/src/tools/acp/abort.ts +21 -1
- package/src/tools/acp/context.ts +5 -5
- package/src/tools/acp/spawn.test.ts +15 -5
- package/src/tools/acp/spawn.ts +26 -3
- package/src/tools/acp/status.ts +20 -1
- package/src/tools/acp/steer.test.ts +20 -0
- package/src/tools/acp/steer.ts +23 -2
- package/src/tools/apps/resolve-app-id.ts +15 -3
- package/src/tools/ask-question/ask-question-tool.test.ts +65 -0
- package/src/tools/ask-question/ask-question-tool.ts +68 -92
- package/src/tools/browser/browser-screencast.ts +6 -6
- package/src/tools/calls/call-end.ts +24 -3
- package/src/tools/calls/call-start.ts +35 -11
- package/src/tools/calls/call-status.ts +20 -1
- package/src/tools/conversation-groups/group_create.ts +63 -0
- package/src/tools/conversation-groups/group_list.ts +20 -0
- package/src/tools/conversation-groups/group_shared.ts +52 -0
- package/src/tools/conversation-groups/move_to_group.ts +106 -0
- package/src/tools/document/document-comment-tool.test.ts +49 -0
- package/src/tools/document/document-comment-tool.ts +45 -6
- package/src/tools/document/document-tool.ts +142 -24
- package/src/tools/executor.ts +27 -13
- package/src/tools/filesystem/edit.ts +62 -60
- package/src/tools/filesystem/list.ts +36 -29
- package/src/tools/filesystem/read.ts +56 -39
- package/src/tools/filesystem/write.ts +44 -38
- package/src/tools/followups/followup_create.ts +41 -12
- package/src/tools/followups/followup_list.ts +34 -6
- package/src/tools/followups/followup_resolve.ts +26 -4
- package/src/tools/host-filesystem/edit.ts +50 -60
- package/src/tools/host-filesystem/read.ts +45 -39
- package/src/tools/host-filesystem/write.ts +31 -36
- package/src/tools/host-terminal/host-shell.ts +76 -62
- package/src/tools/policy-context.ts +27 -10
- package/src/tools/schedule/create.ts +76 -33
- package/src/tools/schedule/delete.ts +21 -2
- package/src/tools/schedule/list.ts +25 -3
- package/src/tools/schedule/update.ts +105 -48
- package/src/tools/shared/filesystem/path-policy.ts +246 -40
- package/src/tools/shared/zod-tool-schema.ts +117 -0
- package/src/tools/subagent/abort.ts +12 -4
- package/src/tools/subagent/consult-deadline.ts +9 -3
- package/src/tools/subagent/message.ts +21 -5
- package/src/tools/subagent/notify-parent.ts +44 -23
- package/src/tools/subagent/read.ts +15 -4
- package/src/tools/subagent/resolve.ts +26 -4
- package/src/tools/subagent/spawn.ts +37 -13
- package/src/tools/subagent/status.ts +12 -4
- package/src/tools/system/request-permission.ts +35 -26
- package/src/tools/terminal/shell.ts +68 -55
- package/src/tools/tool-approval-handler.ts +327 -53
- package/src/tools/tool-input-schemas.ts +85 -0
- package/src/tools/tool-types.ts +7 -0
- package/src/tools/types.ts +8 -0
- package/src/tools/workflows/manage-workflows.ts +30 -2
- package/src/tools/workflows/run-workflow.test.ts +54 -2
- package/src/tools/workflows/run-workflow.ts +32 -4
- package/src/util/fs-symlinks.ts +30 -0
- package/src/util/log-redact.ts +7 -3
- package/src/util/platform.ts +15 -0
- package/src/vellum-assistant-namespace.d.ts +80 -0
- package/src/watcher/watcher-store.ts +8 -0
- package/src/workflows/leaf-runner.test.ts +104 -2
- package/src/workflows/leaf-runner.ts +31 -6
- package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +2 -2
- package/src/workspace/migrations/134-image-generation-mode-to-provider.ts +128 -0
- package/src/workspace/migrations/135-copy-substrate-tunables.ts +248 -0
- package/src/workspace/migrations/__tests__/135-copy-substrate-tunables.test.ts +446 -0
- package/src/workspace/migrations/__tests__/backfill-v3-leaves.test.ts +2 -2
- package/src/workspace/migrations/registry.ts +4 -0
- package/tsconfig.plugin-api.json +1 -1
- package/src/__tests__/memory-retrieval-budget.test.ts +0 -49
- package/src/__tests__/secret-patterns.test.ts +0 -27
- package/src/config/__tests__/proc-to-skills.test.ts +0 -21
- package/src/config/memory-tier.test.ts +0 -44
- package/src/daemon/message-types/acp.ts +0 -20
- package/src/daemon/message-types/apps.ts +0 -11
- package/src/daemon/message-types/background-tools.ts +0 -14
- package/src/daemon/message-types/bookmarks.ts +0 -13
- package/src/daemon/message-types/contacts.ts +0 -13
- package/src/daemon/message-types/document-comments.ts +0 -14
- package/src/daemon/message-types/documents.ts +0 -13
- package/src/daemon/message-types/home.ts +0 -15
- package/src/daemon/message-types/host-bash.ts +0 -12
- package/src/daemon/message-types/host-cu.ts +0 -10
- package/src/daemon/message-types/host-file.ts +0 -12
- package/src/daemon/message-types/host-transfer.ts +0 -12
- package/src/daemon/message-types/integrations.ts +0 -90
- package/src/daemon/message-types/memory.ts +0 -10
- package/src/daemon/message-types/schedules.ts +0 -14
- package/src/daemon/message-types/settings.ts +0 -17
- package/src/daemon/message-types/subagents.ts +0 -63
- package/src/daemon/message-types/upgrades.ts +0 -14
- package/src/daemon/message-types/workflows.ts +0 -25
- package/src/daemon/message-types/workspace.ts +0 -137
- package/src/live-voice/ack-phrases.ts +0 -58
- package/src/plugins/defaults/memory/retrieval-budget.ts +0 -29
- package/src/plugins/defaults/memory/v3/__tests__/gate-flag.test.ts +0 -69
- package/src/plugins/defaults/memory/v3/gate-flag.ts +0 -20
- package/src/plugins/defaults/memory/v3/substrate/__tests__/memory-v2-startup.test.ts +0 -86
- package/src/plugins/defaults/memory/v3/substrate/memory-v2-startup.test.ts +0 -205
- /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/concept-page-frontmatter-schema.test.ts +0 -0
- /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/consolidation-prompt-flag-gating-guard.test.ts +0 -0
- /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/injected-block-slugs.test.ts +0 -0
- /package/src/plugins/defaults/memory/{v3/substrate → substrate}/cli-command-content.ts +0 -0
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
1
3
|
import { resolveCapabilities } from "../../runtime/capabilities.js";
|
|
2
4
|
import { validateScheduleInferenceProfile } from "../../schedule/inference-profile.js";
|
|
3
5
|
import { validateRruleSetLines } from "../../schedule/recurrence-engine.js";
|
|
@@ -17,6 +19,10 @@ import {
|
|
|
17
19
|
getSchedule,
|
|
18
20
|
updateSchedule,
|
|
19
21
|
} from "../../schedule/schedule-store.js";
|
|
22
|
+
import {
|
|
23
|
+
invalidToolInputResult,
|
|
24
|
+
nullAsOmitted,
|
|
25
|
+
} from "../shared/zod-tool-schema.js";
|
|
20
26
|
import type { ToolContext, ToolExecutionResult } from "../types.js";
|
|
21
27
|
|
|
22
28
|
const VALID_MODES: ScheduleMode[] = ["notify", "execute", "script", "workflow"];
|
|
@@ -26,6 +32,44 @@ const VALID_ROUTING_INTENTS: RoutingIntent[] = [
|
|
|
26
32
|
"all_channels",
|
|
27
33
|
];
|
|
28
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Model-input schema, `safeParse`d at the top of {@link executeScheduleUpdate}.
|
|
37
|
+
* Same in-tool pattern and drift guard as {@link scheduleCreateInputSchema}
|
|
38
|
+
* in `create.ts` — see that schema's doc comment for the framework.
|
|
39
|
+
*
|
|
40
|
+
* Update-specific tolerance notes:
|
|
41
|
+
*
|
|
42
|
+
* - Presence semantics matter here (`input.x !== undefined` gates every
|
|
43
|
+
* update), so fields are plain `.optional()` — no null-to-omitted
|
|
44
|
+
* preprocessing that would silently turn an explicit update into a no-op.
|
|
45
|
+
* - `timezone` and `script` are nullable at runtime though advertised as
|
|
46
|
+
* plain strings: `updateSchedule` persists null as "clear this field".
|
|
47
|
+
* - `timeout_ms` / `inference_profile` advertise null (it reverts to the
|
|
48
|
+
* default); the executor's bespoke handling stays.
|
|
49
|
+
* - `mode`, `routing_intent`, `workflow_name`, and `workflow_args` are
|
|
50
|
+
* deliberately UNDECLARED (loose passthrough): the first two keep bespoke
|
|
51
|
+
* `VALID_*` errors; `workflow_name` has bespoke coercion semantics in the
|
|
52
|
+
* resolution below; `workflow_args` accepts any JSON value.
|
|
53
|
+
*/
|
|
54
|
+
export const scheduleUpdateInputSchema = z.looseObject({
|
|
55
|
+
job_id: nullAsOmitted(z.string()),
|
|
56
|
+
name: z.string().optional(),
|
|
57
|
+
description: z.string().optional(),
|
|
58
|
+
syntax: z.enum(["cron", "rrule"]).optional(),
|
|
59
|
+
expression: z.string().optional(),
|
|
60
|
+
timezone: z.string().nullable().optional(),
|
|
61
|
+
message: z.string().optional(),
|
|
62
|
+
script: z.string().nullable().optional(),
|
|
63
|
+
enabled: z.boolean().optional(),
|
|
64
|
+
routing_hints: z.looseObject({}).nullable().optional(),
|
|
65
|
+
quiet: z.boolean().optional(),
|
|
66
|
+
reuse_conversation: z.boolean().optional(),
|
|
67
|
+
max_retries: z.int().optional(),
|
|
68
|
+
retry_backoff_ms: z.int().optional(),
|
|
69
|
+
timeout_ms: z.int().nullable().optional(),
|
|
70
|
+
inference_profile: z.string().nullable().optional(),
|
|
71
|
+
});
|
|
72
|
+
|
|
29
73
|
export async function executeScheduleUpdate(
|
|
30
74
|
input: Record<string, unknown>,
|
|
31
75
|
context: ToolContext,
|
|
@@ -37,19 +81,26 @@ export async function executeScheduleUpdate(
|
|
|
37
81
|
isError: true,
|
|
38
82
|
};
|
|
39
83
|
}
|
|
40
|
-
const
|
|
41
|
-
if (!
|
|
84
|
+
const parsedInput = scheduleUpdateInputSchema.safeParse(input);
|
|
85
|
+
if (!parsedInput.success) {
|
|
86
|
+
return invalidToolInputResult("schedule_update", parsedInput.error);
|
|
87
|
+
}
|
|
88
|
+
const parsed = parsedInput.data;
|
|
89
|
+
|
|
90
|
+
const jobId = parsed.job_id;
|
|
91
|
+
if (!jobId) {
|
|
42
92
|
return { content: "Error: job_id is required", isError: true };
|
|
43
93
|
}
|
|
44
94
|
|
|
45
|
-
// Prevent changing a one-shot to recurring or vice versa
|
|
46
|
-
|
|
95
|
+
// Prevent changing a one-shot to recurring or vice versa. (`fire_at` is
|
|
96
|
+
// not an advertised update field, so it stays a raw-input read.)
|
|
97
|
+
if (parsed.expression !== undefined || input.fire_at !== undefined) {
|
|
47
98
|
const existing = getSchedule(jobId);
|
|
48
99
|
if (!existing) {
|
|
49
100
|
return { content: `Error: Schedule not found: ${jobId}`, isError: true };
|
|
50
101
|
}
|
|
51
102
|
const isExistingOneShot = existing.expression == null;
|
|
52
|
-
if (isExistingOneShot &&
|
|
103
|
+
if (isExistingOneShot && parsed.expression !== undefined) {
|
|
53
104
|
return {
|
|
54
105
|
content:
|
|
55
106
|
"Error: Cannot change a one-shot schedule to recurring. Delete and recreate instead.",
|
|
@@ -66,10 +117,12 @@ export async function executeScheduleUpdate(
|
|
|
66
117
|
}
|
|
67
118
|
|
|
68
119
|
const updates: Record<string, unknown> = {};
|
|
69
|
-
if (
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
120
|
+
if (parsed.name !== undefined) {
|
|
121
|
+
updates.name = parsed.name;
|
|
122
|
+
}
|
|
123
|
+
if (parsed.description !== undefined) {
|
|
124
|
+
const description = parsed.description;
|
|
125
|
+
if (description.trim().length === 0) {
|
|
73
126
|
return {
|
|
74
127
|
content: "Error: description must be a non-empty string when provided",
|
|
75
128
|
isError: true,
|
|
@@ -77,10 +130,18 @@ export async function executeScheduleUpdate(
|
|
|
77
130
|
}
|
|
78
131
|
updates.description = description;
|
|
79
132
|
}
|
|
80
|
-
if (
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
if (
|
|
133
|
+
if (parsed.timezone !== undefined) {
|
|
134
|
+
updates.timezone = parsed.timezone;
|
|
135
|
+
}
|
|
136
|
+
if (parsed.message !== undefined) {
|
|
137
|
+
updates.message = parsed.message;
|
|
138
|
+
}
|
|
139
|
+
if (parsed.script !== undefined) {
|
|
140
|
+
updates.script = parsed.script;
|
|
141
|
+
}
|
|
142
|
+
if (parsed.enabled !== undefined) {
|
|
143
|
+
updates.enabled = parsed.enabled;
|
|
144
|
+
}
|
|
84
145
|
|
|
85
146
|
// Mode validation and pass-through
|
|
86
147
|
if (input.mode !== undefined) {
|
|
@@ -118,81 +179,77 @@ export async function executeScheduleUpdate(
|
|
|
118
179
|
}
|
|
119
180
|
|
|
120
181
|
// Routing hints pass-through
|
|
121
|
-
if (
|
|
122
|
-
updates.routingHints =
|
|
182
|
+
if (parsed.routing_hints !== undefined) {
|
|
183
|
+
updates.routingHints = parsed.routing_hints;
|
|
123
184
|
}
|
|
124
185
|
|
|
125
186
|
// Quiet mode
|
|
126
|
-
if (
|
|
127
|
-
updates.quiet =
|
|
187
|
+
if (parsed.quiet !== undefined) {
|
|
188
|
+
updates.quiet = parsed.quiet;
|
|
128
189
|
}
|
|
129
190
|
|
|
130
191
|
// Conversation reuse
|
|
131
|
-
if (
|
|
132
|
-
updates.reuseConversation =
|
|
192
|
+
if (parsed.reuse_conversation !== undefined) {
|
|
193
|
+
updates.reuseConversation = parsed.reuse_conversation;
|
|
133
194
|
}
|
|
134
195
|
|
|
135
196
|
// Retry policy
|
|
136
|
-
if (
|
|
137
|
-
updates.maxRetries =
|
|
197
|
+
if (parsed.max_retries !== undefined) {
|
|
198
|
+
updates.maxRetries = parsed.max_retries;
|
|
138
199
|
}
|
|
139
|
-
if (
|
|
140
|
-
updates.retryBackoffMs =
|
|
200
|
+
if (parsed.retry_backoff_ms !== undefined) {
|
|
201
|
+
updates.retryBackoffMs = parsed.retry_backoff_ms;
|
|
141
202
|
}
|
|
142
203
|
|
|
143
204
|
// Inference profile override (null clears it, reverting to the default
|
|
144
205
|
// main-agent model selection)
|
|
145
|
-
if (
|
|
146
|
-
if (
|
|
206
|
+
if (parsed.inference_profile !== undefined) {
|
|
207
|
+
if (parsed.inference_profile === null) {
|
|
147
208
|
updates.inferenceProfile = null;
|
|
148
209
|
} else {
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
content: "Error: inference_profile must be a string or null",
|
|
153
|
-
isError: true,
|
|
154
|
-
};
|
|
155
|
-
}
|
|
156
|
-
const profileError = validateScheduleInferenceProfile(inferenceProfile);
|
|
210
|
+
const profileError = validateScheduleInferenceProfile(
|
|
211
|
+
parsed.inference_profile,
|
|
212
|
+
);
|
|
157
213
|
if (profileError) {
|
|
158
214
|
return { content: `Error: ${profileError}`, isError: true };
|
|
159
215
|
}
|
|
160
|
-
updates.inferenceProfile =
|
|
216
|
+
updates.inferenceProfile = parsed.inference_profile;
|
|
161
217
|
}
|
|
162
218
|
}
|
|
163
219
|
|
|
164
220
|
// Script execution timeout override (null clears it, reverting to default)
|
|
165
|
-
if (
|
|
166
|
-
if (
|
|
221
|
+
if (parsed.timeout_ms !== undefined) {
|
|
222
|
+
if (parsed.timeout_ms === null) {
|
|
167
223
|
updates.timeoutMs = null;
|
|
168
224
|
} else {
|
|
169
|
-
const
|
|
170
|
-
const timeoutError = validateScriptTimeoutMs(timeoutMs);
|
|
225
|
+
const timeoutError = validateScriptTimeoutMs(parsed.timeout_ms);
|
|
171
226
|
if (timeoutError) {
|
|
172
227
|
return { content: `Error: ${timeoutError}`, isError: true };
|
|
173
228
|
}
|
|
174
|
-
updates.timeoutMs =
|
|
229
|
+
updates.timeoutMs = parsed.timeout_ms;
|
|
175
230
|
}
|
|
176
231
|
}
|
|
177
232
|
|
|
178
233
|
// Auto-detect syntax when expression changes without explicit syntax
|
|
179
|
-
if (
|
|
234
|
+
if (parsed.expression !== undefined || parsed.syntax !== undefined) {
|
|
180
235
|
const resolved = normalizeScheduleSyntax({
|
|
181
|
-
syntax:
|
|
182
|
-
expression:
|
|
236
|
+
syntax: parsed.syntax,
|
|
237
|
+
expression: parsed.expression,
|
|
183
238
|
});
|
|
184
239
|
if (resolved) {
|
|
185
240
|
updates.syntax = resolved.syntax;
|
|
186
241
|
updates.expression = resolved.expression;
|
|
187
|
-
} else if (
|
|
188
|
-
updates.expression =
|
|
189
|
-
const detected = detectScheduleSyntax(
|
|
190
|
-
if (detected)
|
|
242
|
+
} else if (parsed.expression !== undefined) {
|
|
243
|
+
updates.expression = parsed.expression;
|
|
244
|
+
const detected = detectScheduleSyntax(parsed.expression);
|
|
245
|
+
if (detected) {
|
|
246
|
+
updates.syntax = detected;
|
|
247
|
+
}
|
|
191
248
|
}
|
|
192
249
|
// When only syntax is provided (no expression), normalizeScheduleSyntax returns null
|
|
193
250
|
// but we still need to persist the explicit syntax value.
|
|
194
|
-
if (
|
|
195
|
-
updates.syntax =
|
|
251
|
+
if (parsed.syntax !== undefined && updates.syntax === undefined) {
|
|
252
|
+
updates.syntax = parsed.syntax;
|
|
196
253
|
}
|
|
197
254
|
}
|
|
198
255
|
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { realpathSync } from "node:fs";
|
|
2
|
+
import { homedir, userInfo } from "node:os";
|
|
2
3
|
import {
|
|
3
4
|
basename,
|
|
4
5
|
dirname,
|
|
@@ -8,6 +9,10 @@ import {
|
|
|
8
9
|
resolve,
|
|
9
10
|
} from "node:path";
|
|
10
11
|
|
|
12
|
+
import { getIsContainerized } from "../../../config/env-registry.js";
|
|
13
|
+
import { resolveTrailingLinkTarget } from "../../../util/fs-symlinks.js";
|
|
14
|
+
import { getDotEnvPath } from "../../../util/platform.js";
|
|
15
|
+
|
|
11
16
|
/**
|
|
12
17
|
* Result type shared by both sandbox and host path policies.
|
|
13
18
|
*/
|
|
@@ -48,12 +53,15 @@ const CONTAINER_WORKSPACE_EXACT = "/workspace";
|
|
|
48
53
|
/**
|
|
49
54
|
* Resolve symlinks in an absolute path.
|
|
50
55
|
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
56
|
+
* A trailing (possibly dangling) symlink chain is followed first — see
|
|
57
|
+
* {@link resolveTrailingLinkTarget} — so a link whose destination does not
|
|
58
|
+
* exist yet still reports that destination. For an existing path, returns
|
|
59
|
+
* its `realpathSync`. For a path that does not exist yet (e.g. a
|
|
60
|
+
* `file_write` target), walks up to the nearest existing ancestor, resolves
|
|
61
|
+
* that ancestor via `realpathSync`, then re-appends the trailing
|
|
62
|
+
* (non-existent) components — so a symlink anywhere in the existing prefix
|
|
63
|
+
* is still followed. Falls back to the lexical input when nothing on the
|
|
64
|
+
* path resolves (e.g. the path lives on a filesystem this process cannot
|
|
57
65
|
* see, as with host_file paths proxied to a remote client).
|
|
58
66
|
*
|
|
59
67
|
* Used both for sandbox-boundary enforcement and to canonicalize paths before
|
|
@@ -61,7 +69,7 @@ const CONTAINER_WORKSPACE_EXACT = "/workspace";
|
|
|
61
69
|
* file operation.
|
|
62
70
|
*/
|
|
63
71
|
export function resolveRealPath(absolutePath: string): string {
|
|
64
|
-
let current = absolutePath;
|
|
72
|
+
let current = resolveTrailingLinkTarget(absolutePath);
|
|
65
73
|
const trailing: string[] = [];
|
|
66
74
|
while (current !== dirname(current)) {
|
|
67
75
|
try {
|
|
@@ -79,26 +87,25 @@ export function resolveRealPath(absolutePath: string): string {
|
|
|
79
87
|
// Sandbox policy
|
|
80
88
|
// ---------------------------------------------------------------------------
|
|
81
89
|
|
|
90
|
+
interface SandboxTarget {
|
|
91
|
+
/** Lexically resolved absolute path (boundary-relative input resolved). */
|
|
92
|
+
resolved: string;
|
|
93
|
+
/** Symlink-canonicalized form of `resolved`. */
|
|
94
|
+
realResolved: string;
|
|
95
|
+
/** Symlink-canonicalized boundary directory. */
|
|
96
|
+
realBoundary: string;
|
|
97
|
+
}
|
|
98
|
+
|
|
82
99
|
/**
|
|
83
|
-
* Resolve a user-supplied path against
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
* For existing paths, symlinks are resolved via realpathSync so a symlink
|
|
87
|
-
* pointing outside the boundary is caught. For new paths (e.g. file_write),
|
|
88
|
-
* pass `mustExist: false` - the nearest existing ancestor directory is
|
|
89
|
-
* resolved via realpathSync to catch symlinks in parent dirs.
|
|
90
|
-
*
|
|
91
|
-
* Paths starting with `/workspace/` are treated as container-scoped and
|
|
92
|
-
* remapped relative to the boundary directory (the Docker sandbox mounts
|
|
93
|
-
* the host workspace at /workspace).
|
|
100
|
+
* Resolve a user-supplied path against the boundary directory: apply the
|
|
101
|
+
* container /workspace remap, resolve to an absolute path, and canonicalize
|
|
102
|
+
* symlinks on both the target and the boundary.
|
|
94
103
|
*/
|
|
95
|
-
|
|
104
|
+
function resolveSandboxTarget(
|
|
96
105
|
rawPath: string,
|
|
97
106
|
boundaryDir: string,
|
|
98
|
-
|
|
99
|
-
):
|
|
100
|
-
const mustExist = options?.mustExist ?? true;
|
|
101
|
-
|
|
107
|
+
mustExist: boolean,
|
|
108
|
+
): SandboxTarget {
|
|
102
109
|
// Remap container-scoped /workspace paths to the host boundary dir.
|
|
103
110
|
// Skip remapping if the path already starts with boundaryDir to avoid
|
|
104
111
|
// double-nesting (e.g. /workspace/project/file.ts → /workspace/project/project/file.ts
|
|
@@ -114,19 +121,24 @@ export function sandboxPolicy(
|
|
|
114
121
|
|
|
115
122
|
const resolved = resolve(boundaryDir, effectivePath);
|
|
116
123
|
|
|
124
|
+
// Follow a trailing (possibly dangling) symlink chain first — a write
|
|
125
|
+
// through a dangling link creates the link's destination, so the
|
|
126
|
+
// containment and denial checks below must run against it.
|
|
127
|
+
const linkTarget = resolveTrailingLinkTarget(resolved);
|
|
128
|
+
|
|
117
129
|
// Resolve symlinks to catch symlink-based escapes.
|
|
118
130
|
// For mustExist=false, walk up to the nearest existing ancestor and
|
|
119
131
|
// resolve it, then re-append the trailing components.
|
|
120
|
-
let realResolved =
|
|
132
|
+
let realResolved = linkTarget;
|
|
121
133
|
if (mustExist) {
|
|
122
134
|
try {
|
|
123
|
-
realResolved = realpathSync(
|
|
135
|
+
realResolved = realpathSync(linkTarget);
|
|
124
136
|
} catch {
|
|
125
137
|
// File doesn't exist - will be caught by the tool's own existence check
|
|
126
|
-
realResolved =
|
|
138
|
+
realResolved = linkTarget;
|
|
127
139
|
}
|
|
128
140
|
} else {
|
|
129
|
-
realResolved = resolveRealPath(
|
|
141
|
+
realResolved = resolveRealPath(linkTarget);
|
|
130
142
|
}
|
|
131
143
|
|
|
132
144
|
// Resolve the boundary directory's real path too (in case it's a symlink)
|
|
@@ -137,26 +149,220 @@ export function sandboxPolicy(
|
|
|
137
149
|
realBoundary = boundaryDir;
|
|
138
150
|
}
|
|
139
151
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
return {
|
|
143
|
-
ok: false,
|
|
144
|
-
reason: "out_of_bounds",
|
|
145
|
-
error: `Path "${rawPath}" resolves to "${realResolved}" which is outside the working directory "${realBoundary}"`,
|
|
146
|
-
};
|
|
147
|
-
}
|
|
152
|
+
return { resolved, realResolved, realBoundary };
|
|
153
|
+
}
|
|
148
154
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
155
|
+
/** Whether the canonicalized target escapes the canonicalized boundary. */
|
|
156
|
+
function isOutOfBounds(target: SandboxTarget): boolean {
|
|
157
|
+
const rel = relative(target.realBoundary, target.realResolved);
|
|
158
|
+
return (
|
|
159
|
+
rel.startsWith("..") ||
|
|
160
|
+
resolve(target.realBoundary, rel) !== target.realResolved
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function outOfBoundsFailure(
|
|
165
|
+
rawPath: string,
|
|
166
|
+
target: SandboxTarget,
|
|
167
|
+
): PathResult {
|
|
168
|
+
return {
|
|
169
|
+
ok: false,
|
|
170
|
+
reason: "out_of_bounds",
|
|
171
|
+
error: `Path "${rawPath}" resolves to "${target.realResolved}" which is outside the working directory "${target.realBoundary}"`,
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// The denied check covers both the logical path and the symlink-resolved
|
|
176
|
+
// path so a symlink with a non-denied name pointing at a denied file is
|
|
177
|
+
// still caught.
|
|
178
|
+
function deniedFailure(target: SandboxTarget): PathResult | null {
|
|
179
|
+
if (
|
|
180
|
+
isDeniedBasename(target.resolved) ||
|
|
181
|
+
isDeniedBasename(target.realResolved)
|
|
182
|
+
) {
|
|
152
183
|
return {
|
|
153
184
|
ok: false,
|
|
154
185
|
reason: "denied",
|
|
155
|
-
error: `Access to "${basename(resolved)}" is denied`,
|
|
186
|
+
error: `Access to "${basename(target.resolved)}" is denied`,
|
|
156
187
|
};
|
|
157
188
|
}
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function safeUserInfoHomedir(): string {
|
|
193
|
+
try {
|
|
194
|
+
return userInfo().homedir;
|
|
195
|
+
} catch {
|
|
196
|
+
return "";
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
const SECURITY_DIR_ENV_VARS = [
|
|
201
|
+
"GATEWAY_SECURITY_DIR",
|
|
202
|
+
"CREDENTIAL_SECURITY_DIR",
|
|
203
|
+
] as const;
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Secret-bearing paths the file tools must never touch, in any policy:
|
|
207
|
+
*
|
|
208
|
+
* - Gateway trust material and token signing keys (GATEWAY_SECURITY_DIR)
|
|
209
|
+
* and CES credential keys (CREDENTIAL_SECURITY_DIR — `keys.enc`,
|
|
210
|
+
* `store.key`). The daemon must never read from or write to them — that
|
|
211
|
+
* data flows through the gateway and CES APIs (root AGENTS.md). The
|
|
212
|
+
* env-based resolution mirrors the owning services', since the
|
|
213
|
+
* cross-package import boundary bars importing it; the shared bare-metal
|
|
214
|
+
* default `<home>/.vellum/protected` is always denied. Only absolute
|
|
215
|
+
* overrides join the set — a relative override is unmirrorable and
|
|
216
|
+
* disables the host fallback outright (see
|
|
217
|
+
* {@link securityDirConfigMirrorable}).
|
|
218
|
+
* - The daemon dotenv (`<vellumRoot>/.env`), which carries provider
|
|
219
|
+
* secrets.
|
|
220
|
+
*/
|
|
221
|
+
function getProtectedServicePaths(): string[] {
|
|
222
|
+
const paths = new Set<string>();
|
|
223
|
+
paths.add(
|
|
224
|
+
join(
|
|
225
|
+
process.env.HOME || safeUserInfoHomedir() || homedir(),
|
|
226
|
+
".vellum",
|
|
227
|
+
"protected",
|
|
228
|
+
),
|
|
229
|
+
);
|
|
230
|
+
for (const name of SECURITY_DIR_ENV_VARS) {
|
|
231
|
+
const override = process.env[name]?.trim();
|
|
232
|
+
if (override && isAbsolute(override)) {
|
|
233
|
+
paths.add(resolve(override));
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
paths.add(getDotEnvPath());
|
|
237
|
+
return [...paths];
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Whether the security-dir deny set can be mirrored faithfully. A relative
|
|
242
|
+
* override resolves against the owning service's cwd, which this process
|
|
243
|
+
* cannot know — the true directory would be absent from the deny set, so
|
|
244
|
+
* the host fallback fails closed to the hard boundary instead.
|
|
245
|
+
*/
|
|
246
|
+
function securityDirConfigMirrorable(): boolean {
|
|
247
|
+
return SECURITY_DIR_ENV_VARS.every((name) => {
|
|
248
|
+
const override = process.env[name]?.trim();
|
|
249
|
+
return !override || isAbsolute(override);
|
|
250
|
+
});
|
|
251
|
+
}
|
|
158
252
|
|
|
159
|
-
|
|
253
|
+
function isWithinDir(path: string, dir: string): boolean {
|
|
254
|
+
const normalized = dir !== "/" && dir.endsWith("/") ? dir.slice(0, -1) : dir;
|
|
255
|
+
if (normalized === "/") {
|
|
256
|
+
return isAbsolute(path);
|
|
257
|
+
}
|
|
258
|
+
return path === normalized || path.startsWith(normalized + "/");
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Deny a target that lands in (or on) a protected service path. Both the
|
|
263
|
+
* lexical and symlink-resolved target are checked against both the lexical
|
|
264
|
+
* and symlink-resolved protected path, so neither a symlinked target nor a
|
|
265
|
+
* symlinked directory prefix can mask the hit.
|
|
266
|
+
*/
|
|
267
|
+
function securityDirDenial(target: SandboxTarget): PathResult | null {
|
|
268
|
+
for (const protectedPath of getProtectedServicePaths()) {
|
|
269
|
+
const realProtectedPath = resolveRealPath(protectedPath);
|
|
270
|
+
const hit = [target.resolved, target.realResolved].some(
|
|
271
|
+
(path) =>
|
|
272
|
+
isWithinDir(path, protectedPath) ||
|
|
273
|
+
isWithinDir(path, realProtectedPath),
|
|
274
|
+
);
|
|
275
|
+
if (hit) {
|
|
276
|
+
return {
|
|
277
|
+
ok: false,
|
|
278
|
+
reason: "denied",
|
|
279
|
+
error: "Access to the service security directory is denied",
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function evaluateSandboxPolicy(
|
|
287
|
+
rawPath: string,
|
|
288
|
+
boundaryDir: string,
|
|
289
|
+
options: { mustExist?: boolean } | undefined,
|
|
290
|
+
allowOutOfBounds: boolean,
|
|
291
|
+
): PathResult {
|
|
292
|
+
const target = resolveSandboxTarget(
|
|
293
|
+
rawPath,
|
|
294
|
+
boundaryDir,
|
|
295
|
+
options?.mustExist ?? true,
|
|
296
|
+
);
|
|
297
|
+
|
|
298
|
+
if (!allowOutOfBounds && isOutOfBounds(target)) {
|
|
299
|
+
return outOfBoundsFailure(rawPath, target);
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
// Applied unconditionally — even a boundary configured to contain a
|
|
303
|
+
// service security dir must not expose it through the file tools.
|
|
304
|
+
const securityDenied = securityDirDenial(target);
|
|
305
|
+
if (securityDenied) {
|
|
306
|
+
return securityDenied;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
const denied = deniedFailure(target);
|
|
310
|
+
if (denied) {
|
|
311
|
+
return denied;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return { ok: true, resolved: target.resolved };
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Resolve a user-supplied path against a boundary directory and verify
|
|
319
|
+
* that the result stays within it.
|
|
320
|
+
*
|
|
321
|
+
* For existing paths, symlinks are resolved via realpathSync so a symlink
|
|
322
|
+
* pointing outside the boundary is caught. For new paths (e.g. file_write),
|
|
323
|
+
* pass `mustExist: false` - the nearest existing ancestor directory is
|
|
324
|
+
* resolved via realpathSync to catch symlinks in parent dirs.
|
|
325
|
+
*
|
|
326
|
+
* Paths starting with `/workspace/` are treated as container-scoped and
|
|
327
|
+
* remapped relative to the boundary directory (the Docker sandbox mounts
|
|
328
|
+
* the host workspace at /workspace).
|
|
329
|
+
*/
|
|
330
|
+
export function sandboxPolicy(
|
|
331
|
+
rawPath: string,
|
|
332
|
+
boundaryDir: string,
|
|
333
|
+
options?: { mustExist?: boolean },
|
|
334
|
+
): PathResult {
|
|
335
|
+
return evaluateSandboxPolicy(rawPath, boundaryDir, options, false);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Sandbox policy that permits out-of-workspace targets on non-containerized
|
|
340
|
+
* installs.
|
|
341
|
+
*
|
|
342
|
+
* Identical to {@link sandboxPolicy} for in-bounds targets. A target that
|
|
343
|
+
* escapes the boundary is allowed with host-style validation: the basename
|
|
344
|
+
* denylist still applies to both the logical and symlink-resolved paths, and
|
|
345
|
+
* the service security directories stay denied outright.
|
|
346
|
+
* The permission lane runs before tool execution and classifies
|
|
347
|
+
* out-of-workspace file operations as elevated risk (see the gateway
|
|
348
|
+
* FileRiskClassifier), so an escape reaching this policy has already been
|
|
349
|
+
* threshold-approved or user-approved.
|
|
350
|
+
*
|
|
351
|
+
* In containerized mode the boundary stays hard: the container filesystem is
|
|
352
|
+
* not the host, and the host_file_* proxy tools are the escape hatch for the
|
|
353
|
+
* guardian's device.
|
|
354
|
+
*/
|
|
355
|
+
export function sandboxPolicyWithHostFallback(
|
|
356
|
+
rawPath: string,
|
|
357
|
+
boundaryDir: string,
|
|
358
|
+
options?: { mustExist?: boolean },
|
|
359
|
+
): PathResult {
|
|
360
|
+
return evaluateSandboxPolicy(
|
|
361
|
+
rawPath,
|
|
362
|
+
boundaryDir,
|
|
363
|
+
options,
|
|
364
|
+
!getIsContainerized() && securityDirConfigMirrorable(),
|
|
365
|
+
);
|
|
160
366
|
}
|
|
161
367
|
|
|
162
368
|
// ---------------------------------------------------------------------------
|