@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
|
@@ -79,36 +79,33 @@ const BASELINE: Record<string, readonly string[]> = {
|
|
|
79
79
|
"../../../util/logger.js",
|
|
80
80
|
],
|
|
81
81
|
memory: [
|
|
82
|
-
"../../../../../
|
|
82
|
+
"../../../../../agent/image-optimize.js",
|
|
83
83
|
"../../../../../config/loader.js",
|
|
84
84
|
"../../../../../config/memory-v3-gate.js",
|
|
85
|
-
"../../../../../config/schema.js",
|
|
86
85
|
"../../../../../config/types.js",
|
|
87
|
-
"../../../../../daemon/embedding-reconcile.js",
|
|
88
86
|
"../../../../../messaging/providers/slack/message-metadata.js",
|
|
89
|
-
"../../../../../notifications/emit-signal.js",
|
|
90
87
|
"../../../../../persistence/auto-analysis-constants.js",
|
|
91
88
|
"../../../../../persistence/checkpoints.js",
|
|
92
89
|
"../../../../../persistence/db-connection.js",
|
|
93
90
|
"../../../../../persistence/embeddings/embed.js",
|
|
94
91
|
"../../../../../persistence/embeddings/embedding-backend.js",
|
|
95
92
|
"../../../../../persistence/embeddings/embedding-types.js",
|
|
96
|
-
"../../../../../persistence/embeddings/
|
|
93
|
+
"../../../../../persistence/embeddings/qdrant-circuit-breaker.js",
|
|
94
|
+
"../../../../../persistence/embeddings/qdrant-client.js",
|
|
95
|
+
"../../../../../persistence/job-utils.js",
|
|
97
96
|
"../../../../../persistence/jobs-store.js",
|
|
98
97
|
"../../../../../persistence/raw-query.js",
|
|
99
98
|
"../../../../../persistence/schema/index.js",
|
|
100
|
-
"../../../../../prompts/system-prompt.js",
|
|
101
|
-
"../../../../../providers/platform-proxy/context.js",
|
|
102
|
-
"../../../../../runtime/background-job-runner.js",
|
|
103
99
|
"../../../../../security/untrusted-content.js",
|
|
104
|
-
"../../../../agent/image-optimize.js",
|
|
105
100
|
"../../../../api/events/memory-recalled.js",
|
|
106
101
|
"../../../../api/responses/memory-v3-selection-log.js",
|
|
102
|
+
"../../../../channels/types.js",
|
|
107
103
|
"../../../../config/assistant-feature-flags.js",
|
|
108
104
|
"../../../../config/default-profile-catalog.js",
|
|
109
105
|
"../../../../config/loader.js",
|
|
110
106
|
"../../../../config/memory-v3-gate.js",
|
|
111
107
|
"../../../../config/schema.js",
|
|
108
|
+
"../../../../config/schemas/memory-v2.js",
|
|
112
109
|
"../../../../config/skill-state.js",
|
|
113
110
|
"../../../../config/skills.js",
|
|
114
111
|
"../../../../config/types.js",
|
|
@@ -117,25 +114,32 @@ const BASELINE: Record<string, readonly string[]> = {
|
|
|
117
114
|
"../../../../daemon/conversation-notices.js",
|
|
118
115
|
"../../../../daemon/conversation-registry.js",
|
|
119
116
|
"../../../../daemon/conversation-runtime-assembly.js",
|
|
120
|
-
"../../../../daemon/
|
|
117
|
+
"../../../../daemon/embedding-reconcile.js",
|
|
121
118
|
"../../../../daemon/trust-context.js",
|
|
122
119
|
"../../../../daemon/turn-latency-sub-spans.js",
|
|
120
|
+
"../../../../notifications/emit-signal.js",
|
|
123
121
|
"../../../../persistence/checkpoints.js",
|
|
124
122
|
"../../../../persistence/db-connection.js",
|
|
125
123
|
"../../../../persistence/embeddings/embed.js",
|
|
126
124
|
"../../../../persistence/embeddings/embedding-backend.js",
|
|
127
125
|
"../../../../persistence/embeddings/embedding-billing-breaker.js",
|
|
128
126
|
"../../../../persistence/embeddings/embedding-cache.js",
|
|
127
|
+
"../../../../persistence/embeddings/embedding-runtime-manager.js",
|
|
129
128
|
"../../../../persistence/embeddings/embedding-types.js",
|
|
130
129
|
"../../../../persistence/embeddings/qdrant-circuit-breaker.js",
|
|
131
130
|
"../../../../persistence/embeddings/qdrant-client.js",
|
|
131
|
+
"../../../../persistence/embeddings/sparse-tokenize.js",
|
|
132
132
|
"../../../../persistence/job-utils.js",
|
|
133
133
|
"../../../../persistence/jobs-store.js",
|
|
134
|
-
"../../../../persistence/raw-query.js",
|
|
135
134
|
"../../../../persistence/schema/conversations.js",
|
|
136
135
|
"../../../../persistence/schema/index.js",
|
|
136
|
+
"../../../../prompts/persona-resolver.js",
|
|
137
|
+
"../../../../prompts/system-prompt.js",
|
|
138
|
+
"../../../../prompts/template-detection.js",
|
|
139
|
+
"../../../../providers/platform-proxy/context.js",
|
|
137
140
|
"../../../../runtime/assistant-event-hub.js",
|
|
138
141
|
"../../../../runtime/auth/route-policy.js",
|
|
142
|
+
"../../../../runtime/background-job-runner.js",
|
|
139
143
|
"../../../../runtime/routes/errors.js",
|
|
140
144
|
"../../../../runtime/routes/types.js",
|
|
141
145
|
"../../../../security/secret-scanner.js",
|
|
@@ -149,7 +153,6 @@ const BASELINE: Record<string, readonly string[]> = {
|
|
|
149
153
|
"../../../config/memory-v3-gate.js",
|
|
150
154
|
"../../../config/platform-rehydration.js",
|
|
151
155
|
"../../../config/schema.js",
|
|
152
|
-
"../../../config/schemas/memory-v2.js",
|
|
153
156
|
"../../../config/schemas/memory.js",
|
|
154
157
|
"../../../config/types.js",
|
|
155
158
|
"../../../contacts/guardian-delivery-reader.js",
|
|
@@ -177,7 +180,6 @@ const BASELINE: Record<string, readonly string[]> = {
|
|
|
177
180
|
"../../../persistence/db-maintenance.js",
|
|
178
181
|
"../../../persistence/embeddings/embedding-backend.js",
|
|
179
182
|
"../../../persistence/embeddings/embedding-billing-breaker.js",
|
|
180
|
-
"../../../persistence/embeddings/embedding-runtime-manager.js",
|
|
181
183
|
"../../../persistence/embeddings/embedding-types.js",
|
|
182
184
|
"../../../persistence/embeddings/messages-lexical-index.js",
|
|
183
185
|
"../../../persistence/embeddings/qdrant-circuit-breaker.js",
|
|
@@ -192,11 +194,9 @@ const BASELINE: Record<string, readonly string[]> = {
|
|
|
192
194
|
"../../../persistence/schema/index.js",
|
|
193
195
|
"../../../prompts/persona-resolver.js",
|
|
194
196
|
"../../../prompts/system-prompt.js",
|
|
195
|
-
"../../../prompts/template-detection.js",
|
|
196
197
|
"../../../runtime/actor-trust-resolver.js",
|
|
197
198
|
"../../../runtime/agent-wake.js",
|
|
198
199
|
"../../../runtime/assistant-stream-state.js",
|
|
199
|
-
"../../../runtime/background-job-runner.js",
|
|
200
200
|
"../../../runtime/capabilities.js",
|
|
201
201
|
"../../../runtime/services/auto-analysis-guard.js",
|
|
202
202
|
"../../../runtime/sync/resource-sync-events.js",
|
|
@@ -100,10 +100,6 @@ mock.module("../memory/query-builder.js", () => ({
|
|
|
100
100
|
buildMemoryQuery: () => "",
|
|
101
101
|
}));
|
|
102
102
|
|
|
103
|
-
mock.module("../plugins/defaults/memory/retrieval-budget.js", () => ({
|
|
104
|
-
computeRecallBudget: () => 0,
|
|
105
|
-
}));
|
|
106
|
-
|
|
107
103
|
mock.module("../runtime/sync/sync-publisher.js", () => ({
|
|
108
104
|
publishSyncInvalidation: () => {},
|
|
109
105
|
}));
|
|
@@ -124,7 +124,7 @@ mock.module("../persistence/db-connection.js", () => ({
|
|
|
124
124
|
|
|
125
125
|
// ── Tests ────────────────────────────────────────────────────────────
|
|
126
126
|
|
|
127
|
-
import { rebuildIndexJob } from "../plugins/defaults/memory/job-handlers/index-maintenance.js";
|
|
127
|
+
import { rebuildIndexJob } from "../plugins/defaults/memory/v1/job-handlers/index-maintenance.js";
|
|
128
128
|
|
|
129
129
|
describe("rebuildIndexJob", () => {
|
|
130
130
|
beforeEach(() => {
|
|
@@ -8,16 +8,16 @@
|
|
|
8
8
|
|
|
9
9
|
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
10
10
|
|
|
11
|
-
import type {
|
|
11
|
+
import type { AssistantEvent } from "../api/index.js";
|
|
12
12
|
import { setConfig } from "./helpers/set-config.js";
|
|
13
13
|
|
|
14
14
|
// A short permission timeout keeps a leaked prompt from lingering; the default
|
|
15
15
|
// `secretDetection.allowOneTimeSend` (false) drives the broadcast field.
|
|
16
16
|
setConfig("timeouts", { permissionTimeoutSec: 0.01 });
|
|
17
17
|
|
|
18
|
-
let broadcastMessages:
|
|
18
|
+
let broadcastMessages: AssistantEvent[] = [];
|
|
19
19
|
mock.module("../runtime/assistant-event-hub.js", () => ({
|
|
20
|
-
broadcastMessage: (msg:
|
|
20
|
+
broadcastMessage: (msg: AssistantEvent) => broadcastMessages.push(msg),
|
|
21
21
|
}));
|
|
22
22
|
|
|
23
23
|
const _piStore = new Map<string, { rpcResolve?: (value: unknown) => void }>();
|
|
@@ -177,11 +177,11 @@ describe("requestSecretStandalone channel gate", () => {
|
|
|
177
177
|
});
|
|
178
178
|
|
|
179
179
|
test("falls back to a plain unsupported_channel when minting is refused", async () => {
|
|
180
|
-
// GIVEN the gateway refuses to mint (
|
|
180
|
+
// GIVEN the gateway refuses to mint (no public URL)
|
|
181
181
|
registeredConversation = {
|
|
182
182
|
channelCapabilities: { supportsDynamicUi: false },
|
|
183
183
|
};
|
|
184
|
-
gatewayMintResult = { ok: false, error: "
|
|
184
|
+
gatewayMintResult = { ok: false, error: "no_public_base_url" };
|
|
185
185
|
|
|
186
186
|
// WHEN a standalone prompt is scoped to that conversation
|
|
187
187
|
const result = await requestSecretStandalone({
|
|
@@ -19,6 +19,10 @@ import {
|
|
|
19
19
|
|
|
20
20
|
import { RiskLevel, type ScopeOption } from "../permissions/types.js";
|
|
21
21
|
import type { ToolExecutionResult } from "../tools/types.js";
|
|
22
|
+
import {
|
|
23
|
+
installThresholdReaderMock,
|
|
24
|
+
thresholdReaderMock,
|
|
25
|
+
} from "./gateway-threshold-reader-mock.js";
|
|
22
26
|
|
|
23
27
|
// ---------------------------------------------------------------------------
|
|
24
28
|
// Terminal audit mock — the permission checker / executor call these directly
|
|
@@ -55,13 +59,6 @@ let riskOverride: string = "high";
|
|
|
55
59
|
/** Scope options override — controls whether persistent decisions are offered. */
|
|
56
60
|
let scopeOptionsOverride: ScopeOption[] | undefined;
|
|
57
61
|
|
|
58
|
-
/**
|
|
59
|
-
* Auto-approve threshold returned to the permission checker. "high" is the
|
|
60
|
-
* full-access posture under which the requireFreshApproval promotion is
|
|
61
|
-
* skipped; every lower value still promotes allow → prompt.
|
|
62
|
-
*/
|
|
63
|
-
let thresholdOverride: "none" | "low" | "medium" | "high" = "medium";
|
|
64
|
-
|
|
65
62
|
/**
|
|
66
63
|
* Sentinel cell query the mocked builder returns. When set, the permission
|
|
67
64
|
* checker must thread it into every gateway threshold read for the
|
|
@@ -69,8 +66,23 @@ let thresholdOverride: "none" | "low" | "medium" | "high" = "medium";
|
|
|
69
66
|
*/
|
|
70
67
|
let cellQueryOverride: Record<string, unknown> | undefined;
|
|
71
68
|
|
|
69
|
+
// Falls through to the real builder when no sentinel is set. `mock.module` is
|
|
70
|
+
// process-global, so a hard-coded return here would also be the builder other
|
|
71
|
+
// test files see — and silently strip the channel coordinates their contexts
|
|
72
|
+
// supply, depending on which registration loaded last. The real function is
|
|
73
|
+
// captured by value first: `mock.module` swaps the module's exports in place,
|
|
74
|
+
// so reading it through the namespace inside the factory would resolve to this
|
|
75
|
+
// mock and recurse.
|
|
76
|
+
const realCellQueryModule =
|
|
77
|
+
await import("../permissions/channel-permission-query.js");
|
|
78
|
+
const realBuildCellQuery = realCellQueryModule.buildChannelPermissionCellQuery;
|
|
79
|
+
const realEffectiveCellThreshold =
|
|
80
|
+
realCellQueryModule.effectiveChannelCellThreshold;
|
|
72
81
|
mock.module("../permissions/channel-permission-query.js", () => ({
|
|
73
|
-
buildChannelPermissionCellQuery: (
|
|
82
|
+
buildChannelPermissionCellQuery: (
|
|
83
|
+
...args: Parameters<typeof realBuildCellQuery>
|
|
84
|
+
) => cellQueryOverride ?? realBuildCellQuery(...args),
|
|
85
|
+
effectiveChannelCellThreshold: realEffectiveCellThreshold,
|
|
74
86
|
}));
|
|
75
87
|
|
|
76
88
|
mock.module("../permissions/checker.js", () => ({
|
|
@@ -130,28 +142,15 @@ mock.module("../tools/registry.js", () => ({
|
|
|
130
142
|
getAllTools: () => [],
|
|
131
143
|
}));
|
|
132
144
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
getAutoApproveThreshold: async (
|
|
143
|
-
conversationId?: string,
|
|
144
|
-
executionContext?: string,
|
|
145
|
-
cellQuery?: Record<string, unknown>,
|
|
146
|
-
) => {
|
|
147
|
-
thresholdReadLog.push({ conversationId, executionContext, cellQuery });
|
|
148
|
-
return thresholdOverride;
|
|
149
|
-
},
|
|
150
|
-
// Refresh failure ("null") keeps the original decision — these tests
|
|
151
|
-
// exercise the cached-threshold paths only.
|
|
152
|
-
refreshAutoApproveThreshold: async () => null,
|
|
153
|
-
_clearGlobalCacheForTesting: () => {},
|
|
154
|
-
}));
|
|
145
|
+
// The mock defaults leave no cell at any cascade level, so the sensitive-tool
|
|
146
|
+
// gate's capability floor stands on its own — these tests are about
|
|
147
|
+
// fresh-approval promotion, not the channel matrix. `thresholdReads` records
|
|
148
|
+
// every getAutoApproveThreshold call so tests can assert the cell query is
|
|
149
|
+
// threaded into each read (including the background auto-approve).
|
|
150
|
+
installThresholdReaderMock();
|
|
151
|
+
|
|
152
|
+
/** Records every getAutoApproveThreshold call. */
|
|
153
|
+
const thresholdReadLog = thresholdReaderMock.thresholdReads;
|
|
155
154
|
|
|
156
155
|
// Stub the workflow run manager so the `manage_workflows` resume gate can read a
|
|
157
156
|
// target run's STORED capabilities without a real journal/DB. Tests set
|
|
@@ -168,6 +167,7 @@ mock.module("../workflows/run-manager.js", () => ({
|
|
|
168
167
|
|
|
169
168
|
mock.module("../tools/shared/filesystem/path-policy.js", () => ({
|
|
170
169
|
sandboxPolicy: () => ({ ok: false }),
|
|
170
|
+
sandboxPolicyWithHostFallback: () => ({ ok: false }),
|
|
171
171
|
hostPolicy: () => ({ ok: false }),
|
|
172
172
|
}));
|
|
173
173
|
|
|
@@ -208,7 +208,7 @@ describe("requireFreshApproval: non-interactive guardian denial", () => {
|
|
|
208
208
|
checkResultOverride = undefined;
|
|
209
209
|
scopeOptionsOverride = undefined;
|
|
210
210
|
riskOverride = "high";
|
|
211
|
-
|
|
211
|
+
thresholdReaderMock.threshold = "medium";
|
|
212
212
|
cellQueryOverride = undefined;
|
|
213
213
|
thresholdReadLog.length = 0;
|
|
214
214
|
});
|
|
@@ -374,7 +374,7 @@ describe("requireFreshApproval: context flag propagation", () => {
|
|
|
374
374
|
checkResultOverride = undefined;
|
|
375
375
|
scopeOptionsOverride = undefined;
|
|
376
376
|
riskOverride = "high";
|
|
377
|
-
|
|
377
|
+
thresholdReaderMock.threshold = "medium";
|
|
378
378
|
});
|
|
379
379
|
|
|
380
380
|
afterEach(() => {});
|
|
@@ -403,7 +403,7 @@ describe("requireFreshApproval: workflow capability grants", () => {
|
|
|
403
403
|
checkResultOverride = undefined;
|
|
404
404
|
scopeOptionsOverride = undefined;
|
|
405
405
|
riskOverride = "low";
|
|
406
|
-
|
|
406
|
+
thresholdReaderMock.threshold = "medium";
|
|
407
407
|
fakeWorkflowRun = null;
|
|
408
408
|
});
|
|
409
409
|
|
|
@@ -444,7 +444,7 @@ describe("requireFreshApproval: workflow capability grants", () => {
|
|
|
444
444
|
"run_workflow side-effecting launch prompts at the %s threshold (non-full-access posture)",
|
|
445
445
|
async (threshold) => {
|
|
446
446
|
checkResultOverride = { decision: "allow", reason: "allowed" };
|
|
447
|
-
|
|
447
|
+
thresholdReaderMock.threshold = threshold;
|
|
448
448
|
const state = { prompted: false };
|
|
449
449
|
const executor = new ToolExecutor(trackingPrompter(state));
|
|
450
450
|
const ctx = makeContext();
|
|
@@ -465,7 +465,7 @@ describe("requireFreshApproval: workflow capability grants", () => {
|
|
|
465
465
|
// Full-access posture auto-approves even high-risk tools, so the
|
|
466
466
|
// requireFreshApproval promotion is skipped — the grant auto-allows.
|
|
467
467
|
checkResultOverride = { decision: "allow", reason: "allowed" };
|
|
468
|
-
|
|
468
|
+
thresholdReaderMock.threshold = "high";
|
|
469
469
|
const state = { prompted: false };
|
|
470
470
|
const executor = new ToolExecutor(trackingPrompter(state));
|
|
471
471
|
const ctx = makeContext();
|
|
@@ -487,7 +487,7 @@ describe("requireFreshApproval: workflow capability grants", () => {
|
|
|
487
487
|
// Full access skips the fresh-approval promotion but never overrides an
|
|
488
488
|
// explicit deny — deny rules win regardless of posture.
|
|
489
489
|
checkResultOverride = { decision: "deny", reason: "blocked by rule" };
|
|
490
|
-
|
|
490
|
+
thresholdReaderMock.threshold = "high";
|
|
491
491
|
const state = { prompted: false };
|
|
492
492
|
const executor = new ToolExecutor(trackingPrompter(state));
|
|
493
493
|
const ctx = makeContext();
|
|
@@ -504,7 +504,7 @@ describe("requireFreshApproval: workflow capability grants", () => {
|
|
|
504
504
|
|
|
505
505
|
test("a deny rule still blocks a side-effecting launch at a normal threshold", async () => {
|
|
506
506
|
checkResultOverride = { decision: "deny", reason: "blocked by rule" };
|
|
507
|
-
|
|
507
|
+
thresholdReaderMock.threshold = "medium";
|
|
508
508
|
const state = { prompted: false };
|
|
509
509
|
const executor = new ToolExecutor(trackingPrompter(state));
|
|
510
510
|
const ctx = makeContext();
|
|
@@ -522,7 +522,7 @@ describe("requireFreshApproval: workflow capability grants", () => {
|
|
|
522
522
|
test("a read-only launch (no requireFreshApproval) is unaffected by a normal threshold", async () => {
|
|
523
523
|
// No requireFreshApproval means the allow stands untouched at any posture.
|
|
524
524
|
checkResultOverride = { decision: "allow", reason: "allowed" };
|
|
525
|
-
|
|
525
|
+
thresholdReaderMock.threshold = "medium";
|
|
526
526
|
const state = { prompted: false };
|
|
527
527
|
const executor = new ToolExecutor(trackingPrompter(state));
|
|
528
528
|
const ctx = makeContext();
|
|
@@ -24,6 +24,18 @@ function makeApp(id: string, updatedAt: number): AppDefinition {
|
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
/** An app the conversation only reached through a descendant's lineage. */
|
|
28
|
+
function makeInheritedApp(
|
|
29
|
+
id: string,
|
|
30
|
+
updatedAt: number,
|
|
31
|
+
conversationId: string,
|
|
32
|
+
): AppDefinition {
|
|
33
|
+
return {
|
|
34
|
+
...makeApp(id, updatedAt),
|
|
35
|
+
inheritedConversationIds: [conversationId],
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
27
39
|
describe("resolveAppId", () => {
|
|
28
40
|
test("returns an explicit non-empty app_id unchanged", () => {
|
|
29
41
|
appsByConversation = [makeApp("other", 1)];
|
|
@@ -45,6 +57,26 @@ describe("resolveAppId", () => {
|
|
|
45
57
|
appsByConversation = [];
|
|
46
58
|
expect(resolveAppId({}, "conv-1")).toBeNull();
|
|
47
59
|
});
|
|
60
|
+
|
|
61
|
+
test("prefers a direct app over a more recent lineage-linked one", () => {
|
|
62
|
+
// A background subagent's app is linked into the parent thread and, being
|
|
63
|
+
// newest, heads the list — it must not capture the parent's implicit call.
|
|
64
|
+
appsByConversation = [
|
|
65
|
+
makeInheritedApp("background", 30, "conv-1"),
|
|
66
|
+
makeApp("foreground", 10),
|
|
67
|
+
];
|
|
68
|
+
expect(resolveAppId({}, "conv-1")).toBe("foreground");
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test("falls back to a lineage-linked app when the conversation has no direct one", () => {
|
|
72
|
+
appsByConversation = [makeInheritedApp("background", 30, "conv-1")];
|
|
73
|
+
expect(resolveAppId({}, "conv-1")).toBe("background");
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
test("an app inherited by another conversation is direct here", () => {
|
|
77
|
+
appsByConversation = [makeInheritedApp("shared", 30, "conv-other")];
|
|
78
|
+
expect(resolveAppId({}, "conv-1")).toBe("shared");
|
|
79
|
+
});
|
|
48
80
|
});
|
|
49
81
|
|
|
50
82
|
describe("missingAppIdError", () => {
|
|
@@ -41,9 +41,24 @@ mock.module("../notifications/emit-signal.js", () => ({
|
|
|
41
41
|
emitNotificationSignal: mockEmitNotificationSignal,
|
|
42
42
|
}));
|
|
43
43
|
|
|
44
|
+
// Scripted quiesce-lease answers, consumed one per isLifecycleQuiesced()
|
|
45
|
+
// call; empty means "no lease" (the real fail-open default), so existing
|
|
46
|
+
// tests run ungated. Lets a test arm the lease BETWEEN the claim-site check
|
|
47
|
+
// and the per-job re-check, which no real interleaving can do determinstically.
|
|
48
|
+
let quiesceAnswers: boolean[] = [];
|
|
49
|
+
const realLifecycleQuiesce =
|
|
50
|
+
await import("../persistence/lifecycle-quiesce.js");
|
|
51
|
+
mock.module("../persistence/lifecycle-quiesce.js", () => ({
|
|
52
|
+
...realLifecycleQuiesce,
|
|
53
|
+
isLifecycleQuiesced: () => quiesceAnswers.shift() ?? false,
|
|
54
|
+
}));
|
|
55
|
+
|
|
44
56
|
import { getDb } from "../persistence/db-connection.js";
|
|
45
57
|
import { initializeDb } from "../persistence/db-init.js";
|
|
46
|
-
import {
|
|
58
|
+
import {
|
|
59
|
+
createSchedule,
|
|
60
|
+
deferClaimedSchedule,
|
|
61
|
+
} from "../schedule/schedule-store.js";
|
|
47
62
|
import { runDueSchedulesOnce } from "../schedule/scheduler.js";
|
|
48
63
|
|
|
49
64
|
await initializeDb();
|
|
@@ -55,6 +70,7 @@ function rawDb(): import("bun:sqlite").Database {
|
|
|
55
70
|
|
|
56
71
|
beforeEach(() => {
|
|
57
72
|
mockEmitNotificationSignal.mockClear();
|
|
73
|
+
quiesceAnswers = [];
|
|
58
74
|
const db = getDb();
|
|
59
75
|
db.run("DELETE FROM cron_runs");
|
|
60
76
|
db.run("DELETE FROM cron_jobs");
|
|
@@ -120,6 +136,61 @@ describe("runDueSchedulesOnce (the schedule worker's tick)", () => {
|
|
|
120
136
|
expect(row.enabled).toBe(0);
|
|
121
137
|
});
|
|
122
138
|
|
|
139
|
+
test("a lease armed between claim and start defers the job back to the queue", async () => {
|
|
140
|
+
const oneShot = await createSchedule({
|
|
141
|
+
name: "Deferred notify",
|
|
142
|
+
cronExpression: null,
|
|
143
|
+
message: "ping",
|
|
144
|
+
mode: "notify",
|
|
145
|
+
nextRunAt: Date.now() - 1000,
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
// Call 1 is the claim-site gate (claimDueSchedules): no lease yet.
|
|
149
|
+
// Call 2 is the per-job re-check: the lease has landed.
|
|
150
|
+
quiesceAnswers = [false, true];
|
|
151
|
+
const result = await runDueSchedulesOnce();
|
|
152
|
+
|
|
153
|
+
expect(result.claimed).toBe(1);
|
|
154
|
+
expect(result.skipped).toBe(1);
|
|
155
|
+
expect(result.completed).toBe(0);
|
|
156
|
+
// Nothing executed and nothing was lost: no notification fired, and the
|
|
157
|
+
// one-shot is back in the queue with a near-future retry time.
|
|
158
|
+
expect(mockEmitNotificationSignal).not.toHaveBeenCalled();
|
|
159
|
+
const row = rawDb()
|
|
160
|
+
.query("SELECT status, next_run_at FROM cron_jobs WHERE id = ?")
|
|
161
|
+
.get(oneShot.id) as { status: string; next_run_at: number };
|
|
162
|
+
expect(row.status).toBe("active");
|
|
163
|
+
expect(row.next_run_at).toBeGreaterThan(Date.now());
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
test("deferClaimedSchedule restores an exhausted recurring claim", async () => {
|
|
167
|
+
const recurring = await createSchedule({
|
|
168
|
+
name: "Bounded recurring",
|
|
169
|
+
cronExpression: "* * * * *",
|
|
170
|
+
message: "final occurrence",
|
|
171
|
+
mode: "notify",
|
|
172
|
+
});
|
|
173
|
+
// A bounded recurring schedule's FINAL occurrence is claimed by
|
|
174
|
+
// exhausting the job: enabled = false, nextRunAt = 0.
|
|
175
|
+
rawDb().run(
|
|
176
|
+
"UPDATE cron_jobs SET enabled = 0, next_run_at = 0 WHERE id = ?",
|
|
177
|
+
[recurring.id],
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
await deferClaimedSchedule(recurring.id, Date.now() + 30_000);
|
|
181
|
+
|
|
182
|
+
const row = rawDb()
|
|
183
|
+
.query("SELECT enabled, next_run_at, status FROM cron_jobs WHERE id = ?")
|
|
184
|
+
.get(recurring.id) as {
|
|
185
|
+
enabled: number;
|
|
186
|
+
next_run_at: number;
|
|
187
|
+
status: string;
|
|
188
|
+
};
|
|
189
|
+
expect(row.enabled).toBe(1);
|
|
190
|
+
expect(row.next_run_at).toBeGreaterThan(Date.now());
|
|
191
|
+
expect(row.status).toBe("active");
|
|
192
|
+
});
|
|
193
|
+
|
|
123
194
|
test("records an error run and schedules a retry when a script fails", async () => {
|
|
124
195
|
const failing = await createSchedule({
|
|
125
196
|
name: "Failing script",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* HTTP parity tests for the SSE assistant-events endpoint.
|
|
3
3
|
*
|
|
4
|
-
* Asserts that every streaming/delta
|
|
4
|
+
* Asserts that every streaming/delta AssistantEvent type is preserved
|
|
5
5
|
* exactly — field-for-field — when delivered through the SSE route.
|
|
6
6
|
*
|
|
7
7
|
* Message types covered:
|
|
@@ -17,11 +17,10 @@
|
|
|
17
17
|
*/
|
|
18
18
|
import { beforeEach, describe, expect, test } from "bun:test";
|
|
19
19
|
|
|
20
|
-
import type {
|
|
20
|
+
import type { AssistantEvent, AssistantEventEnvelope } from "../api/index.js";
|
|
21
21
|
import { getOrCreateConversation } from "../persistence/conversation-key-store.js";
|
|
22
22
|
import { getDb } from "../persistence/db-connection.js";
|
|
23
23
|
import { initializeDb } from "../persistence/db-init.js";
|
|
24
|
-
import type { AssistantEvent } from "../runtime/assistant-event.js";
|
|
25
24
|
import { buildAssistantEvent } from "../runtime/assistant-event.js";
|
|
26
25
|
import { assistantEventHub } from "../runtime/assistant-event-hub.js";
|
|
27
26
|
|
|
@@ -33,15 +32,15 @@ await initializeDb();
|
|
|
33
32
|
|
|
34
33
|
/**
|
|
35
34
|
* Subscribe to the SSE endpoint for a given conversationKey, publish one
|
|
36
|
-
* event, read the first SSE frame, and return the parsed
|
|
35
|
+
* event, read the first SSE frame, and return the parsed AssistantEventEnvelope.
|
|
37
36
|
*
|
|
38
37
|
* Uses handleSubscribeAssistantEvents directly (bypassing HTTP) to avoid
|
|
39
38
|
* chunked-transfer buffering in Bun's loopback implementation.
|
|
40
39
|
*/
|
|
41
40
|
async function publishAndReadFrame(
|
|
42
41
|
conversationKey: string,
|
|
43
|
-
message:
|
|
44
|
-
): Promise<
|
|
42
|
+
message: AssistantEvent,
|
|
43
|
+
): Promise<AssistantEventEnvelope> {
|
|
45
44
|
const { conversationId } = getOrCreateConversation(conversationKey);
|
|
46
45
|
|
|
47
46
|
const ac = new AbortController();
|
|
@@ -68,8 +67,10 @@ async function publishAndReadFrame(
|
|
|
68
67
|
const frame = new TextDecoder().decode(value);
|
|
69
68
|
// SSE frame: "event: assistant_event\nid: <id>\ndata: <json>\n\n"
|
|
70
69
|
const dataLine = frame.split("\n").find((l) => l.startsWith("data: "));
|
|
71
|
-
if (!dataLine)
|
|
72
|
-
|
|
70
|
+
if (!dataLine) {
|
|
71
|
+
throw new Error(`No data line in SSE frame:\n${frame}`);
|
|
72
|
+
}
|
|
73
|
+
return JSON.parse(dataLine.slice("data: ".length)) as AssistantEventEnvelope;
|
|
73
74
|
}
|
|
74
75
|
|
|
75
76
|
// ---------------------------------------------------------------------------
|
|
@@ -317,7 +318,7 @@ describe("SSE HTTP parity — streaming/delta message types", () => {
|
|
|
317
318
|
abortSignal: ac.signal,
|
|
318
319
|
});
|
|
319
320
|
|
|
320
|
-
const msg:
|
|
321
|
+
const msg: AssistantEvent = {
|
|
321
322
|
type: "assistant_text_delta" as const,
|
|
322
323
|
text: "envelope test",
|
|
323
324
|
};
|
|
@@ -337,7 +338,7 @@ describe("SSE HTTP parity — streaming/delta message types", () => {
|
|
|
337
338
|
const dataLine = frame.split("\n").find((l) => l.startsWith("data: "))!;
|
|
338
339
|
const received = JSON.parse(
|
|
339
340
|
dataLine.slice("data: ".length),
|
|
340
|
-
) as
|
|
341
|
+
) as AssistantEventEnvelope;
|
|
341
342
|
|
|
342
343
|
// Envelope fields
|
|
343
344
|
expect(received.id).toBe(published.id);
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Tests:
|
|
5
5
|
* - 401 unauthorized (missing bearer token)
|
|
6
6
|
* - 200 when conversationKey is omitted (unfiltered subscription)
|
|
7
|
-
* - Happy path: stream receives a published
|
|
7
|
+
* - Happy path: stream receives a published AssistantEventEnvelope
|
|
8
8
|
* - Unfiltered: streams events from multiple conversations
|
|
9
9
|
*/
|
|
10
10
|
import { beforeEach, describe, expect, test } from "bun:test";
|
|
@@ -38,10 +38,12 @@ mock.module("../daemon/conversation-store.js", () => ({
|
|
|
38
38
|
},
|
|
39
39
|
}));
|
|
40
40
|
|
|
41
|
+
import type { AssistantEventEnvelope } from "../api/index.js";
|
|
41
42
|
import { SYNC_TAGS } from "../daemon/message-types/sync.js";
|
|
42
43
|
import {
|
|
43
44
|
insertPendingHeartbeatRun,
|
|
44
45
|
startHeartbeatRun,
|
|
46
|
+
supersedePendingRun,
|
|
45
47
|
} from "../heartbeat/heartbeat-run-store.js";
|
|
46
48
|
import {
|
|
47
49
|
archiveConversation,
|
|
@@ -51,7 +53,6 @@ import { getDb } from "../persistence/db-connection.js";
|
|
|
51
53
|
import { initializeDb } from "../persistence/db-init.js";
|
|
52
54
|
import { recordUsageEvent } from "../persistence/llm-usage-store.js";
|
|
53
55
|
import { rawRun } from "../persistence/raw-query.js";
|
|
54
|
-
import type { AssistantEvent } from "../runtime/assistant-event.js";
|
|
55
56
|
import { assistantEventHub } from "../runtime/assistant-event-hub.js";
|
|
56
57
|
import { BadRequestError, NotFoundError } from "../runtime/routes/errors.js";
|
|
57
58
|
import { ROUTES as HEARTBEAT_ROUTES } from "../runtime/routes/heartbeat-routes.js";
|
|
@@ -82,7 +83,9 @@ function findRoute(endpoint: string, method: string): RouteDefinition {
|
|
|
82
83
|
const route = SCHEDULE_ROUTES.find(
|
|
83
84
|
(r) => r.endpoint === endpoint && r.method === method,
|
|
84
85
|
);
|
|
85
|
-
if (!route)
|
|
86
|
+
if (!route) {
|
|
87
|
+
throw new Error(`Route ${method} ${endpoint} not found`);
|
|
88
|
+
}
|
|
86
89
|
return route;
|
|
87
90
|
}
|
|
88
91
|
|
|
@@ -90,7 +93,9 @@ function findHeartbeatRoute(endpoint: string, method: string): RouteDefinition {
|
|
|
90
93
|
const route = HEARTBEAT_ROUTES.find(
|
|
91
94
|
(r) => r.endpoint === endpoint && r.method === method,
|
|
92
95
|
);
|
|
93
|
-
if (!route)
|
|
96
|
+
if (!route) {
|
|
97
|
+
throw new Error(`Route ${method} ${endpoint} not found`);
|
|
98
|
+
}
|
|
94
99
|
return route;
|
|
95
100
|
}
|
|
96
101
|
|
|
@@ -152,7 +157,9 @@ function setScheduleRunWindow({
|
|
|
152
157
|
async function waitFor(predicate: () => boolean): Promise<void> {
|
|
153
158
|
const deadline = Date.now() + 500;
|
|
154
159
|
while (Date.now() < deadline) {
|
|
155
|
-
if (predicate())
|
|
160
|
+
if (predicate()) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
156
163
|
await new Promise((resolve) => setTimeout(resolve, 5));
|
|
157
164
|
}
|
|
158
165
|
throw new Error("Timed out waiting for schedule route event");
|
|
@@ -417,7 +424,7 @@ describe("GET /schedules — default defer exclusion", () => {
|
|
|
417
424
|
});
|
|
418
425
|
|
|
419
426
|
test("mutation routes emit schedule sync invalidation", async () => {
|
|
420
|
-
const received:
|
|
427
|
+
const received: AssistantEventEnvelope[] = [];
|
|
421
428
|
const subscription = assistantEventHub.subscribe({
|
|
422
429
|
type: "process",
|
|
423
430
|
callback: (event) => {
|
|
@@ -840,6 +847,38 @@ describe("schedule and heartbeat run metadata", () => {
|
|
|
840
847
|
|
|
841
848
|
expect(result.runs[0].estimatedCostUsd).toBeCloseTo(0.02);
|
|
842
849
|
});
|
|
850
|
+
|
|
851
|
+
test("heartbeat runs omit bookkeeping rows so timer resets don't render as runs", () => {
|
|
852
|
+
const now = Date.now();
|
|
853
|
+
|
|
854
|
+
// Timer resets (e.g. guardian messages) supersede the pending row and
|
|
855
|
+
// schedule a new one an interval into the future.
|
|
856
|
+
for (let i = 0; i < 3; i++) {
|
|
857
|
+
supersedePendingRun(insertPendingHeartbeatRun(now + 60 * 60 * 1000 + i));
|
|
858
|
+
}
|
|
859
|
+
// The next scheduled run, not yet fired.
|
|
860
|
+
insertPendingHeartbeatRun(now + 60 * 60 * 1000 + 10);
|
|
861
|
+
|
|
862
|
+
// The one run that actually executed.
|
|
863
|
+
const okId = insertPendingHeartbeatRun(now - 1000);
|
|
864
|
+
startHeartbeatRun(okId);
|
|
865
|
+
rawRun(
|
|
866
|
+
"test:setHeartbeatRunOk",
|
|
867
|
+
"UPDATE heartbeat_runs SET status = 'ok', finished_at = ?, duration_ms = ? WHERE id = ?",
|
|
868
|
+
now,
|
|
869
|
+
1000,
|
|
870
|
+
okId,
|
|
871
|
+
);
|
|
872
|
+
|
|
873
|
+
const route = findHeartbeatRoute("heartbeat/runs", "GET");
|
|
874
|
+
const result = route.handler({}) as {
|
|
875
|
+
runs: Array<{ id: string; status: string }>;
|
|
876
|
+
};
|
|
877
|
+
|
|
878
|
+
expect(result.runs).toHaveLength(1);
|
|
879
|
+
expect(result.runs[0].id).toBe(okId);
|
|
880
|
+
expect(result.runs[0].status).toBe("ok");
|
|
881
|
+
});
|
|
843
882
|
});
|
|
844
883
|
|
|
845
884
|
// ── schedules/usage-summary ───────────────────────────────────────────────
|