@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
|
@@ -2,15 +2,33 @@ import { realpathSync } from "node:fs";
|
|
|
2
2
|
import { basename, dirname, normalize, resolve } from "node:path";
|
|
3
3
|
|
|
4
4
|
import { getIsContainerized } from "../config/env-registry.js";
|
|
5
|
+
import { resolveTrailingLinkTarget } from "../util/fs-symlinks.js";
|
|
6
|
+
import {
|
|
7
|
+
getMonitoringDataDir,
|
|
8
|
+
getWorkspaceHooksDir,
|
|
9
|
+
getWorkspacePluginsDir,
|
|
10
|
+
getWorkspaceRoutesDir,
|
|
11
|
+
getWorkspaceSkillsDir,
|
|
12
|
+
getWorkspaceSystemPromptDir,
|
|
13
|
+
getWorkspaceToolsDir,
|
|
14
|
+
getWorkspaceWorkflowsDir,
|
|
15
|
+
} from "../util/platform.js";
|
|
5
16
|
|
|
6
17
|
/**
|
|
7
|
-
* Resolve a path to its canonical form.
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
18
|
+
* Resolve a path to its canonical form. A trailing (possibly dangling)
|
|
19
|
+
* symlink chain is followed first so a link whose destination does not
|
|
20
|
+
* exist yet still canonicalizes to that destination — a write through the
|
|
21
|
+
* link creates it. When the target itself doesn't exist (e.g. a new file
|
|
22
|
+
* being written), walk up to the nearest existing ancestor and append the
|
|
23
|
+
* remaining segments so that symlinks in parent directories (like macOS
|
|
24
|
+
* `/var` -> `/private/var`) are still resolved.
|
|
11
25
|
*/
|
|
12
26
|
function canonicalize(p: string): string {
|
|
13
|
-
const abs = resolve(p);
|
|
27
|
+
const abs = resolveTrailingLinkTarget(resolve(p));
|
|
28
|
+
return canonicalizeExisting(abs);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function canonicalizeExisting(abs: string): string {
|
|
14
32
|
try {
|
|
15
33
|
return realpathSync(abs);
|
|
16
34
|
} catch {
|
|
@@ -21,10 +39,38 @@ function canonicalize(p: string): string {
|
|
|
21
39
|
// Reached filesystem root — nothing left to resolve.
|
|
22
40
|
return normalize(abs);
|
|
23
41
|
}
|
|
24
|
-
return `${
|
|
42
|
+
return `${canonicalizeExisting(parent)}/${name}`;
|
|
25
43
|
}
|
|
26
44
|
}
|
|
27
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Canonicalize a path's directory chain while keeping the final segment as
|
|
48
|
+
* addressed: symlinks among the ancestors (macOS `/var` → `/private/var`, a
|
|
49
|
+
* linked parent directory) resolve, a trailing symlink does not. This is
|
|
50
|
+
* the *name* the daemon acts on — the prompt renderer and the code loaders
|
|
51
|
+
* open control-plane paths by name and follow links while reading, so when
|
|
52
|
+
* the final segment is itself a symlink, a write addressed at it changes
|
|
53
|
+
* what they read even though the bytes land at the link's destination.
|
|
54
|
+
*/
|
|
55
|
+
function canonicalizeAddressedName(p: string): string {
|
|
56
|
+
const abs = resolve(p);
|
|
57
|
+
return `${canonicalizeExisting(dirname(abs))}/${basename(abs)}`;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Whether a canonical path is a canonical directory or falls under it. The
|
|
62
|
+
* trailing separator keeps `/workspace-extra` from matching `/workspace`.
|
|
63
|
+
* Both arguments must already be canonicalized — comparing a canonical path
|
|
64
|
+
* against a lexical directory would re-open the symlink dodge.
|
|
65
|
+
*/
|
|
66
|
+
function isAtOrUnderCanonicalDir(
|
|
67
|
+
canonicalPath: string,
|
|
68
|
+
canonicalDir: string,
|
|
69
|
+
): boolean {
|
|
70
|
+
const prefix = canonicalDir.endsWith("/") ? canonicalDir : `${canonicalDir}/`;
|
|
71
|
+
return canonicalPath === canonicalDir || canonicalPath.startsWith(prefix);
|
|
72
|
+
}
|
|
73
|
+
|
|
28
74
|
/**
|
|
29
75
|
* Resolve a file path to its canonical form (resolving symlinks and
|
|
30
76
|
* normalizing segments like `.` and `..`), then check whether it falls
|
|
@@ -34,19 +80,12 @@ export function isPathWithinWorkspaceRoot(
|
|
|
34
80
|
filePath: string,
|
|
35
81
|
workspaceRoot: string,
|
|
36
82
|
): boolean {
|
|
37
|
-
if (!filePath || !workspaceRoot)
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
// match `/workspace`.
|
|
44
|
-
const rootPrefix = canonicalRoot.endsWith("/")
|
|
45
|
-
? canonicalRoot
|
|
46
|
-
: `${canonicalRoot}/`;
|
|
47
|
-
|
|
48
|
-
return (
|
|
49
|
-
canonicalPath === canonicalRoot || canonicalPath.startsWith(rootPrefix)
|
|
83
|
+
if (!filePath || !workspaceRoot) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
return isAtOrUnderCanonicalDir(
|
|
87
|
+
canonicalize(filePath),
|
|
88
|
+
canonicalize(workspaceRoot),
|
|
50
89
|
);
|
|
51
90
|
}
|
|
52
91
|
|
|
@@ -55,6 +94,14 @@ export function isPathWithinWorkspaceRoot(
|
|
|
55
94
|
/** File-path tools whose workspace-scoped-ness depends on the file_path input. */
|
|
56
95
|
const PATH_SCOPED_TOOLS = new Set(["file_read", "file_write", "file_edit"]);
|
|
57
96
|
|
|
97
|
+
/** Sandbox file tools that write. Reads never plant code. */
|
|
98
|
+
const WORKSPACE_WRITE_TOOLS = new Set(["file_write", "file_edit"]);
|
|
99
|
+
|
|
100
|
+
/** Whether a tool is a sandbox file tool that writes. */
|
|
101
|
+
export function isWorkspaceWriteTool(toolName: string): boolean {
|
|
102
|
+
return WORKSPACE_WRITE_TOOLS.has(toolName);
|
|
103
|
+
}
|
|
104
|
+
|
|
58
105
|
/** Network-accessing tools — never workspace-scoped. */
|
|
59
106
|
const NETWORK_TOOLS = new Set(["web_search", "web_fetch", "network_request"]);
|
|
60
107
|
|
|
@@ -76,6 +123,196 @@ const ALWAYS_SCOPED_TOOLS = new Set([
|
|
|
76
123
|
"ui_dismiss",
|
|
77
124
|
]);
|
|
78
125
|
|
|
126
|
+
// The Docker sandbox mounts the workspace at /workspace, and the model emits
|
|
127
|
+
// container-scoped paths (e.g. "/workspace/tools/evil.ts") even on local
|
|
128
|
+
// turns. The execution-time path policy and the gateway classifier both
|
|
129
|
+
// apply this remap, so every workspace-containment decision here must too.
|
|
130
|
+
const CONTAINER_WORKSPACE_PREFIX = "/workspace/";
|
|
131
|
+
const CONTAINER_WORKSPACE_EXACT = "/workspace";
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Resolve a sandbox file path to its lexical base the same way the
|
|
135
|
+
* execution-time `sandboxPolicy` and the gateway classifier do: remap a
|
|
136
|
+
* container-scoped `/workspace/...` path onto `workingDir`, then resolve
|
|
137
|
+
* (relative paths resolve against `workingDir`, not process.cwd()).
|
|
138
|
+
*/
|
|
139
|
+
export function resolveSandboxBase(
|
|
140
|
+
rawPath: string,
|
|
141
|
+
workingDir: string,
|
|
142
|
+
): string {
|
|
143
|
+
let effectivePath = rawPath;
|
|
144
|
+
if (!rawPath.startsWith(workingDir + "/") && rawPath !== workingDir) {
|
|
145
|
+
if (rawPath.startsWith(CONTAINER_WORKSPACE_PREFIX)) {
|
|
146
|
+
effectivePath = rawPath.slice(CONTAINER_WORKSPACE_PREFIX.length);
|
|
147
|
+
} else if (rawPath === CONTAINER_WORKSPACE_EXACT) {
|
|
148
|
+
effectivePath = ".";
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return resolve(workingDir, effectivePath);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Extract a path-scoped tool's target path from its input. `path` takes
|
|
156
|
+
* priority over `file_path` — the file tools execute `input.path` and the
|
|
157
|
+
* risk classifier reads the fields in the same order, so containment
|
|
158
|
+
* decisions must be derived from the field that actually executes (an input
|
|
159
|
+
* carrying both fields is not runtime-stripped). Returns `""` when the
|
|
160
|
+
* input carries no usable path.
|
|
161
|
+
*/
|
|
162
|
+
function resolvePathScopedTarget(
|
|
163
|
+
toolInput: Record<string, unknown>,
|
|
164
|
+
workspaceRoot: string,
|
|
165
|
+
): string {
|
|
166
|
+
const rawPath =
|
|
167
|
+
typeof toolInput.path === "string"
|
|
168
|
+
? toolInput.path
|
|
169
|
+
: typeof toolInput.file_path === "string"
|
|
170
|
+
? toolInput.file_path
|
|
171
|
+
: "";
|
|
172
|
+
if (rawPath === "") {
|
|
173
|
+
return "";
|
|
174
|
+
}
|
|
175
|
+
return resolveSandboxBase(rawPath, workspaceRoot);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Whether a sandbox file-tool invocation targets a path outside the
|
|
180
|
+
* workspace root. Always false in containerized mode — the execution-time
|
|
181
|
+
* boundary is hard there, so an escaping path never executes. Non-path
|
|
182
|
+
* tools are never classified by this predicate.
|
|
183
|
+
*/
|
|
184
|
+
export function isOutOfWorkspaceFileInvocation(
|
|
185
|
+
toolName: string,
|
|
186
|
+
toolInput: Record<string, unknown>,
|
|
187
|
+
workspaceRoot: string,
|
|
188
|
+
): boolean {
|
|
189
|
+
if (getIsContainerized()) {
|
|
190
|
+
return false;
|
|
191
|
+
}
|
|
192
|
+
if (!PATH_SCOPED_TOOLS.has(toolName)) {
|
|
193
|
+
return false;
|
|
194
|
+
}
|
|
195
|
+
const filePath = resolvePathScopedTarget(toolInput, workspaceRoot);
|
|
196
|
+
return filePath !== "" && !isPathWithinWorkspaceRoot(filePath, workspaceRoot);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* The workspace directories the daemon imports and executes — hooks,
|
|
201
|
+
* plugins, skills, tools, routes, workflows — plus the monitoring data
|
|
202
|
+
* directory, whose source-versions sentinel steers which plugin code the
|
|
203
|
+
* daemon imports. A write to any of them is code that runs later with the
|
|
204
|
+
* daemon's own reach. The list mirrors the file risk classifier's
|
|
205
|
+
* code-injection sinks.
|
|
206
|
+
*/
|
|
207
|
+
function executableSinkDirs(): string[] {
|
|
208
|
+
return [
|
|
209
|
+
getWorkspaceHooksDir(),
|
|
210
|
+
getWorkspacePluginsDir(),
|
|
211
|
+
getWorkspaceSkillsDir(),
|
|
212
|
+
getWorkspaceToolsDir(),
|
|
213
|
+
getWorkspaceRoutesDir(),
|
|
214
|
+
getWorkspaceWorkflowsDir(),
|
|
215
|
+
getMonitoringDataDir(),
|
|
216
|
+
];
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Workspace-root files and directories the prompt renderer reads into the
|
|
221
|
+
* system prompt at render time (`prompts/templates/system-sections.ts`
|
|
222
|
+
* `workspacePath` entries — a drift-guard test walks the real section list
|
|
223
|
+
* against this predicate). A write to any of them rewrites the assistant's
|
|
224
|
+
* standing instructions, per-user context, or per-channel context.
|
|
225
|
+
*/
|
|
226
|
+
const PROMPT_SURFACE_FILES = [
|
|
227
|
+
"IDENTITY.md",
|
|
228
|
+
"SOUL.md",
|
|
229
|
+
"VOICE.md",
|
|
230
|
+
"BOOTSTRAP.md",
|
|
231
|
+
// Read by the heartbeat service as its checklist — instructions executed
|
|
232
|
+
// unattended (`runtime/routes/heartbeat-routes.ts`).
|
|
233
|
+
"HEARTBEAT.md",
|
|
234
|
+
// The scratchpad the heartbeat checklist reads its to-dos from, injected
|
|
235
|
+
// into every full-mode guardian turn by the `now-md` injector
|
|
236
|
+
// (`plugins/defaults/workspace/injectors.ts`). Injector-fed rather than a
|
|
237
|
+
// system section, so the drift guard cannot see it — this entry is the
|
|
238
|
+
// coverage.
|
|
239
|
+
"NOW.md",
|
|
240
|
+
];
|
|
241
|
+
const PROMPT_SURFACE_DIRS = ["users", "channels"];
|
|
242
|
+
|
|
243
|
+
// `memory/**` is deliberately data-plane, not control-plane: memory pages
|
|
244
|
+
// inject into guardian sessions as past-record rather than standing
|
|
245
|
+
// instructions, consolidation owns and rewrites those files, and the gated
|
|
246
|
+
// write path is `remember()` (provenance-checked in the indexer). If direct
|
|
247
|
+
// file writes to memory pages ever become a delegation surface, they join
|
|
248
|
+
// this list.
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Whether a sandbox file-tool invocation writes a workspace control-plane
|
|
252
|
+
* target: an executable sink directory (code the daemon executes) or a
|
|
253
|
+
* prompt surface (instructions it obeys). The two categories are one
|
|
254
|
+
* delegation a layer apart — approving the write approves everything the
|
|
255
|
+
* planted code or rewritten instructions cause later.
|
|
256
|
+
*
|
|
257
|
+
* Unlike {@link isOutOfWorkspaceFileInvocation} this holds in containerized
|
|
258
|
+
* mode too: the workspace boundary is what contains an escaping *path*, and
|
|
259
|
+
* these paths do not escape — the daemon acts on them from inside.
|
|
260
|
+
*
|
|
261
|
+
* Two views of the write are checked against every baseline, because a
|
|
262
|
+
* symlink at either end dodges a single view:
|
|
263
|
+
*
|
|
264
|
+
* - The canonical destination ({@link canonicalize}): a benign-looking name
|
|
265
|
+
* whose trailing link points at a control-plane path is a write to that
|
|
266
|
+
* path, and a lexical check does not see it.
|
|
267
|
+
* - The addressed name ({@link canonicalizeAddressedName}): a control-plane
|
|
268
|
+
* name that is itself a symlink to a benign path still changes what the
|
|
269
|
+
* daemon reads under that name — the renderer and the loaders follow the
|
|
270
|
+
* link — while the destination alone canonicalizes past the surface.
|
|
271
|
+
*
|
|
272
|
+
* The baselines are canonicalized too: a prompt surface may itself be a
|
|
273
|
+
* symlink (SOUL.md → personas/current.md), and the renderer reads through
|
|
274
|
+
* it — so a write to the link's destination must match as well.
|
|
275
|
+
*/
|
|
276
|
+
export function isControlPlaneWorkspaceWrite(
|
|
277
|
+
toolName: string,
|
|
278
|
+
toolInput: Record<string, unknown>,
|
|
279
|
+
workspaceRoot: string,
|
|
280
|
+
): boolean {
|
|
281
|
+
if (!isWorkspaceWriteTool(toolName)) {
|
|
282
|
+
return false;
|
|
283
|
+
}
|
|
284
|
+
const filePath = resolvePathScopedTarget(toolInput, workspaceRoot);
|
|
285
|
+
if (filePath === "") {
|
|
286
|
+
return false;
|
|
287
|
+
}
|
|
288
|
+
const target = canonicalize(filePath);
|
|
289
|
+
const addressed = canonicalizeAddressedName(filePath);
|
|
290
|
+
const root = canonicalize(workspaceRoot);
|
|
291
|
+
const writesUnder = (dir: string): boolean => {
|
|
292
|
+
const canonicalDir = canonicalize(dir);
|
|
293
|
+
return (
|
|
294
|
+
isAtOrUnderCanonicalDir(target, canonicalDir) ||
|
|
295
|
+
isAtOrUnderCanonicalDir(addressed, canonicalDir)
|
|
296
|
+
);
|
|
297
|
+
};
|
|
298
|
+
return (
|
|
299
|
+
executableSinkDirs().some(writesUnder) ||
|
|
300
|
+
PROMPT_SURFACE_FILES.some((file) => {
|
|
301
|
+
const canonicalFile = canonicalize(`${root}/${file}`);
|
|
302
|
+
return target === canonicalFile || addressed === canonicalFile;
|
|
303
|
+
}) ||
|
|
304
|
+
PROMPT_SURFACE_DIRS.some((dir) => writesUnder(`${root}/${dir}`)) ||
|
|
305
|
+
// The system-section override layer: a `<section-id>.md` under
|
|
306
|
+
// `prompts/system/` replaces the bundled section of the same id — or,
|
|
307
|
+
// stripped to nothing, silences it — including the security-policy
|
|
308
|
+
// sections (credential handling, external content, the non-guardian
|
|
309
|
+
// boundary). A brand-new id adds a workspace-only section, so the whole
|
|
310
|
+
// directory is a prompt surface. The baseline is the getter the renderer
|
|
311
|
+
// itself resolves, like {@link executableSinkDirs}.
|
|
312
|
+
writesUnder(getWorkspaceSystemPromptDir())
|
|
313
|
+
);
|
|
314
|
+
}
|
|
315
|
+
|
|
79
316
|
/**
|
|
80
317
|
* Determine whether a tool invocation only affects resources within the
|
|
81
318
|
* workspace root. This is a conservative classification — unknown tools
|
|
@@ -86,22 +323,18 @@ export function isWorkspaceScopedInvocation(
|
|
|
86
323
|
toolInput: Record<string, unknown>,
|
|
87
324
|
workspaceRoot: string,
|
|
88
325
|
): boolean {
|
|
89
|
-
if (ALWAYS_SCOPED_TOOLS.has(toolName))
|
|
90
|
-
|
|
91
|
-
|
|
326
|
+
if (ALWAYS_SCOPED_TOOLS.has(toolName)) {
|
|
327
|
+
return true;
|
|
328
|
+
}
|
|
329
|
+
if (NETWORK_TOOLS.has(toolName)) {
|
|
330
|
+
return false;
|
|
331
|
+
}
|
|
332
|
+
if (HOST_TOOLS.has(toolName)) {
|
|
333
|
+
return false;
|
|
334
|
+
}
|
|
92
335
|
|
|
93
336
|
if (PATH_SCOPED_TOOLS.has(toolName)) {
|
|
94
|
-
const
|
|
95
|
-
typeof toolInput.file_path === "string"
|
|
96
|
-
? toolInput.file_path
|
|
97
|
-
: typeof toolInput.path === "string"
|
|
98
|
-
? toolInput.path
|
|
99
|
-
: "";
|
|
100
|
-
// Resolve relative paths against workspaceRoot (not process.cwd())
|
|
101
|
-
const filePath =
|
|
102
|
-
rawPath !== "" && !rawPath.startsWith("/")
|
|
103
|
-
? resolve(workspaceRoot, rawPath)
|
|
104
|
-
: rawPath;
|
|
337
|
+
const filePath = resolvePathScopedTarget(toolInput, workspaceRoot);
|
|
105
338
|
return (
|
|
106
339
|
filePath !== "" && isPathWithinWorkspaceRoot(filePath, workspaceRoot)
|
|
107
340
|
);
|
|
@@ -112,7 +345,9 @@ export function isWorkspaceScopedInvocation(
|
|
|
112
345
|
// bash is NOT workspace-scoped here — path resolution for allowlisted commands is
|
|
113
346
|
// handled upstream in the checker's hasSandboxAutoApprove computation, which validates
|
|
114
347
|
// all path arguments against the workspace root for non-containerized environments.
|
|
115
|
-
if (toolName === "bash")
|
|
348
|
+
if (toolName === "bash") {
|
|
349
|
+
return getIsContainerized();
|
|
350
|
+
}
|
|
116
351
|
|
|
117
352
|
// Unknown tool — conservative default.
|
|
118
353
|
return false;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The quiesce lease is the safety-critical piece of `vellum sleep --wait`:
|
|
3
|
+
* a stuck or misread lease would silently pause heartbeats, schedules, and
|
|
4
|
+
* memory jobs. These tests pin the fail-open contract (missing, malformed,
|
|
5
|
+
* or expired lease reads as "not quiesced") and the TTL clamps.
|
|
6
|
+
*/
|
|
7
|
+
import { beforeEach, describe, expect, test } from "bun:test";
|
|
8
|
+
|
|
9
|
+
import { setMemoryCheckpoint } from "../checkpoints.js";
|
|
10
|
+
import { initializeDb } from "../db-init.js";
|
|
11
|
+
import {
|
|
12
|
+
clearLifecycleQuiesce,
|
|
13
|
+
DEFAULT_QUIESCE_TTL_MS,
|
|
14
|
+
getLifecycleQuiesceUntil,
|
|
15
|
+
isLifecycleQuiesced,
|
|
16
|
+
MAX_QUIESCE_TTL_MS,
|
|
17
|
+
MIN_QUIESCE_TTL_MS,
|
|
18
|
+
setLifecycleQuiesce,
|
|
19
|
+
} from "../lifecycle-quiesce.js";
|
|
20
|
+
import { resetTestTables } from "../raw-query.js";
|
|
21
|
+
|
|
22
|
+
const QUIESCE_KEY = "lifecycle:quiesce_until";
|
|
23
|
+
|
|
24
|
+
await initializeDb();
|
|
25
|
+
|
|
26
|
+
beforeEach(() => {
|
|
27
|
+
resetTestTables("memory_checkpoints");
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
describe("lifecycle-quiesce", () => {
|
|
31
|
+
test("no lease reads as not quiesced (fail-open default)", () => {
|
|
32
|
+
expect(isLifecycleQuiesced()).toBe(false);
|
|
33
|
+
expect(getLifecycleQuiesceUntil()).toBeNull();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
test("setLifecycleQuiesce arms the lease for the requested TTL", () => {
|
|
37
|
+
const before = Date.now();
|
|
38
|
+
const until = setLifecycleQuiesce(DEFAULT_QUIESCE_TTL_MS);
|
|
39
|
+
expect(until).toBeGreaterThanOrEqual(before + DEFAULT_QUIESCE_TTL_MS);
|
|
40
|
+
expect(until).toBeLessThanOrEqual(Date.now() + DEFAULT_QUIESCE_TTL_MS);
|
|
41
|
+
expect(isLifecycleQuiesced()).toBe(true);
|
|
42
|
+
expect(getLifecycleQuiesceUntil()).toBe(until);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test("TTL is clamped to the sane range", () => {
|
|
46
|
+
const beforeMin = Date.now();
|
|
47
|
+
const untilMin = setLifecycleQuiesce(1);
|
|
48
|
+
expect(untilMin).toBeGreaterThanOrEqual(beforeMin + MIN_QUIESCE_TTL_MS);
|
|
49
|
+
|
|
50
|
+
const beforeMax = Date.now();
|
|
51
|
+
const untilMax = setLifecycleQuiesce(Number.MAX_SAFE_INTEGER);
|
|
52
|
+
expect(untilMax).toBeLessThanOrEqual(
|
|
53
|
+
Date.now() + MAX_QUIESCE_TTL_MS + 1_000,
|
|
54
|
+
);
|
|
55
|
+
expect(untilMax).toBeGreaterThanOrEqual(beforeMax + MAX_QUIESCE_TTL_MS);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test("re-arming extends the lease (refresh semantics)", () => {
|
|
59
|
+
const first = setLifecycleQuiesce(MIN_QUIESCE_TTL_MS);
|
|
60
|
+
const second = setLifecycleQuiesce(MAX_QUIESCE_TTL_MS);
|
|
61
|
+
expect(second).toBeGreaterThan(first);
|
|
62
|
+
expect(getLifecycleQuiesceUntil()).toBe(second);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
test("an expired lease reads as not quiesced", () => {
|
|
66
|
+
setMemoryCheckpoint(QUIESCE_KEY, String(Date.now() - 1));
|
|
67
|
+
expect(isLifecycleQuiesced()).toBe(false);
|
|
68
|
+
expect(getLifecycleQuiesceUntil()).toBeNull();
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("a malformed lease value reads as not quiesced (fail-open)", () => {
|
|
72
|
+
setMemoryCheckpoint(QUIESCE_KEY, "not-a-number");
|
|
73
|
+
expect(isLifecycleQuiesced()).toBe(false);
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test("clearLifecycleQuiesce releases an active lease", () => {
|
|
77
|
+
setLifecycleQuiesce(DEFAULT_QUIESCE_TTL_MS);
|
|
78
|
+
expect(isLifecycleQuiesced()).toBe(true);
|
|
79
|
+
clearLifecycleQuiesce();
|
|
80
|
+
expect(isLifecycleQuiesced()).toBe(false);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
@@ -9,6 +9,7 @@ import { mkdirSync, writeFileSync } from "node:fs";
|
|
|
9
9
|
import { join } from "node:path";
|
|
10
10
|
import { describe, expect, test } from "bun:test";
|
|
11
11
|
|
|
12
|
+
import { contentBlockArraySchema } from "../../providers/content-block-schema.js";
|
|
12
13
|
import type { ContentBlock } from "../../providers/types.js";
|
|
13
14
|
import { getWorkspaceDir } from "../../util/platform.js";
|
|
14
15
|
import {
|
|
@@ -170,11 +171,10 @@ describe("resolveMessageContentBlocks", () => {
|
|
|
170
171
|
});
|
|
171
172
|
|
|
172
173
|
test("passes typed blocks outside the union through untouched", () => {
|
|
173
|
-
//
|
|
174
|
-
//
|
|
174
|
+
// A persisted kind the union does not model still passes through: its
|
|
175
|
+
// renderer owns the shape, so repair must not rewrite it.
|
|
175
176
|
const historical = [
|
|
176
177
|
textBlock("kept as-is"),
|
|
177
|
-
{ type: "ui_surface", surfaceType: "call_summary", data: { x: 1 } },
|
|
178
178
|
{ type: "some_retired_block_kind", payload: 1 },
|
|
179
179
|
];
|
|
180
180
|
expect(resolveMessageContentBlocks(JSON.stringify(historical))).toEqual(
|
|
@@ -182,6 +182,61 @@ describe("resolveMessageContentBlocks", () => {
|
|
|
182
182
|
);
|
|
183
183
|
});
|
|
184
184
|
|
|
185
|
+
test("validates ui_surface blocks without entering the repair path", () => {
|
|
186
|
+
// ui_surface is a first-class union member (LUM-2869). Before it was
|
|
187
|
+
// modelled, every read of a row holding a card failed schema validation
|
|
188
|
+
// and paid a per-block repair that changed nothing — the read-path noise
|
|
189
|
+
// that spiked with voice GA. Asserting schema success (not just a clean
|
|
190
|
+
// round trip) is what proves the repair path can no longer fire, since
|
|
191
|
+
// repair passes these blocks through unchanged either way.
|
|
192
|
+
const surfaceRow = [
|
|
193
|
+
{
|
|
194
|
+
type: "ui_surface",
|
|
195
|
+
surfaceId: "call-1",
|
|
196
|
+
surfaceType: "call_summary",
|
|
197
|
+
completed: true,
|
|
198
|
+
display: "inline",
|
|
199
|
+
data: { summaryText: "**Call completed** (42s).", events: [] },
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
type: "text",
|
|
203
|
+
text: "**Call completed** (42s).",
|
|
204
|
+
_surfaceFallback: true,
|
|
205
|
+
},
|
|
206
|
+
];
|
|
207
|
+
expect(contentBlockArraySchema.safeParse(surfaceRow).success).toBe(true);
|
|
208
|
+
// `data` stays opaque and internal riders survive the round trip.
|
|
209
|
+
expect(resolveMessageContentBlocks(JSON.stringify(surfaceRow))).toEqual(
|
|
210
|
+
surfaceRow as unknown as ContentBlock[],
|
|
211
|
+
);
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
test("validates an LLM-emitted surface with an arbitrary display value", () => {
|
|
215
|
+
// Surfaces written by the `ui_show` tool carry whatever the model chose:
|
|
216
|
+
// `CurrentTurnSurface.display` is a bare string, NOT the inline/panel enum
|
|
217
|
+
// of the `ui_surface_show` wire event. Narrowing it here would send every
|
|
218
|
+
// LLM surface back through the per-block repair — the read-path noise this
|
|
219
|
+
// variant exists to stop. Daemon-only riders must survive too.
|
|
220
|
+
const llmSurfaceRow = [
|
|
221
|
+
{
|
|
222
|
+
type: "ui_surface",
|
|
223
|
+
surfaceId: "surface-1",
|
|
224
|
+
surfaceType: "card",
|
|
225
|
+
title: "Pick one",
|
|
226
|
+
data: { title: "Pick one", options: ["a", "b"] },
|
|
227
|
+
actions: [{ id: "a", label: "A" }],
|
|
228
|
+
display: "modal",
|
|
229
|
+
persistent: true,
|
|
230
|
+
toolCallId: "tu-1",
|
|
231
|
+
activationMoment: "commit",
|
|
232
|
+
},
|
|
233
|
+
];
|
|
234
|
+
expect(contentBlockArraySchema.safeParse(llmSurfaceRow).success).toBe(true);
|
|
235
|
+
expect(resolveMessageContentBlocks(JSON.stringify(llmSurfaceRow))).toEqual(
|
|
236
|
+
llmSurfaceRow as unknown as ContentBlock[],
|
|
237
|
+
);
|
|
238
|
+
});
|
|
239
|
+
|
|
185
240
|
test("wraps type-less values in a text block carrying the payload", () => {
|
|
186
241
|
const historical = [{ payload: 1 }, "bare string"];
|
|
187
242
|
expect(resolveMessageContentBlocks(JSON.stringify(historical))).toEqual([
|
|
@@ -677,6 +677,58 @@ interface InsertMessageCoreParams {
|
|
|
677
677
|
* WAL contention. The timestamp is recomputed each attempt so a late
|
|
678
678
|
* retry doesn't persist a stale `updatedAt`.
|
|
679
679
|
*/
|
|
680
|
+
/**
|
|
681
|
+
* Guard: a message whose blocks are ALL `ui_surface` cards is invisible to
|
|
682
|
+
* the model — every provider drops cards when serializing history, and the
|
|
683
|
+
* contract (see `notifications/approval-card-builder.ts`) is that the
|
|
684
|
+
* producer pairs a card with a model-readable sibling block (for cards whose
|
|
685
|
+
* meaning the model needs, a `_surfaceFallback` text block; surfaces appended
|
|
686
|
+
* to a normal turn ride alongside its text/tool blocks and need nothing).
|
|
687
|
+
*
|
|
688
|
+
* Voice call summaries shipped without the sibling and the model silently
|
|
689
|
+
* lost those turns (LUM-2869) — nothing enforced the contract. In tests this
|
|
690
|
+
* throws, so a producer that forgets the pairing fails its own suite before
|
|
691
|
+
* merge; in production it only warns, per the daemon's never-block posture —
|
|
692
|
+
* a degraded card row beats a dropped guardian notification.
|
|
693
|
+
*/
|
|
694
|
+
function warnOnModelInvisibleContent(
|
|
695
|
+
content: string,
|
|
696
|
+
conversationId: string,
|
|
697
|
+
): void {
|
|
698
|
+
// Fast path: the overwhelmingly common non-surface message never parses.
|
|
699
|
+
if (!content.includes('"ui_surface"')) {
|
|
700
|
+
return;
|
|
701
|
+
}
|
|
702
|
+
let parsed: unknown;
|
|
703
|
+
try {
|
|
704
|
+
parsed = JSON.parse(content);
|
|
705
|
+
} catch {
|
|
706
|
+
return; // legacy plain-string content — not this guard's concern
|
|
707
|
+
}
|
|
708
|
+
if (!Array.isArray(parsed) || parsed.length === 0) {
|
|
709
|
+
return;
|
|
710
|
+
}
|
|
711
|
+
const allCards = parsed.every(
|
|
712
|
+
(block) =>
|
|
713
|
+
typeof block === "object" &&
|
|
714
|
+
block !== null &&
|
|
715
|
+
(block as { type?: unknown }).type === "ui_surface",
|
|
716
|
+
);
|
|
717
|
+
if (!allCards) {
|
|
718
|
+
return;
|
|
719
|
+
}
|
|
720
|
+
const surfaceTypes = parsed
|
|
721
|
+
.map((block) => (block as { surfaceType?: unknown }).surfaceType)
|
|
722
|
+
.filter((t): t is string => typeof t === "string");
|
|
723
|
+
const message =
|
|
724
|
+
"Persisting a message whose only content is ui_surface blocks — the model cannot see it. " +
|
|
725
|
+
"Pair the card with a model-readable sibling (e.g. a _surfaceFallback text block).";
|
|
726
|
+
if (process.env.NODE_ENV === "test") {
|
|
727
|
+
throw new Error(`${message} (surfaceTypes: ${surfaceTypes.join(", ")})`);
|
|
728
|
+
}
|
|
729
|
+
log.warn({ conversationId, surfaceTypes }, message);
|
|
730
|
+
}
|
|
731
|
+
|
|
680
732
|
async function insertMessageCore(
|
|
681
733
|
params: InsertMessageCoreParams,
|
|
682
734
|
): Promise<InsertedMessage> {
|
|
@@ -689,6 +741,7 @@ async function insertMessageCore(
|
|
|
689
741
|
clientMessageId,
|
|
690
742
|
id,
|
|
691
743
|
} = params;
|
|
744
|
+
warnOnModelInvisibleContent(content, conversationId);
|
|
692
745
|
const db = getDb();
|
|
693
746
|
// Time-ordered UUIDv7 so server-generated message ids append to the tail of
|
|
694
747
|
// the WITHOUT ROWID `messages` primary key instead of scattering (v4).
|
|
@@ -2721,6 +2774,42 @@ export function isConversationProcessing(id: string): boolean {
|
|
|
2721
2774
|
return row?.processing_started_at != null;
|
|
2722
2775
|
}
|
|
2723
2776
|
|
|
2777
|
+
/**
|
|
2778
|
+
* Conversations currently mid-turn, longest-running first. Throws on a read
|
|
2779
|
+
* failure — drain callers must distinguish "nothing processing" from "could
|
|
2780
|
+
* not read", so this does not degrade to an empty list.
|
|
2781
|
+
*/
|
|
2782
|
+
export function listProcessingConversations(limit = 20): Array<{
|
|
2783
|
+
conversationId: string;
|
|
2784
|
+
title: string | null;
|
|
2785
|
+
originChannel: string | null;
|
|
2786
|
+
originInterface: string | null;
|
|
2787
|
+
processingStartedAt: number;
|
|
2788
|
+
}> {
|
|
2789
|
+
const rows = rawAll<{
|
|
2790
|
+
id: string;
|
|
2791
|
+
title: string | null;
|
|
2792
|
+
origin_channel: string | null;
|
|
2793
|
+
origin_interface: string | null;
|
|
2794
|
+
processing_started_at: number;
|
|
2795
|
+
}>(
|
|
2796
|
+
"conversation:listProcessing",
|
|
2797
|
+
`SELECT id, title, origin_channel, origin_interface, processing_started_at
|
|
2798
|
+
FROM conversations
|
|
2799
|
+
WHERE processing_started_at IS NOT NULL
|
|
2800
|
+
ORDER BY processing_started_at ASC
|
|
2801
|
+
LIMIT ?`,
|
|
2802
|
+
limit,
|
|
2803
|
+
);
|
|
2804
|
+
return rows.map((row) => ({
|
|
2805
|
+
conversationId: row.id,
|
|
2806
|
+
title: row.title,
|
|
2807
|
+
originChannel: row.origin_channel,
|
|
2808
|
+
originInterface: row.origin_interface,
|
|
2809
|
+
processingStartedAt: row.processing_started_at,
|
|
2810
|
+
}));
|
|
2811
|
+
}
|
|
2812
|
+
|
|
2724
2813
|
/**
|
|
2725
2814
|
* Highest stream `seq` whose content is durably persisted to this
|
|
2726
2815
|
* conversation's message rows, read from the `conversations.seq` column. This
|
|
@@ -3161,6 +3250,10 @@ export async function clearAll(): Promise<{
|
|
|
3161
3250
|
await runOrThrow("DELETE FROM tool_invocations");
|
|
3162
3251
|
await runOrThrow("DELETE FROM messages");
|
|
3163
3252
|
await runOrThrow("DELETE FROM conversations");
|
|
3253
|
+
// Subagent lifecycle records reference conversations by id without an FK
|
|
3254
|
+
// cascade; wipe them explicitly so labels/objectives don't survive (or
|
|
3255
|
+
// rehydrate after) a clear-all.
|
|
3256
|
+
await runOrThrow("DELETE FROM subagents");
|
|
3164
3257
|
|
|
3165
3258
|
// The memory feature's relocated conversation-keyed tables lost their main-DB
|
|
3166
3259
|
// cascade. Signal the wipe through the hook rather than reaching into the
|