@vellumai/assistant 0.10.12 → 0.11.0-staging.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +1 -1
- package/ARCHITECTURE.md +4 -5
- package/README.md +1 -1
- package/docs/architecture/memory.md +60 -23
- package/docs/error-handling.md +3 -3
- package/docs/guardian-request-flow.md +112 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +9 -1
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +449 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/channels.ts +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +468 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/app.d.ts +28 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/app.d.ts.map +1 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/index.d.ts +2 -2
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/index.d.ts.map +1 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/index.js.map +1 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/message.d.ts +2 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/dist/events/message.d.ts.map +1 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@slack/types/package.json +1 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +9 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +449 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/channels.ts +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/secret-detection.ts +468 -0
- package/node_modules/@vellumai/gateway-client/package.json +1 -1
- package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +6 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +34 -0
- package/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/channels.test.ts +9 -1
- package/node_modules/@vellumai/service-contracts/src/__tests__/secret-detection.test.ts +449 -0
- package/node_modules/@vellumai/service-contracts/src/channels.ts +1 -0
- package/node_modules/@vellumai/service-contracts/src/secret-detection.ts +468 -0
- package/openapi.yaml +246 -10
- package/package.json +2 -2
- package/src/__tests__/acp-session.test.ts +3 -3
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +3 -0
- package/src/__tests__/anthropic-provider.test.ts +40 -0
- package/src/__tests__/approval-cascade.test.ts +5 -5
- package/src/__tests__/approval-routes-http.test.ts +3 -3
- package/src/__tests__/ask-question-resolver.test.ts +207 -0
- package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +16 -16
- package/src/__tests__/assistant-event-hub-targeted.test.ts +13 -11
- package/src/__tests__/assistant-event-hub.test.ts +13 -11
- package/src/__tests__/assistant-event.test.ts +12 -9
- package/src/__tests__/assistant-feature-flag-guard.test.ts +3 -3
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +1 -1
- package/src/__tests__/assistant-id-boundary-guard.test.ts +0 -58
- package/src/__tests__/assistant-stream-state.test.ts +17 -7
- package/src/__tests__/avatar-identity-sync.test.ts +3 -3
- package/src/__tests__/background-workers-disk-pressure.test.ts +1 -0
- package/src/__tests__/call-conversation-messages.test.ts +134 -18
- package/src/__tests__/call-start-guardian-guard.test.ts +27 -0
- package/src/__tests__/channel-approvals.test.ts +0 -27
- package/src/__tests__/channel-guardian.test.ts +85 -512
- package/src/__tests__/channel-readiness-slack-remote.test.ts +151 -3
- package/src/__tests__/channel-retry-sweep.test.ts +88 -1
- package/src/__tests__/channel-setup-panel-ack.test.ts +12 -9
- package/src/__tests__/chat-reveal-guard-priming.test.ts +31 -34
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +2 -2
- package/src/__tests__/compaction-events.test.ts +8 -8
- package/src/__tests__/config-loader-platform-defaults.test.ts +54 -28
- package/src/__tests__/config-model-image-provider.test.ts +20 -0
- package/src/__tests__/config-schema-memory-substrate.test.ts +306 -0
- package/src/__tests__/config-schema.test.ts +14 -2
- package/src/__tests__/config-set-platform-guard.test.ts +11 -12
- package/src/__tests__/config-sounds-sync.test.ts +4 -4
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +5 -0
- package/src/__tests__/context-search-memory-source.test.ts +1 -1
- package/src/__tests__/context-search-memory-v2-source.test.ts +6 -6
- package/src/__tests__/context-token-estimator.test.ts +54 -1
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +12 -3
- package/src/__tests__/conversation-agent-loop-fatal-cleanup.test.ts +13 -4
- package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +4 -4
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +10 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +22 -13
- package/src/__tests__/conversation-agent-loop.test.ts +39 -30
- package/src/__tests__/conversation-confirmation-signals.test.ts +14 -14
- package/src/__tests__/conversation-evictor.test.ts +49 -0
- package/src/__tests__/conversation-fork-crud.test.ts +1 -1
- package/src/__tests__/conversation-history-web-search.test.ts +1 -1
- package/src/__tests__/conversation-key-store-disk-view.test.ts +5 -5
- package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +5 -5
- package/src/__tests__/conversation-message-sync-tags.test.ts +4 -4
- package/src/__tests__/conversation-queue.test.ts +81 -81
- package/src/__tests__/conversation-routes-enabled-plugins.test.ts +8 -1
- package/src/__tests__/conversation-routes-hidden-queue.test.ts +8 -1
- package/src/__tests__/conversation-routes-slash-commands.test.ts +10 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +29 -2
- package/src/__tests__/conversation-slash-queue.test.ts +11 -11
- package/src/__tests__/conversation-slash-unknown.test.ts +2 -2
- package/src/__tests__/conversation-speed-override.test.ts +2 -2
- package/src/__tests__/conversation-summarize-route.test.ts +9 -0
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +18 -16
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +17 -17
- package/src/__tests__/conversation-surfaces-app-open.test.ts +7 -4
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +7 -7
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +9 -9
- package/src/__tests__/conversation-surfaces-standalone.test.ts +12 -12
- package/src/__tests__/conversation-surfaces-state-update.test.ts +8 -5
- package/src/__tests__/conversation-surfaces-table-action.test.ts +6 -3
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +46 -46
- package/src/__tests__/conversation-sync-tags.test.ts +5 -5
- package/src/__tests__/conversation-wait-for-idle.test.ts +2 -2
- package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -4
- package/src/__tests__/conversation-workspace-injection.test.ts +0 -3
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -3
- package/src/__tests__/copy-composer-tc-templates.test.ts +3 -131
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/daemon-assistant-events.test.ts +14 -15
- package/src/__tests__/db-test-helpers.ts +13 -27
- package/src/__tests__/disk-pressure-routes.test.ts +12 -3
- package/src/__tests__/document-tool-security.test.ts +95 -0
- package/src/__tests__/drain-kick-guard.test.ts +232 -0
- package/src/__tests__/dynamic-skill-background-guard.test.ts +19 -6
- package/src/__tests__/emit-event-signal.test.ts +5 -6
- package/src/__tests__/encrypted-store-test-helpers.ts +10 -20
- package/src/__tests__/events-tail-route.test.ts +6 -4
- package/src/__tests__/feature-flag-test-helpers.ts +10 -20
- package/src/__tests__/file-edit-tool.test.ts +24 -4
- package/src/__tests__/file-list-tool.test.ts +2 -1
- package/src/__tests__/file-read-tool.test.ts +62 -10
- package/src/__tests__/file-write-tool.test.ts +24 -5
- package/src/__tests__/followup-tools.test.ts +58 -0
- package/src/__tests__/gateway-threshold-reader-mock.ts +99 -0
- package/src/__tests__/graph-extraction-event-date.test.ts +1 -1
- package/src/__tests__/guardian-question-mode.test.ts +42 -3
- package/src/__tests__/guardian-reply-router-answer-mode.test.ts +283 -0
- package/src/__tests__/guardian-vellum-destination-pinning.test.ts +221 -0
- package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
- package/src/__tests__/heartbeat-service.test.ts +1 -0
- package/src/__tests__/helpers/native-web-search-harness.ts +10 -10
- package/src/__tests__/host-browser-proxy.test.ts +1 -1
- package/src/__tests__/host-file-edit-tool.test.ts +3 -3
- package/src/__tests__/host-file-read-tool.test.ts +2 -2
- package/src/__tests__/host-file-write-tool.test.ts +7 -3
- package/src/__tests__/host-shell-tool.test.ts +17 -5
- package/src/__tests__/host-transfer-pending-interactions.test.ts +8 -8
- package/src/__tests__/image-credentials.test.ts +65 -8
- package/src/__tests__/injection-block.test.ts +4 -4
- package/src/__tests__/injector-chain.test.ts +1 -1
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +2 -2
- package/src/__tests__/injector-registry-order-guard.test.ts +4 -9
- package/src/__tests__/injector-v3-suppression.test.ts +6 -4
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +27 -28
- package/src/__tests__/list-messages-page-latest.test.ts +2 -2
- package/src/__tests__/llm-usage-store.test.ts +67 -4
- package/src/__tests__/log-redact.test.ts +18 -0
- package/src/__tests__/managed-profile-guard.test.ts +27 -0
- package/src/__tests__/managed-skill-lifecycle.test.ts +2 -2
- package/src/__tests__/media-generate-image.test.ts +62 -11
- package/src/__tests__/memory-identity-context-parity.test.ts +1 -1
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +9 -1
- package/src/__tests__/memory-retrieval-hook.test.ts +4 -4
- package/src/__tests__/notification-decision-strategy.test.ts +115 -11
- package/src/__tests__/notification-deep-link.test.ts +12 -12
- package/src/__tests__/notification-vellum-adapter.test.ts +8 -8
- package/src/__tests__/outbound-slack-persistence.test.ts +8 -8
- package/src/__tests__/path-policy.test.ts +315 -0
- package/src/__tests__/pending-interactions-resolved-event.test.ts +6 -6
- package/src/__tests__/persistence-layering-guard.test.ts +2 -2
- package/src/__tests__/pkb-autoinject.test.ts +1 -1
- package/src/__tests__/platform-bash-auto-approve.test.ts +1 -0
- package/src/__tests__/plugin-event-hub-facade.test.ts +22 -15
- package/src/__tests__/plugin-import-boundary-guard.test.ts +15 -15
- package/src/__tests__/processing-flag-persist-failure.test.ts +0 -4
- package/src/__tests__/provider-platform-proxy-integration.test.ts +0 -1
- package/src/__tests__/rebuild-index-graph-nodes.test.ts +1 -1
- package/src/__tests__/request-secret-standalone-channel-gate.test.ts +5 -5
- package/src/__tests__/require-fresh-approval.test.ts +38 -38
- package/src/__tests__/run-due-schedules.test.ts +72 -1
- package/src/__tests__/runtime-events-sse-parity.test.ts +11 -10
- package/src/__tests__/runtime-events-sse.test.ts +1 -1
- package/src/__tests__/schedule-routes.test.ts +44 -5
- package/src/__tests__/schedule-store.test.ts +3 -3
- package/src/__tests__/schedule-tools.test.ts +176 -0
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +3 -3
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +3 -3
- package/src/__tests__/secret-response-routing.test.ts +3 -3
- package/src/__tests__/secret-routes-platform-proxy.test.ts +4 -7
- package/src/__tests__/secret-scanner.test.ts +36 -0
- package/src/__tests__/send-endpoint-busy.test.ts +7 -7
- package/src/__tests__/slack-required-scopes-mirror.test.ts +81 -0
- package/src/__tests__/starter-task-flow.test.ts +6 -3
- package/src/__tests__/subagent-call-site-routing.test.ts +2 -2
- package/src/__tests__/subagent-disposal.test.ts +40 -11
- package/src/__tests__/subagent-fork-notifications.test.ts +4 -4
- package/src/__tests__/subagent-fork-prompt-role.test.ts +3 -3
- package/src/__tests__/subagent-fork-spawn.test.ts +4 -4
- package/src/__tests__/subagent-manager-notify.test.ts +73 -14
- package/src/__tests__/subagent-notify-parent.test.ts +48 -4
- package/src/__tests__/subagent-spawn-and-await.test.ts +62 -14
- package/src/__tests__/subagent-tools.test.ts +64 -0
- package/src/__tests__/sync-message-contract.test.ts +3 -3
- package/src/__tests__/terminal-tools.test.ts +12 -3
- package/src/__tests__/test-preload.ts +9 -0
- package/src/__tests__/tool-approval-handler.test.ts +583 -43
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +7 -4
- package/src/__tests__/tool-executor.test.ts +116 -0
- package/src/__tests__/tool-grant-request-escalation.test.ts +5 -0
- package/src/__tests__/tool-preview-lifecycle.test.ts +32 -29
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +5 -5
- package/src/__tests__/tool-start-timestamp.test.ts +4 -4
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +9 -22
- package/src/__tests__/ui-choice-copy-surfaces.test.ts +13 -13
- package/src/__tests__/ui-work-result-surface.test.ts +3 -3
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +6 -6
- package/src/__tests__/voice-session-bridge.test.ts +44 -44
- package/src/__tests__/workspace-migration-134-image-generation-mode-to-provider.test.ts +284 -0
- package/src/__tests__/workspace-policy.test.ts +399 -0
- package/src/acp/__tests__/client-handler.test.ts +3 -3
- package/src/acp/__tests__/session-manager-persistence.test.ts +10 -10
- package/src/acp/__tests__/session-manager-resume.test.ts +7 -7
- package/src/acp/client-handler.ts +3 -3
- package/src/acp/session-manager.ts +8 -8
- package/src/api/events/subagent-event.ts +2 -2
- package/src/api/responses/memory-v2-activation-log.ts +2 -2
- package/src/approvals/AGENTS.md +2 -0
- package/src/approvals/guardian-request-resolvers.ts +118 -24
- package/src/calls/__tests__/voice-control-protocol.test.ts +57 -0
- package/src/calls/__tests__/voice-session-bridge.test.ts +158 -4
- package/src/calls/__tests__/voice-triage-escalate.test.ts +3 -4
- package/src/calls/call-controller.ts +27 -27
- package/src/calls/call-conversation-messages.ts +58 -18
- package/src/calls/voice-control-protocol.ts +56 -0
- package/src/calls/voice-session-bridge.ts +156 -58
- package/src/calls/voice-triage-escalate.ts +2 -3
- package/src/channels/config.ts +8 -0
- package/src/channels/types.ts +1 -0
- package/src/cli/commands/config.ts +49 -13
- package/src/cli/commands/memory/index.help.ts +4 -2
- package/src/cli/commands/memory/memory-retrospective.ts +5 -0
- package/src/cli/lib/bundled-marketplace.json +12 -0
- package/src/cli.ts +2 -109
- package/src/config/__tests__/deployment-context-defaults.test.ts +9 -0
- package/src/config/__tests__/substrate-twin-shadowing.test.ts +191 -0
- package/src/config/assistant-feature-flags.ts +1 -1
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +13 -7
- package/src/config/feature-flag-cache.ts +6 -16
- package/src/config/feature-flag-registry.json +14 -30
- package/src/config/loader.ts +7 -1
- package/src/config/memory-tier.ts +15 -10
- package/src/config/memory-v3-gate.test.ts +278 -1
- package/src/config/memory-v3-gate.ts +88 -26
- package/src/config/raw-config-utils.ts +1 -1
- package/src/config/schemas/__tests__/live-voice.test.ts +27 -16
- package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
- package/src/config/schemas/live-voice.ts +33 -7
- package/src/config/schemas/llm.ts +1 -0
- package/src/config/schemas/memory-retrospective.ts +13 -0
- package/src/config/schemas/memory-substrate.ts +183 -0
- package/src/config/schemas/memory-v2.ts +3 -2
- package/src/config/schemas/memory-v3.ts +11 -4
- package/src/config/schemas/memory.ts +35 -1
- package/src/config/schemas/services.ts +10 -2
- package/src/config/substrate-twin-shadowing.ts +195 -0
- package/src/config/webhook-routing.ts +67 -0
- package/src/context/compactor.ts +10 -3
- package/src/context/token-estimator.ts +21 -0
- package/src/daemon/__tests__/channel-ui-capability.test.ts +85 -0
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +3 -3
- package/src/daemon/__tests__/embedding-reconcile.test.ts +3 -3
- package/src/daemon/__tests__/inference-profile-notification.test.ts +3 -6
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +5 -5
- package/src/daemon/__tests__/web-search-status-text.test.ts +2 -2
- package/src/daemon/channel-ui-capability.ts +70 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +4 -4
- package/src/daemon/conversation-agent-loop.ts +12 -5
- package/src/daemon/conversation-evictor.ts +26 -4
- package/src/daemon/conversation-launch.ts +11 -14
- package/src/daemon/conversation-messaging.ts +14 -14
- package/src/daemon/conversation-notifiers.ts +2 -2
- package/src/daemon/conversation-process.ts +133 -21
- package/src/daemon/conversation-queue-manager.ts +7 -7
- package/src/daemon/conversation-runtime-assembly.ts +16 -0
- package/src/daemon/conversation-store.ts +11 -3
- package/src/daemon/conversation-surfaces.ts +4 -4
- package/src/daemon/conversation-tool-setup.ts +13 -7
- package/src/daemon/conversation-usage.ts +12 -11
- package/src/daemon/conversation.ts +38 -15
- package/src/daemon/disk-pressure-guard.ts +5 -12
- package/src/daemon/embedding-reconcile.ts +14 -9
- package/src/daemon/handlers/config-channels.ts +40 -134
- package/src/daemon/handlers/config-model.ts +15 -7
- package/src/daemon/handlers/conversations.ts +4 -2
- package/src/daemon/handlers/shared.ts +29 -0
- package/src/daemon/host-proxy-base.ts +4 -4
- package/src/daemon/lifecycle.ts +13 -0
- package/src/daemon/message-protocol.ts +8 -144
- package/src/daemon/message-types/computer-use.ts +0 -12
- package/src/daemon/message-types/conversations.ts +9 -345
- package/src/daemon/message-types/host-app-control.ts +0 -9
- package/src/daemon/message-types/host-browser.ts +0 -7
- package/src/daemon/message-types/host-ui-snapshot.ts +0 -7
- package/src/daemon/message-types/messages.ts +0 -48
- package/src/daemon/message-types/notifications.ts +0 -7
- package/src/daemon/message-types/skills.ts +0 -5
- package/src/daemon/message-types/surfaces.ts +0 -9
- package/src/daemon/message-types/sync.ts +0 -2
- package/src/daemon/process-message.ts +5 -5
- package/src/daemon/skill-memory-refresh.ts +5 -5
- package/src/daemon/tool-side-effects.ts +13 -13
- package/src/daemon/trust-context.ts +1 -1
- package/src/daemon/wake-conversation-ops.ts +4 -4
- package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +100 -7
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +67 -0
- package/src/heartbeat/heartbeat-run-store.ts +81 -4
- package/src/heartbeat/heartbeat-service.ts +32 -1
- package/src/home/__tests__/feed-writer.test.ts +7 -7
- package/src/home/__tests__/home-content-refresh.test.ts +3 -0
- package/src/home/__tests__/suggested-prompts.test.ts +1 -0
- package/src/home/feed-writer.ts +6 -13
- package/src/home/home-content-refresh.ts +6 -9
- package/src/home/relationship-state-writer.ts +5 -12
- package/src/home/suggested-prompts-cache.ts +6 -19
- package/src/ipc/__tests__/events-publish-client.test.ts +67 -0
- package/src/ipc/events-publish-client.ts +44 -0
- package/src/ipc/routes/__tests__/conversation-sync-ipc-routes.test.ts +2 -2
- package/src/ipc/routes/__tests__/events-ipc-routes.test.ts +38 -9
- package/src/ipc/routes/events-ipc-routes.ts +11 -31
- package/src/live-voice/__tests__/front-decision.test.ts +4 -176
- package/src/live-voice/__tests__/live-voice-agent-turn.test.ts +276 -68
- package/src/live-voice/__tests__/live-voice-events.test.ts +6 -3
- package/src/live-voice/__tests__/live-voice-progress.test.ts +185 -46
- package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +24 -59
- package/src/live-voice/__tests__/live-voice-tts-session.test.ts +38 -54
- package/src/live-voice/__tests__/live-voice-vad.test.ts +218 -422
- package/src/live-voice/front-decision.ts +5 -155
- package/src/live-voice/live-voice-metrics.ts +4 -1
- package/src/live-voice/live-voice-session.ts +650 -333
- package/src/live-voice/progress-phrases.ts +17 -0
- package/src/live-voice/protocol.ts +15 -0
- package/src/media/app-icon-generator.ts +15 -8
- package/src/media/avatar-router.ts +9 -5
- package/src/media/image-credentials.ts +42 -10
- package/src/media/image-service.ts +1 -13
- package/src/media/types.ts +26 -3
- package/src/notifications/AGENTS.md +2 -0
- package/src/notifications/__tests__/broadcaster.test.ts +95 -0
- package/src/notifications/adapters/macos.ts +3 -3
- package/src/notifications/broadcaster.ts +57 -0
- package/src/notifications/copy-composer.ts +0 -15
- package/src/notifications/decision-engine.ts +21 -22
- package/src/notifications/guardian-question-mode.ts +57 -2
- package/src/notifications/home-feed-side-effect.ts +4 -0
- package/src/notifications/signal.ts +6 -4
- package/src/notifications/trusted-contact-payloads.ts +3 -4
- package/src/notifications/vellum-card-affinity.ts +39 -0
- package/src/oauth/AGENTS.md +1 -1
- package/src/permissions/channel-permission-query.test.ts +69 -0
- package/src/permissions/channel-permission-query.ts +73 -1
- package/src/permissions/checker.test.ts +85 -9
- package/src/permissions/checker.ts +17 -22
- package/src/permissions/confirmation-guardian-request.test.ts +2 -2
- package/src/permissions/confirmation-guardian-request.ts +2 -2
- package/src/permissions/gateway-threshold-reader.test.ts +224 -17
- package/src/permissions/gateway-threshold-reader.ts +82 -10
- package/src/permissions/ipc-risk-types.ts +8 -0
- package/src/permissions/prompter.ts +5 -5
- package/src/permissions/question-guardian-request.test.ts +222 -0
- package/src/permissions/question-guardian-request.ts +179 -0
- package/src/permissions/question-prompter.test.ts +8 -8
- package/src/permissions/question-prompter.ts +18 -0
- package/src/permissions/secret-prompter.ts +2 -4
- package/src/permissions/workspace-policy.ts +236 -34
- package/src/persistence/__tests__/lifecycle-quiesce.test.ts +82 -0
- package/src/persistence/__tests__/message-content-file.test.ts +58 -3
- package/src/persistence/conversation-crud.ts +93 -0
- package/src/persistence/conversation-key-store.ts +63 -0
- package/src/persistence/db-async-query.ts +1 -1
- package/src/persistence/db-singleton.ts +14 -27
- package/src/persistence/delivery-crud.ts +45 -0
- package/src/persistence/embeddings/embedding-backend.ts +2 -1
- package/src/persistence/embeddings/embedding-identity.ts +7 -3
- package/src/persistence/job-utils.ts +32 -27
- package/src/persistence/jobs-store.ts +92 -3
- package/src/persistence/lifecycle-quiesce.ts +80 -0
- package/src/persistence/llm-usage-store.ts +45 -8
- package/src/persistence/message-content-file.ts +4 -4
- package/src/persistence/migrations/336-move-memory-v2-activation-logs-to-memory-db.ts +1 -1
- package/src/persistence/migrations/351-schedule-skill-script-handoff.ts +39 -0
- package/src/persistence/migrations/352-drop-schedule-skill-script-handoff.test.ts +83 -0
- package/src/persistence/migrations/352-drop-schedule-skill-script-handoff.ts +36 -0
- package/src/persistence/migrations/353-add-llm-usage-conversation-type.test.ts +110 -0
- package/src/persistence/migrations/353-add-llm-usage-conversation-type.ts +49 -0
- package/src/persistence/schema/infrastructure.ts +11 -0
- package/src/persistence/steps.ts +7 -1
- package/src/plugin-api/__tests__/publish-event-forwarding.test.ts +113 -0
- package/src/plugin-api/__tests__/publish-event.test.ts +57 -0
- package/src/plugin-api/conversation-turn.ts +4 -4
- package/src/plugin-api/event-hub-facade.ts +15 -6
- package/src/plugin-api/index.ts +10 -4
- package/src/plugin-api/publish-event.ts +36 -0
- package/src/plugins/AGENTS.md +2 -0
- package/src/plugins/defaults/compaction/window-manager.ts +9 -0
- package/src/plugins/defaults/index.ts +9 -13
- package/src/plugins/defaults/memory/AGENTS.md +775 -0
- package/src/plugins/defaults/memory/__tests__/capability-seed-embed-gate.test.ts +186 -0
- package/src/plugins/defaults/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +1 -1
- package/src/plugins/defaults/memory/__tests__/indexer-tier-dispatch.test.ts +129 -0
- package/src/plugins/defaults/memory/__tests__/jobs-worker-quiesce-gate.test.ts +91 -0
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v1-graph-substrate-noop.test.ts +342 -0
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +9 -1
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-schedule.test.ts +36 -1
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-sweep-defer.test.ts +9 -1
- package/src/plugins/defaults/memory/__tests__/memory-log-stores-degraded.test.ts +2 -2
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +44 -10
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-sweep.test.ts +151 -10
- package/src/plugins/defaults/memory/__tests__/memory-tier-boundary-guard.test.ts +1155 -0
- package/src/plugins/defaults/memory/__tests__/memory-v2-activation-log-store.test.ts +1 -1
- package/src/plugins/defaults/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -3
- package/src/plugins/defaults/memory/__tests__/tools-delete-memory-page.test.ts +1 -1
- package/src/plugins/defaults/memory/context-search/sources/memory-v2.ts +71 -35
- package/src/plugins/defaults/memory/context-search/sources/memory.ts +5 -1
- package/src/plugins/defaults/memory/fork-conversation-memory.ts +4 -4
- package/src/plugins/defaults/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +80 -10
- package/src/plugins/defaults/memory/graph/__tests__/handle-remember-v2.test.ts +1 -1
- package/src/plugins/defaults/memory/graph/capability-seed.ts +24 -10
- package/src/plugins/defaults/memory/graph/conversation-graph-memory.ts +123 -49
- package/src/plugins/defaults/memory/graph/graph-search.ts +6 -118
- package/src/plugins/defaults/memory/graph/in-context-tracker.test.ts +173 -0
- package/src/plugins/defaults/memory/graph/in-context-tracker.ts +109 -0
- package/src/plugins/defaults/memory/graph/store.ts +1 -0
- package/src/plugins/defaults/memory/graph/tool-handlers.test.ts +1 -1
- package/src/plugins/defaults/memory/graph/tool-handlers.ts +5 -2
- package/src/plugins/defaults/memory/graph-topology/__tests__/build-memory-graph.test.ts +1 -1
- package/src/plugins/defaults/memory/graph-topology/build-memory-graph.ts +6 -9
- package/src/plugins/defaults/memory/hooks/__tests__/user-prompt-submit.test.ts +30 -16
- package/src/plugins/defaults/memory/hooks/user-prompt-submit.ts +18 -14
- package/src/plugins/defaults/memory/indexer.ts +146 -89
- package/src/plugins/defaults/memory/injectors.ts +86 -41
- package/src/plugins/defaults/memory/job-handlers.ts +130 -39
- package/src/plugins/defaults/memory/jobs/__tests__/embed-concept-page.test.ts +2 -2
- package/src/plugins/defaults/memory/jobs/embed-concept-page.ts +22 -10
- package/src/plugins/defaults/memory/jobs-worker.ts +279 -208
- package/src/plugins/defaults/memory/memory-retrospective-enqueue.ts +4 -2
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +40 -3
- package/src/plugins/defaults/memory/memory-retrospective-sweep.ts +99 -11
- package/src/plugins/defaults/memory/src/__tests__/memory-v2-routes.test.ts +5 -3
- package/src/plugins/defaults/memory/src/__tests__/memory-v2-simulate-route.test.ts +3 -4
- package/src/plugins/defaults/memory/src/memory-graph-routes.ts +2 -1
- package/src/plugins/defaults/memory/src/memory-item-routes.test.ts +7 -5
- package/src/plugins/defaults/memory/src/memory-item-routes.ts +51 -19
- package/src/plugins/defaults/memory/src/memory-v2-routes.ts +31 -20
- package/src/plugins/defaults/memory/startup.ts +58 -21
- package/src/plugins/defaults/memory/substrate/__tests__/boot-maintenance.test.ts +335 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/cli-command-store.test.ts +14 -8
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/consolidation-job.test.ts +51 -21
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/edge-index.test.ts +1 -1
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/frontmatter-sweep.test.ts +3 -3
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/page-index.test.ts +1 -1
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/page-store.test.ts +1 -1
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/prompts-consolidation.test.ts +2 -2
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/qdrant.test.ts +23 -14
- package/src/plugins/defaults/memory/substrate/__tests__/reembed-job.test.ts +262 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sim.test.ts +9 -12
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/skill-content.test.ts +2 -2
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/skill-store.test.ts +9 -9
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sparse-bm25.test.ts +12 -5
- package/src/plugins/defaults/memory/substrate/__tests__/spread.test.ts +276 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/static-context.test.ts +17 -8
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/sweep-job.test.ts +9 -9
- package/src/plugins/defaults/memory/{v3/substrate/memory-v2-startup.ts → substrate/boot-maintenance.ts} +43 -24
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/cli-command-store.ts +13 -8
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/consolidation-job.ts +51 -27
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/constants.ts +1 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/edge-index.ts +28 -9
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/frontmatter-sweep.ts +14 -7
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/injected-block-slugs.ts +9 -3
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/page-index.ts +29 -10
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/page-store.ts +35 -12
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/prompts/consolidation.ts +14 -8
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/prompts/sweep.ts +4 -1
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/qdrant.ts +96 -36
- package/src/plugins/defaults/memory/substrate/reembed-job.ts +54 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/sim.ts +26 -15
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/skill-content.ts +1 -1
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/skill-store.ts +13 -8
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/sparse-bm25.ts +27 -10
- package/src/plugins/defaults/memory/substrate/spread.ts +165 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/static-context.ts +12 -7
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/sweep-job.ts +20 -15
- package/src/plugins/defaults/memory/substrate/tuning.ts +93 -0
- package/src/plugins/defaults/memory/{v3/substrate → substrate}/types.ts +7 -4
- package/src/plugins/defaults/memory/tools.test.ts +1 -1
- package/src/plugins/defaults/memory/tools.ts +1 -1
- package/src/plugins/defaults/memory/v1/README.md +5 -0
- package/src/plugins/defaults/memory/{__tests__ → v1/__tests__}/filing-jobs.test.ts +4 -4
- package/src/plugins/defaults/memory/{filing-jobs.ts → v1/filing-jobs.ts} +3 -3
- package/src/plugins/defaults/memory/{graph → v1/graph}/bootstrap.test.ts +68 -6
- package/src/plugins/defaults/memory/{graph → v1/graph}/bootstrap.ts +40 -21
- package/src/plugins/defaults/memory/{graph → v1/graph}/consolidation.ts +14 -14
- package/src/plugins/defaults/memory/{graph → v1/graph}/decay.test.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/decay.ts +3 -3
- package/src/plugins/defaults/memory/{graph → v1/graph}/extraction-job.ts +5 -5
- package/src/plugins/defaults/memory/{graph → v1/graph}/extraction.test.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/extraction.ts +20 -14
- package/src/plugins/defaults/memory/{graph → v1/graph}/graph-search.test.ts +3 -3
- package/src/plugins/defaults/memory/v1/graph/graph-search.ts +123 -0
- package/src/plugins/defaults/memory/{graph → v1/graph}/injection.test.ts +1 -118
- package/src/plugins/defaults/memory/{graph → v1/graph}/injection.ts +9 -111
- package/src/plugins/defaults/memory/{graph → v1/graph}/narrative.ts +6 -6
- package/src/plugins/defaults/memory/{graph → v1/graph}/pattern-scan.ts +5 -5
- package/src/plugins/defaults/memory/{graph → v1/graph}/retriever.test.ts +135 -42
- package/src/plugins/defaults/memory/{graph → v1/graph}/retriever.ts +40 -22
- package/src/plugins/defaults/memory/{graph → v1/graph}/scoring.test.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/scoring.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/serendipity.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/triggers.test.ts +1 -1
- package/src/plugins/defaults/memory/{graph → v1/graph}/triggers.ts +1 -1
- package/src/plugins/defaults/memory/{identity-context.ts → v1/identity-context.ts} +4 -4
- package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/backfill.ts +6 -6
- package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/embedding.test.ts +6 -6
- package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/embedding.ts +6 -6
- package/src/plugins/defaults/memory/{job-handlers → v1/job-handlers}/index-maintenance.ts +8 -8
- package/src/plugins/defaults/memory/{jobs → v1/jobs}/embed-pkb-file.test.ts +7 -7
- package/src/plugins/defaults/memory/{jobs → v1/jobs}/embed-pkb-file.ts +5 -5
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/autoinject.ts +1 -1
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/context.ts +2 -2
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-index.test.ts +3 -3
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-index.ts +2 -2
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-reconcile.test.ts +3 -3
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-reconcile.ts +2 -2
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-search.test.ts +3 -3
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/pkb-search.ts +6 -6
- package/src/plugins/defaults/memory/{pkb → v1/pkb}/types.ts +3 -5
- package/src/plugins/defaults/memory/{pkb-schedule.ts → v1/pkb-schedule.ts} +2 -2
- package/src/plugins/defaults/memory/{search/semantic.ts → v1/semantic-search.ts} +1 -1
- package/src/plugins/defaults/memory/v2/__tests__/activation-store.test.ts +1 -1
- package/src/plugins/defaults/memory/v2/__tests__/activation.test.ts +11 -274
- package/src/plugins/defaults/memory/v2/__tests__/backfill-jobs.test.ts +9 -131
- package/src/plugins/defaults/memory/v2/__tests__/harness-compare.test.ts +1 -1
- package/src/plugins/defaults/memory/v2/__tests__/harness-oracle.test.ts +1 -1
- package/src/plugins/defaults/memory/v2/__tests__/harness-replay-input.test.ts +1 -1
- package/src/plugins/defaults/memory/v2/__tests__/injection.test.ts +14 -10
- package/src/plugins/defaults/memory/v2/__tests__/reranker.test.ts +7 -5
- package/src/plugins/defaults/memory/v2/__tests__/router.test.ts +12 -6
- package/src/plugins/defaults/memory/{memory-v2-activation-log-store.ts → v2/activation-log-store.ts} +2 -2
- package/src/plugins/defaults/memory/v2/activation-store.ts +22 -8
- package/src/plugins/defaults/memory/v2/activation.ts +30 -163
- package/src/plugins/defaults/memory/v2/backfill-jobs.ts +7 -54
- package/src/plugins/defaults/memory/{memory-v2-concept-frequency.ts → v2/concept-frequency.ts} +3 -3
- package/src/plugins/defaults/memory/v2/harness/oracle.ts +1 -1
- package/src/plugins/defaults/memory/v2/harness/replay-input.ts +2 -2
- package/src/plugins/defaults/memory/v2/harness/retriever.ts +1 -1
- package/src/plugins/defaults/memory/v2/injection.ts +36 -26
- package/src/plugins/defaults/memory/v2/migration.ts +2 -2
- package/src/plugins/defaults/memory/{rerank-local.ts → v2/rerank-local.ts} +44 -18
- package/src/plugins/defaults/memory/v2/reranker.ts +29 -11
- package/src/plugins/defaults/memory/v2/router.ts +38 -15
- package/src/plugins/defaults/memory/v3/__tests__/candidate-match.test.ts +5 -3
- package/src/plugins/defaults/memory/v3/__tests__/carry-integration.test.ts +21 -8
- package/src/plugins/defaults/memory/v3/__tests__/edge.test.ts +1 -1
- package/src/plugins/defaults/memory/v3/__tests__/live-integration.test.ts +1 -1
- package/src/plugins/defaults/memory/v3/__tests__/maintain-job.test.ts +4 -1
- package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +181 -3
- package/src/plugins/defaults/memory/v3/__tests__/selection-log-store.test.ts +3 -0
- package/src/plugins/defaults/memory/v3/__tests__/shadow-integration.test.ts +14 -5
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +40 -50
- package/src/plugins/defaults/memory/v3/__tests__/tuning-profile.test.ts +1 -0
- package/src/plugins/defaults/memory/v3/candidate-match.ts +2 -2
- package/src/plugins/defaults/memory/v3/capabilities.ts +6 -4
- package/src/plugins/defaults/memory/v3/card.ts +25 -9
- package/src/plugins/defaults/memory/v3/edge.ts +52 -18
- package/src/plugins/defaults/memory/v3/gate.ts +4 -4
- package/src/plugins/defaults/memory/v3/injector.ts +10 -3
- package/src/plugins/defaults/memory/v3/maintain-job.ts +3 -3
- package/src/plugins/defaults/memory/v3/orchestrate.ts +100 -18
- package/src/plugins/defaults/memory/v3/page-content.ts +26 -10
- package/src/plugins/defaults/memory/v3/prune.ts +40 -16
- package/src/plugins/defaults/memory/v3/selection-log-store.ts +34 -12
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +9 -13
- package/src/plugins/defaults/memory/v3/span-query.test.ts +86 -0
- package/src/plugins/defaults/memory/v3/span-query.ts +71 -0
- package/src/plugins/defaults/memory/v3/tuning-profile.ts +3 -0
- package/src/plugins/defaults/memory/v3/types.ts +4 -1
- package/src/plugins/defaults/memory/v3-eval/eval-packets.ts +2 -2
- package/src/plugins/defaults/memory/validation.ts +1 -1
- package/src/plugins/defaults/memory/worker.ts +2 -1
- package/src/plugins/defaults/platform-hosted/__tests__/reengage.test.ts +104 -12
- package/src/plugins/defaults/platform-hosted/routes/reengage.ts +104 -12
- package/src/plugins/types.ts +2 -2
- package/src/providers/__tests__/registry-native-web-search.test.ts +47 -2
- package/src/providers/anthropic/client.ts +15 -6
- package/src/providers/content-block-schema.ts +26 -0
- package/src/providers/inference/__tests__/connections-credential-normalize.test.ts +87 -0
- package/src/providers/inference/adapter-factory.ts +6 -0
- package/src/providers/inference/connections.ts +30 -14
- package/src/providers/model-catalog.ts +77 -0
- package/src/providers/openai/__tests__/chat-completions-input-audio.test.ts +260 -0
- package/src/providers/openai/chat-completions-provider.ts +65 -17
- package/src/providers/openai/input-audio.ts +76 -0
- package/src/providers/openrouter/client.ts +0 -2
- package/src/providers/platform-proxy/constants.ts +4 -0
- package/src/providers/poolside/client.ts +42 -0
- package/src/providers/registry.ts +40 -8
- package/src/providers/retry.ts +2 -0
- package/src/providers/types.ts +39 -1
- package/src/providers/vercel-ai-gateway/client.ts +0 -2
- package/src/runtime/AGENTS.md +7 -5
- package/src/runtime/__tests__/question-request-guardian-bridge.test.ts +173 -0
- package/src/runtime/__tests__/question-resolution.test.ts +111 -0
- package/src/runtime/access-request-helper.ts +7 -15
- package/src/runtime/assistant-event-hub.ts +43 -31
- package/src/runtime/assistant-event-publish-options.ts +31 -0
- package/src/runtime/assistant-event.ts +19 -30
- package/src/runtime/assistant-stream-state.ts +4 -4
- package/src/runtime/channel-approvals.ts +0 -25
- package/src/runtime/channel-readiness-service.ts +99 -40
- package/src/runtime/channel-retry-sweep.ts +38 -15
- package/src/runtime/confirmation-request-guardian-bridge.ts +4 -0
- package/src/runtime/guardian-reply-router.ts +108 -0
- package/src/runtime/http-server.ts +8 -0
- package/src/runtime/http-types.ts +2 -2
- package/src/runtime/process-role.ts +42 -0
- package/src/runtime/question-request-guardian-bridge.ts +184 -0
- package/src/runtime/question-resolution.ts +153 -0
- package/src/runtime/routes/__tests__/bookmark-routes.test.ts +6 -2
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +1 -1
- package/src/runtime/routes/acp-routes.ts +2 -2
- package/src/runtime/routes/bookmark-routes.ts +3 -15
- package/src/runtime/routes/canned-message-complete.ts +2 -2
- package/src/runtime/routes/consolidation-routes.ts +8 -2
- package/src/runtime/routes/conversation-list-routes.ts +3 -19
- package/src/runtime/routes/conversation-management-routes.ts +1 -5
- package/src/runtime/routes/conversation-query-routes.ts +52 -8
- package/src/runtime/routes/conversation-routes.ts +36 -22
- package/src/runtime/routes/credential-request-routes.ts +0 -1
- package/src/runtime/routes/filing-routes.ts +7 -7
- package/src/runtime/routes/global-search-routes.ts +1 -1
- package/src/runtime/routes/guardian-approval-prompt.ts +2 -2
- package/src/runtime/routes/image-generation-routes.ts +12 -9
- package/src/runtime/routes/inbound-message-handler.ts +17 -0
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +50 -0
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +19 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +4 -4
- package/src/runtime/routes/inbound-stages/inbound-content-prep.test.ts +129 -0
- package/src/runtime/routes/inbound-stages/inbound-content-prep.ts +141 -9
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/lifecycle-routes.ts +199 -0
- package/src/runtime/routes/platform-routes.ts +3 -8
- package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +7 -7
- package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +5 -5
- package/src/runtime/routes/question-routes.ts +34 -87
- package/src/runtime/routes/secret-routes.ts +11 -1
- package/src/runtime/routes/settings-routes.ts +8 -18
- package/src/runtime/routes/upgrade-broadcast-routes.ts +4 -5
- package/src/runtime/routes/workspace-routes.test.ts +7 -4
- package/src/runtime/slack-reply-session.test.ts +12 -12
- package/src/runtime/slack-reply-session.ts +17 -17
- package/src/runtime/sync/sync-publisher.test.ts +7 -5
- package/src/runtime/tool-grant-request-helper.ts +4 -0
- package/src/schedule/schedule-store.ts +70 -0
- package/src/schedule/scheduler.ts +27 -0
- package/src/security/AGENTS.md +1 -1
- package/src/security/credential-key.ts +17 -0
- package/src/security/secret-ingress.ts +14 -105
- package/src/security/secret-patterns.ts +8 -139
- package/src/security/secret-scanner.ts +8 -3
- package/src/security/store-path-override.ts +6 -16
- package/src/sequence/store.ts +8 -0
- package/src/signals/emit-event.ts +5 -10
- package/src/signals/event-stream.ts +20 -10
- package/src/subagent/manager.ts +76 -25
- package/src/subagent/notify.ts +8 -0
- package/src/subagent/types.ts +13 -3
- package/src/telegram/__tests__/webhook-health.test.ts +442 -0
- package/src/telegram/webhook-health.ts +478 -0
- package/src/telemetry/AGENTS.md +6 -0
- package/src/telemetry/memory-corpus-size.test.ts +129 -0
- package/src/telemetry/memory-corpus-size.ts +184 -0
- package/src/telemetry/memory-tier-reporter.test.ts +67 -2
- package/src/telemetry/memory-tier-reporter.ts +30 -3
- package/src/tools/__tests__/document-tool-input-schemas.test.ts +103 -0
- package/src/tools/__tests__/followup-call-acp-tool-input-schemas.test.ts +125 -0
- package/src/tools/__tests__/schedule-tool-input-schemas.test.ts +83 -0
- package/src/tools/__tests__/subagent-workflow-tool-input-schemas.test.ts +116 -0
- package/src/tools/__tests__/tool-input-schemas.test.ts +192 -0
- package/src/tools/__tests__/tool-schema-drift-harness.ts +142 -0
- package/src/tools/acp/abort.ts +21 -1
- package/src/tools/acp/context.ts +5 -5
- package/src/tools/acp/spawn.test.ts +15 -5
- package/src/tools/acp/spawn.ts +26 -3
- package/src/tools/acp/status.ts +20 -1
- package/src/tools/acp/steer.test.ts +20 -0
- package/src/tools/acp/steer.ts +23 -2
- package/src/tools/ask-question/ask-question-tool.test.ts +65 -0
- package/src/tools/ask-question/ask-question-tool.ts +68 -92
- package/src/tools/browser/browser-screencast.ts +6 -6
- package/src/tools/calls/call-end.ts +24 -3
- package/src/tools/calls/call-start.ts +35 -11
- package/src/tools/calls/call-status.ts +20 -1
- package/src/tools/document/document-comment-tool.test.ts +49 -0
- package/src/tools/document/document-comment-tool.ts +45 -6
- package/src/tools/document/document-tool.ts +142 -24
- package/src/tools/executor.ts +27 -13
- package/src/tools/filesystem/edit.ts +62 -60
- package/src/tools/filesystem/list.ts +36 -29
- package/src/tools/filesystem/read.ts +56 -39
- package/src/tools/filesystem/write.ts +44 -38
- package/src/tools/followups/followup_create.ts +41 -12
- package/src/tools/followups/followup_list.ts +34 -6
- package/src/tools/followups/followup_resolve.ts +26 -4
- package/src/tools/host-filesystem/edit.ts +50 -60
- package/src/tools/host-filesystem/read.ts +45 -39
- package/src/tools/host-filesystem/write.ts +31 -36
- package/src/tools/host-terminal/host-shell.ts +76 -62
- package/src/tools/policy-context.ts +27 -10
- package/src/tools/schedule/create.ts +76 -33
- package/src/tools/schedule/delete.ts +21 -2
- package/src/tools/schedule/list.ts +25 -3
- package/src/tools/schedule/update.ts +105 -48
- package/src/tools/shared/filesystem/path-policy.ts +246 -40
- package/src/tools/shared/zod-tool-schema.ts +117 -0
- package/src/tools/subagent/abort.ts +12 -4
- package/src/tools/subagent/consult-deadline.ts +9 -3
- package/src/tools/subagent/message.ts +21 -5
- package/src/tools/subagent/notify-parent.ts +44 -23
- package/src/tools/subagent/read.ts +15 -4
- package/src/tools/subagent/resolve.ts +26 -4
- package/src/tools/subagent/spawn.ts +37 -13
- package/src/tools/subagent/status.ts +12 -4
- package/src/tools/system/request-permission.ts +35 -26
- package/src/tools/terminal/shell.ts +68 -55
- package/src/tools/tool-approval-handler.ts +327 -53
- package/src/tools/tool-input-schemas.ts +85 -0
- package/src/tools/tool-types.ts +7 -0
- package/src/tools/types.ts +8 -0
- package/src/tools/workflows/manage-workflows.ts +30 -2
- package/src/tools/workflows/run-workflow.test.ts +54 -2
- package/src/tools/workflows/run-workflow.ts +32 -4
- package/src/util/fs-symlinks.ts +30 -0
- package/src/util/log-redact.ts +7 -3
- package/src/vellum-assistant-namespace.d.ts +80 -0
- package/src/watcher/watcher-store.ts +8 -0
- package/src/workflows/leaf-runner.test.ts +104 -2
- package/src/workflows/leaf-runner.ts +31 -6
- package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +2 -2
- package/src/workspace/migrations/134-image-generation-mode-to-provider.ts +128 -0
- package/src/workspace/migrations/135-copy-substrate-tunables.ts +248 -0
- package/src/workspace/migrations/__tests__/135-copy-substrate-tunables.test.ts +446 -0
- package/src/workspace/migrations/__tests__/backfill-v3-leaves.test.ts +2 -2
- package/src/workspace/migrations/registry.ts +4 -0
- package/src/__tests__/memory-retrieval-budget.test.ts +0 -49
- package/src/__tests__/secret-patterns.test.ts +0 -27
- package/src/config/__tests__/proc-to-skills.test.ts +0 -21
- package/src/config/memory-tier.test.ts +0 -44
- package/src/daemon/message-types/acp.ts +0 -20
- package/src/daemon/message-types/apps.ts +0 -11
- package/src/daemon/message-types/background-tools.ts +0 -14
- package/src/daemon/message-types/bookmarks.ts +0 -13
- package/src/daemon/message-types/contacts.ts +0 -13
- package/src/daemon/message-types/document-comments.ts +0 -14
- package/src/daemon/message-types/documents.ts +0 -13
- package/src/daemon/message-types/home.ts +0 -15
- package/src/daemon/message-types/host-bash.ts +0 -12
- package/src/daemon/message-types/host-cu.ts +0 -10
- package/src/daemon/message-types/host-file.ts +0 -12
- package/src/daemon/message-types/host-transfer.ts +0 -12
- package/src/daemon/message-types/integrations.ts +0 -90
- package/src/daemon/message-types/memory.ts +0 -10
- package/src/daemon/message-types/schedules.ts +0 -14
- package/src/daemon/message-types/settings.ts +0 -17
- package/src/daemon/message-types/subagents.ts +0 -63
- package/src/daemon/message-types/upgrades.ts +0 -14
- package/src/daemon/message-types/workflows.ts +0 -25
- package/src/daemon/message-types/workspace.ts +0 -137
- package/src/live-voice/ack-phrases.ts +0 -58
- package/src/plugins/defaults/memory/retrieval-budget.ts +0 -29
- package/src/plugins/defaults/memory/v3/__tests__/gate-flag.test.ts +0 -69
- package/src/plugins/defaults/memory/v3/gate-flag.ts +0 -20
- package/src/plugins/defaults/memory/v3/substrate/__tests__/memory-v2-startup.test.ts +0 -86
- package/src/plugins/defaults/memory/v3/substrate/memory-v2-startup.test.ts +0 -205
- /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/concept-page-frontmatter-schema.test.ts +0 -0
- /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/consolidation-prompt-flag-gating-guard.test.ts +0 -0
- /package/src/plugins/defaults/memory/{v3/substrate → substrate}/__tests__/injected-block-slugs.test.ts +0 -0
- /package/src/plugins/defaults/memory/{v3/substrate → substrate}/cli-command-content.ts +0 -0
|
@@ -6,7 +6,9 @@
|
|
|
6
6
|
* before it enters model context — the model is instructed never to follow
|
|
7
7
|
* instructions found inside those boundaries. Guardian messages are trusted and
|
|
8
8
|
* pass through unwrapped. Slack additionally keeps the raw text as
|
|
9
|
-
* `displayContent` so the UI shows the message the sender actually typed
|
|
9
|
+
* `displayContent` so the UI shows the message the sender actually typed, and
|
|
10
|
+
* prepends a `<slack_app_context>` block when the event reported what the
|
|
11
|
+
* sender had open in Slack.
|
|
10
12
|
*
|
|
11
13
|
* Shared by the live ingress path (`inbound-message-handler.ts`) and the retry
|
|
12
14
|
* sweep (`channel-retry-sweep.ts`) so both prepare content identically: a turn
|
|
@@ -14,9 +16,114 @@
|
|
|
14
16
|
* boundary cannot be skipped on a retry or crash-recovery path.
|
|
15
17
|
*/
|
|
16
18
|
import type { ChannelId } from "../../../channels/types.js";
|
|
19
|
+
import type {
|
|
20
|
+
SlackAppContext,
|
|
21
|
+
SlackAppContextEntity,
|
|
22
|
+
} from "../../../daemon/handlers/shared.js";
|
|
17
23
|
import type { TrustContext } from "../../../daemon/trust-context-types.js";
|
|
18
24
|
import { wrapUntrustedContent } from "../../../security/untrusted-content.js";
|
|
19
25
|
|
|
26
|
+
/** Slack `app_context` entity types whose `value` is a plain object id. */
|
|
27
|
+
const SLACK_APP_CONTEXT_ID_LABELS = new Map<string, string>([
|
|
28
|
+
["slack#/types/channel_id", "channel"],
|
|
29
|
+
["slack#/types/canvas_id", "canvas"],
|
|
30
|
+
["slack#/types/list_id", "list"],
|
|
31
|
+
]);
|
|
32
|
+
|
|
33
|
+
/** The one entity type whose `value` is an object rather than an id string. */
|
|
34
|
+
const SLACK_APP_CONTEXT_MESSAGE_TYPE = "slack#/types/message_context";
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Shape of a Slack-issued object id (channel `C…`/`G…`/`D…`, canvas/list `F…`).
|
|
38
|
+
* The rendered block sits OUTSIDE the `<external_content>` fence, so every
|
|
39
|
+
* value that reaches it must be provably Slack-minted rather than sender-typed
|
|
40
|
+
* text — an entity whose id does not match this is dropped, not rendered.
|
|
41
|
+
*/
|
|
42
|
+
const SLACK_OBJECT_ID_PATTERN = /^[A-Z][A-Z0-9]{1,31}$/;
|
|
43
|
+
|
|
44
|
+
/** Slack message `ts`, `<seconds>.<micros>`. Same rationale as the id pattern. */
|
|
45
|
+
const SLACK_TS_PATTERN = /^\d{1,19}\.\d{1,19}$/;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Cap on rendered entities. Slack sends a handful; the cap bounds how much
|
|
49
|
+
* trusted framing a malformed payload can occupy.
|
|
50
|
+
*/
|
|
51
|
+
const MAX_APP_CONTEXT_ENTITIES = 8;
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Render the sender's active Slack context as a `<slack_app_context>` block, or
|
|
55
|
+
* `undefined` when no entity survives validation.
|
|
56
|
+
*
|
|
57
|
+
* The block is deliberately NOT fenced as untrusted content. Every value it
|
|
58
|
+
* carries is a Slack-issued opaque identifier, validated against the patterns
|
|
59
|
+
* above, so there is no sender-authored text in it — and the model has to be
|
|
60
|
+
* able to act on the block (resolving "this channel", "that message") rather
|
|
61
|
+
* than treat it as inert data it must ignore. Nothing derived from a channel
|
|
62
|
+
* name, canvas title, or any other user-writable string may be added here
|
|
63
|
+
* without moving the block inside the fence.
|
|
64
|
+
*
|
|
65
|
+
* The block reaches the model for this turn only: persistence stores
|
|
66
|
+
* `displayContent` (the raw text), so replayed history carries the message
|
|
67
|
+
* without it. That is the intended lifetime — `app_context` describes what the
|
|
68
|
+
* sender had open when they sent the message, not what they have open now.
|
|
69
|
+
*/
|
|
70
|
+
function renderSlackAppContext(
|
|
71
|
+
entities: readonly SlackAppContextEntity[],
|
|
72
|
+
): string | undefined {
|
|
73
|
+
const lines: string[] = [];
|
|
74
|
+
|
|
75
|
+
for (const entity of entities) {
|
|
76
|
+
if (lines.length >= MAX_APP_CONTEXT_ENTITIES) {
|
|
77
|
+
break;
|
|
78
|
+
}
|
|
79
|
+
// Entities arrive unvalidated on both paths (an unparsed HTTP body live, a
|
|
80
|
+
// stored payload on replay), so a malformed element is skipped, not thrown on.
|
|
81
|
+
if (!entity || typeof entity !== "object") {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
const idLabel = SLACK_APP_CONTEXT_ID_LABELS.get(entity.type);
|
|
85
|
+
if (idLabel) {
|
|
86
|
+
if (
|
|
87
|
+
typeof entity.value === "string" &&
|
|
88
|
+
SLACK_OBJECT_ID_PATTERN.test(entity.value)
|
|
89
|
+
) {
|
|
90
|
+
lines.push(`${idLabel}: ${entity.value}`);
|
|
91
|
+
}
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
if (
|
|
95
|
+
entity.type !== SLACK_APP_CONTEXT_MESSAGE_TYPE ||
|
|
96
|
+
!entity.value ||
|
|
97
|
+
typeof entity.value !== "object"
|
|
98
|
+
) {
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
const { channelId, messageTs } = entity.value;
|
|
102
|
+
if (
|
|
103
|
+
channelId &&
|
|
104
|
+
messageTs &&
|
|
105
|
+
SLACK_OBJECT_ID_PATTERN.test(channelId) &&
|
|
106
|
+
SLACK_TS_PATTERN.test(messageTs)
|
|
107
|
+
) {
|
|
108
|
+
lines.push(`message: channel ${channelId} ts ${messageTs}`);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (lines.length === 0) {
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return [
|
|
117
|
+
"<slack_app_context>",
|
|
118
|
+
"Slack reports these as open for the sender right now. Use the ids to",
|
|
119
|
+
'resolve references like "this channel" or "that message"; when the',
|
|
120
|
+
"reference is still ambiguous, ask rather than guess.",
|
|
121
|
+
"",
|
|
122
|
+
...lines,
|
|
123
|
+
"</slack_app_context>",
|
|
124
|
+
].join("\n");
|
|
125
|
+
}
|
|
126
|
+
|
|
20
127
|
export interface PreparedChannelInboundContent {
|
|
21
128
|
/**
|
|
22
129
|
* Model-facing content. For non-guardian senders this is `trimmedContent`
|
|
@@ -27,8 +134,10 @@ export interface PreparedChannelInboundContent {
|
|
|
27
134
|
/**
|
|
28
135
|
* User-facing display copy (the raw, unwrapped text) persisted alongside the
|
|
29
136
|
* model content so the UI renders what the sender typed rather than the
|
|
30
|
-
* boundary-wrapped form. Set
|
|
31
|
-
*
|
|
137
|
+
* boundary-wrapped form. Set on any Slack turn whose `content` diverges from
|
|
138
|
+
* the raw text — non-guardian turns (which are fenced) and turns carrying a
|
|
139
|
+
* `<slack_app_context>` block. Absent otherwise (persistence falls back to
|
|
140
|
+
* `content`).
|
|
32
141
|
*/
|
|
33
142
|
displayContent?: string;
|
|
34
143
|
}
|
|
@@ -43,21 +152,44 @@ export function prepareChannelInboundContent(params: {
|
|
|
43
152
|
trustClass: TrustContext["trustClass"];
|
|
44
153
|
sourceChannel: ChannelId;
|
|
45
154
|
requesterIdentifier?: string;
|
|
155
|
+
/**
|
|
156
|
+
* The sender's active Slack context, when the inbound event carried one.
|
|
157
|
+
* Ignored for non-Slack channels.
|
|
158
|
+
*/
|
|
159
|
+
slackAppContext?: SlackAppContext;
|
|
46
160
|
}): PreparedChannelInboundContent {
|
|
47
|
-
const {
|
|
48
|
-
|
|
161
|
+
const {
|
|
162
|
+
trimmedContent,
|
|
163
|
+
trustClass,
|
|
164
|
+
sourceChannel,
|
|
165
|
+
requesterIdentifier,
|
|
166
|
+
slackAppContext,
|
|
167
|
+
} = params;
|
|
49
168
|
|
|
50
169
|
const isGuardian = trustClass === "guardian";
|
|
51
|
-
const
|
|
170
|
+
const messageContent = isGuardian
|
|
52
171
|
? trimmedContent
|
|
53
172
|
: wrapUntrustedContent(trimmedContent, {
|
|
54
173
|
source: sourceChannel === "slack" ? "slack" : "webhook",
|
|
55
174
|
sourceDetail: requesterIdentifier,
|
|
56
175
|
});
|
|
57
176
|
|
|
58
|
-
//
|
|
59
|
-
//
|
|
60
|
-
|
|
177
|
+
// Prepended outside the fence — see `renderSlackAppContext` for why that is
|
|
178
|
+
// safe and what would make it unsafe.
|
|
179
|
+
// `Array.isArray` rather than a truthiness check: on the replay path this
|
|
180
|
+
// object comes straight off the stored payload without re-validation.
|
|
181
|
+
const appContextBlock =
|
|
182
|
+
sourceChannel === "slack" && Array.isArray(slackAppContext?.entities)
|
|
183
|
+
? renderSlackAppContext(slackAppContext.entities)
|
|
184
|
+
: undefined;
|
|
185
|
+
const content = appContextBlock
|
|
186
|
+
? `${appContextBlock}\n\n${messageContent}`
|
|
187
|
+
: messageContent;
|
|
188
|
+
|
|
189
|
+
// Slack persists the raw text as display copy whenever the model content
|
|
190
|
+
// diverges from it, so the transcript shows the sender's words rather than
|
|
191
|
+
// the wrapped form or the prepended context block.
|
|
192
|
+
if (sourceChannel === "slack" && (!isGuardian || appContextBlock)) {
|
|
61
193
|
return { content, displayContent: trimmedContent };
|
|
62
194
|
}
|
|
63
195
|
return { content };
|
|
@@ -101,6 +101,7 @@ import { ROUTES as VERCEL_ROUTES } from "./integrations/vercel.js";
|
|
|
101
101
|
import { ROUTES as INTERNAL_OAUTH_ROUTES } from "./internal-oauth-routes.js";
|
|
102
102
|
import { ROUTES as INTERNAL_TELEMETRY_ROUTES } from "./internal-telemetry-routes.js";
|
|
103
103
|
import { ROUTES as INTERNAL_TWILIO_ROUTES } from "./internal-twilio-routes.js";
|
|
104
|
+
import { ROUTES as LIFECYCLE_ROUTES } from "./lifecycle-routes.js";
|
|
104
105
|
import { ROUTES as LIVE_VOICE_ROUTES } from "./live-voice-routes.js";
|
|
105
106
|
import { ROUTES as LLM_CALL_SITES_ROUTES } from "./llm-call-sites-routes.js";
|
|
106
107
|
import { ROUTES as LOG_EXPORT_ROUTES } from "./log-export-routes.js";
|
|
@@ -241,6 +242,7 @@ export const ROUTES: RouteDefinition[] = [
|
|
|
241
242
|
...MCP_AUTH_ROUTES,
|
|
242
243
|
...OAUTH_CONNECT_ROUTES,
|
|
243
244
|
...INTERNAL_TWILIO_ROUTES,
|
|
245
|
+
...LIFECYCLE_ROUTES,
|
|
244
246
|
...LIVE_VOICE_ROUTES,
|
|
245
247
|
...LOG_EXPORT_ROUTES,
|
|
246
248
|
...LLM_CALL_SITES_ROUTES,
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lifecycle drain endpoints backing `vellum sleep --wait`.
|
|
3
|
+
*
|
|
4
|
+
* The quiesce lease pauses the STARTING of new background LLM work (heartbeat
|
|
5
|
+
* beats, schedule/watcher/sequence claims, memory-job claims) across the
|
|
6
|
+
* daemon and its worker processes; drain-status reports what is still in
|
|
7
|
+
* flight so a client can wait for the assistant to go idle before stopping
|
|
8
|
+
* it. Enqueue paths stay open — work queued during a drain runs after the
|
|
9
|
+
* next start. The lease is TTL-bound and refreshed by the waiting client, so
|
|
10
|
+
* an abandoned drain can never leave background work paused.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { z } from "zod";
|
|
14
|
+
|
|
15
|
+
import { listRunningHeartbeatRuns } from "../../heartbeat/heartbeat-run-store.js";
|
|
16
|
+
import { listProcessingConversations } from "../../persistence/conversation-crud.js";
|
|
17
|
+
import { listRunningMemoryJobs } from "../../persistence/jobs-store.js";
|
|
18
|
+
import {
|
|
19
|
+
clearLifecycleQuiesce,
|
|
20
|
+
DEFAULT_QUIESCE_TTL_MS,
|
|
21
|
+
getLifecycleQuiesceUntil,
|
|
22
|
+
setLifecycleQuiesce,
|
|
23
|
+
} from "../../persistence/lifecycle-quiesce.js";
|
|
24
|
+
import { listRunningScheduleRuns } from "../../schedule/schedule-store.js";
|
|
25
|
+
import { getLogger } from "../../util/logger.js";
|
|
26
|
+
import { listRuns as listWorkflowRuns } from "../../workflows/journal-store.js";
|
|
27
|
+
import { ACTOR_PRINCIPALS } from "../auth/route-policy.js";
|
|
28
|
+
import { BadRequestError } from "./errors.js";
|
|
29
|
+
import type { RouteDefinition, RouteHandlerArgs } from "./types.js";
|
|
30
|
+
|
|
31
|
+
const log = getLogger("lifecycle-routes");
|
|
32
|
+
|
|
33
|
+
const quiesceResponseSchema = z.object({
|
|
34
|
+
quiescedUntil: z
|
|
35
|
+
.number()
|
|
36
|
+
.describe("Epoch ms when the quiesce lease expires."),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const activeConversationSchema = z.object({
|
|
40
|
+
conversationId: z.string(),
|
|
41
|
+
title: z.string().nullable(),
|
|
42
|
+
originChannel: z.string().nullable(),
|
|
43
|
+
originInterface: z.string().nullable(),
|
|
44
|
+
processingStartedAt: z.number(),
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const runningMemoryJobSchema = z.object({
|
|
48
|
+
id: z.string(),
|
|
49
|
+
type: z.string(),
|
|
50
|
+
startedAt: z.number().nullable(),
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
const runningScheduleRunSchema = z.object({
|
|
54
|
+
runId: z.string(),
|
|
55
|
+
scheduleName: z.string().nullable(),
|
|
56
|
+
startedAt: z.number(),
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const runningWorkflowRunSchema = z.object({
|
|
60
|
+
runId: z.string(),
|
|
61
|
+
name: z.string().nullable(),
|
|
62
|
+
startedAt: z.number().nullable(),
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const runningHeartbeatRunSchema = z.object({
|
|
66
|
+
runId: z.string(),
|
|
67
|
+
startedAt: z.number(),
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
const drainStatusResponseSchema = z.object({
|
|
71
|
+
quiescedUntil: z.number().nullable(),
|
|
72
|
+
idle: z
|
|
73
|
+
.boolean()
|
|
74
|
+
.describe(
|
|
75
|
+
"True when no conversation turn, memory job, schedule run, workflow run, or heartbeat run is in flight.",
|
|
76
|
+
),
|
|
77
|
+
activeConversations: z.array(activeConversationSchema),
|
|
78
|
+
memoryJobs: z.array(runningMemoryJobSchema),
|
|
79
|
+
scheduleRuns: z.array(runningScheduleRunSchema),
|
|
80
|
+
workflowRuns: z.array(runningWorkflowRunSchema),
|
|
81
|
+
heartbeatRuns: z.array(runningHeartbeatRunSchema),
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Age cap for `running` heartbeat rows in the drain snapshot. A beat orphaned
|
|
86
|
+
* by a crash keeps its `running` status until a later boot's stale sweep, so
|
|
87
|
+
* an unbounded read would let a phantom row hold the drain open indefinitely.
|
|
88
|
+
* Real beats finish well inside this bound (the runner enforces its own
|
|
89
|
+
* timeout).
|
|
90
|
+
*/
|
|
91
|
+
const HEARTBEAT_RUN_MAX_AGE_MS = 15 * 60_000;
|
|
92
|
+
|
|
93
|
+
export const ROUTES: RouteDefinition[] = [
|
|
94
|
+
{
|
|
95
|
+
operationId: "quiesceLifecycle",
|
|
96
|
+
endpoint: "lifecycle/quiesce",
|
|
97
|
+
method: "POST",
|
|
98
|
+
policy: {
|
|
99
|
+
requiredScopes: ["settings.write"],
|
|
100
|
+
allowedPrincipalTypes: ACTOR_PRINCIPALS,
|
|
101
|
+
},
|
|
102
|
+
summary: "Arm or refresh the drain quiesce lease",
|
|
103
|
+
description:
|
|
104
|
+
"Pauses the starting of new background work (heartbeat, schedules, watchers, sequences, memory jobs) for the lease TTL. Refresh by calling again; the lease self-expires so an abandoned drain never leaves background work paused.",
|
|
105
|
+
tags: ["system"],
|
|
106
|
+
requestBody: z.object({
|
|
107
|
+
ttlMs: z
|
|
108
|
+
.number()
|
|
109
|
+
.optional()
|
|
110
|
+
.describe("Lease TTL in ms (clamped to a sane range)."),
|
|
111
|
+
}),
|
|
112
|
+
responseBody: quiesceResponseSchema,
|
|
113
|
+
handler: (args: RouteHandlerArgs) => {
|
|
114
|
+
const raw = args.body?.ttlMs;
|
|
115
|
+
let ttlMs = DEFAULT_QUIESCE_TTL_MS;
|
|
116
|
+
if (raw !== undefined) {
|
|
117
|
+
if (typeof raw !== "number" || !Number.isFinite(raw)) {
|
|
118
|
+
throw new BadRequestError("ttlMs must be a finite number");
|
|
119
|
+
}
|
|
120
|
+
ttlMs = raw;
|
|
121
|
+
}
|
|
122
|
+
const quiescedUntil = setLifecycleQuiesce(ttlMs);
|
|
123
|
+
log.info({ quiescedUntil }, "Lifecycle quiesce lease armed");
|
|
124
|
+
return { quiescedUntil };
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
operationId: "releaseLifecycleQuiesce",
|
|
129
|
+
endpoint: "lifecycle/quiesce",
|
|
130
|
+
method: "DELETE",
|
|
131
|
+
policy: {
|
|
132
|
+
requiredScopes: ["settings.write"],
|
|
133
|
+
allowedPrincipalTypes: ACTOR_PRINCIPALS,
|
|
134
|
+
},
|
|
135
|
+
summary: "Release the drain quiesce lease",
|
|
136
|
+
description:
|
|
137
|
+
"Resumes background work immediately instead of waiting for the lease TTL to expire (e.g. when a drain is cancelled).",
|
|
138
|
+
tags: ["system"],
|
|
139
|
+
responseBody: z.object({ released: z.boolean() }),
|
|
140
|
+
handler: () => {
|
|
141
|
+
clearLifecycleQuiesce();
|
|
142
|
+
log.info("Lifecycle quiesce lease released");
|
|
143
|
+
return { released: true };
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
operationId: "getLifecycleDrainStatus",
|
|
148
|
+
endpoint: "lifecycle/drain-status",
|
|
149
|
+
method: "GET",
|
|
150
|
+
policy: {
|
|
151
|
+
requiredScopes: ["settings.read"],
|
|
152
|
+
allowedPrincipalTypes: ACTOR_PRINCIPALS,
|
|
153
|
+
},
|
|
154
|
+
summary: "In-flight background work",
|
|
155
|
+
description:
|
|
156
|
+
"Reports conversation turns, memory jobs, schedule runs, workflow runs, and heartbeat runs currently in flight, plus the active quiesce lease. `idle: true` means it is safe to stop the assistant without interrupting work.",
|
|
157
|
+
tags: ["system"],
|
|
158
|
+
responseBody: drainStatusResponseSchema,
|
|
159
|
+
handler: () => {
|
|
160
|
+
// Every read THROWS on failure (surfacing as a 5xx the client retries):
|
|
161
|
+
// for a drain decision, a failed read must not pass for proof of
|
|
162
|
+
// absence, or the client stops the assistant over unobservable
|
|
163
|
+
// in-flight work. Only the quiesce GATES are fail-open — this snapshot
|
|
164
|
+
// fails closed.
|
|
165
|
+
const activeConversations = listProcessingConversations();
|
|
166
|
+
const memoryJobs = listRunningMemoryJobs();
|
|
167
|
+
const scheduleRuns = listRunningScheduleRuns();
|
|
168
|
+
// Workflows launched by a schedule outlive their schedule run — the
|
|
169
|
+
// scheduler fires them and completes its own run row immediately — so
|
|
170
|
+
// a running workflow must hold the drain open in its own right.
|
|
171
|
+
const workflowRuns = listWorkflowRuns({
|
|
172
|
+
limit: 20,
|
|
173
|
+
status: "running",
|
|
174
|
+
}).map((run) => ({
|
|
175
|
+
runId: run.id,
|
|
176
|
+
name: run.name,
|
|
177
|
+
startedAt: run.createdAt,
|
|
178
|
+
}));
|
|
179
|
+
// A beat between startHeartbeatRun() and its background conversation
|
|
180
|
+
// existing (e.g. mid credential-health check) has a running row but no
|
|
181
|
+
// processing conversation yet.
|
|
182
|
+
const heartbeatRuns = listRunningHeartbeatRuns(HEARTBEAT_RUN_MAX_AGE_MS);
|
|
183
|
+
return {
|
|
184
|
+
quiescedUntil: getLifecycleQuiesceUntil(),
|
|
185
|
+
idle:
|
|
186
|
+
activeConversations.length === 0 &&
|
|
187
|
+
memoryJobs.length === 0 &&
|
|
188
|
+
scheduleRuns.length === 0 &&
|
|
189
|
+
workflowRuns.length === 0 &&
|
|
190
|
+
heartbeatRuns.length === 0,
|
|
191
|
+
activeConversations,
|
|
192
|
+
memoryJobs,
|
|
193
|
+
scheduleRuns,
|
|
194
|
+
workflowRuns,
|
|
195
|
+
heartbeatRuns,
|
|
196
|
+
};
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
];
|
|
@@ -30,8 +30,7 @@ import {
|
|
|
30
30
|
getSecureKeyAsync,
|
|
31
31
|
} from "../../security/secure-keys.js";
|
|
32
32
|
import { getExistingDeviceId } from "../../util/device-id.js";
|
|
33
|
-
import {
|
|
34
|
-
import { assistantEventHub } from "../assistant-event-hub.js";
|
|
33
|
+
import { broadcastMessage } from "../assistant-event-hub.js";
|
|
35
34
|
import { ACTOR_PRINCIPALS, LOCAL_PRINCIPALS } from "../auth/route-policy.js";
|
|
36
35
|
import {
|
|
37
36
|
BadRequestError,
|
|
@@ -193,9 +192,7 @@ async function handlePlatformConnect(
|
|
|
193
192
|
}
|
|
194
193
|
|
|
195
194
|
// Emit signal for connected clients to show the platform login UI
|
|
196
|
-
|
|
197
|
-
buildAssistantEvent({ type: "show_platform_login" }),
|
|
198
|
-
);
|
|
195
|
+
broadcastMessage({ type: "show_platform_login" });
|
|
199
196
|
|
|
200
197
|
return { showPlatformLogin: true };
|
|
201
198
|
}
|
|
@@ -259,9 +256,7 @@ async function handlePlatformDisconnect(
|
|
|
259
256
|
}
|
|
260
257
|
|
|
261
258
|
// Notify connected clients
|
|
262
|
-
|
|
263
|
-
buildAssistantEvent({ type: "platform_disconnected" }),
|
|
264
|
-
);
|
|
259
|
+
broadcastMessage({ type: "platform_disconnected" });
|
|
265
260
|
|
|
266
261
|
return {
|
|
267
262
|
disconnected: true,
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { describe, expect, mock, test } from "bun:test";
|
|
5
5
|
|
|
6
|
+
import type { AssistantEvent } from "../../../../api/index.js";
|
|
6
7
|
import type { Conversation } from "../../../../daemon/conversation.js";
|
|
7
|
-
import type { ServerMessage } from "../../../../daemon/message-protocol.js";
|
|
8
8
|
|
|
9
9
|
let _mockConversation: MockConversation | undefined;
|
|
10
10
|
|
|
@@ -18,8 +18,8 @@ mock.module("../../../../context/token-estimator.js", () => ({
|
|
|
18
18
|
|
|
19
19
|
mock.module("../helpers.js", () => ({
|
|
20
20
|
getConversationById: async (id: string) => {
|
|
21
|
-
if (!_mockConversation) return undefined;
|
|
22
|
-
if (_mockConversation.conversationId !== id) return undefined;
|
|
21
|
+
if (!_mockConversation) {return undefined;}
|
|
22
|
+
if (_mockConversation.conversationId !== id) {return undefined;}
|
|
23
23
|
return _mockConversation as unknown as Conversation;
|
|
24
24
|
},
|
|
25
25
|
listConversationsByTitlePrefix: () => [],
|
|
@@ -41,13 +41,13 @@ interface MockConversation {
|
|
|
41
41
|
agentLoop: { compactionCircuit: MockCompactionCircuit };
|
|
42
42
|
contextCompactedMessageCount: number;
|
|
43
43
|
contextCompactedAt: number | null;
|
|
44
|
-
sentMessages:
|
|
45
|
-
sendToClient: (msg:
|
|
44
|
+
sentMessages: AssistantEvent[];
|
|
45
|
+
sendToClient: (msg: AssistantEvent) => void;
|
|
46
46
|
getMessages: () => unknown[];
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
function makeConversation(id = "conv-playground-test"): MockConversation {
|
|
50
|
-
const sentMessages:
|
|
50
|
+
const sentMessages: AssistantEvent[] = [];
|
|
51
51
|
return {
|
|
52
52
|
conversationId: id,
|
|
53
53
|
agentLoop: {
|
|
@@ -68,7 +68,7 @@ function findRoute() {
|
|
|
68
68
|
const route = ROUTES.find(
|
|
69
69
|
(r) => r.operationId === "playgroundInjectCompactionFailures",
|
|
70
70
|
);
|
|
71
|
-
if (!route) throw new Error("inject-failures route not registered");
|
|
71
|
+
if (!route) {throw new Error("inject-failures route not registered");}
|
|
72
72
|
return route;
|
|
73
73
|
}
|
|
74
74
|
|
|
@@ -19,8 +19,8 @@ mock.module("../helpers.js", () => ({
|
|
|
19
19
|
addPlaygroundMessage: async () => ({ id: "msg-test" }),
|
|
20
20
|
}));
|
|
21
21
|
|
|
22
|
+
import type { AssistantEvent } from "../../../../api/index.js";
|
|
22
23
|
import type { Conversation } from "../../../../daemon/conversation.js";
|
|
23
|
-
import type { ServerMessage } from "../../../../daemon/message-protocol.js";
|
|
24
24
|
import { RouteError } from "../../errors.js";
|
|
25
25
|
import { ROUTES } from "../index.js";
|
|
26
26
|
|
|
@@ -33,7 +33,7 @@ interface FakeConversationState {
|
|
|
33
33
|
|
|
34
34
|
interface FakeConversation {
|
|
35
35
|
conversation: Conversation;
|
|
36
|
-
sent:
|
|
36
|
+
sent: AssistantEvent[];
|
|
37
37
|
state: FakeConversationState;
|
|
38
38
|
}
|
|
39
39
|
|
|
@@ -47,7 +47,7 @@ function makeFakeConversation(
|
|
|
47
47
|
contextCompactedAt: null,
|
|
48
48
|
...overrides,
|
|
49
49
|
};
|
|
50
|
-
const sent:
|
|
50
|
+
const sent: AssistantEvent[] = [];
|
|
51
51
|
const compactionCircuit = {
|
|
52
52
|
get consecutiveCompactionFailures(): number {
|
|
53
53
|
return state.consecutiveCompactionFailures;
|
|
@@ -72,7 +72,7 @@ function makeFakeConversation(
|
|
|
72
72
|
return state.contextCompactedAt;
|
|
73
73
|
},
|
|
74
74
|
getMessages: () => [],
|
|
75
|
-
sendToClient: (msg:
|
|
75
|
+
sendToClient: (msg: AssistantEvent) => {
|
|
76
76
|
sent.push(msg);
|
|
77
77
|
},
|
|
78
78
|
} as unknown as Conversation;
|
|
@@ -84,7 +84,7 @@ function findRoute() {
|
|
|
84
84
|
const route = ROUTES.find(
|
|
85
85
|
(r) => r.operationId === "playgroundResetCompactionCircuit",
|
|
86
86
|
);
|
|
87
|
-
if (!route) throw new Error("reset-circuit route not registered");
|
|
87
|
+
if (!route) {throw new Error("reset-circuit route not registered");}
|
|
88
88
|
return route;
|
|
89
89
|
}
|
|
90
90
|
|