@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
|
@@ -34,7 +34,7 @@ let fetchCalls: Array<{ url: string; init?: RequestInit }>;
|
|
|
34
34
|
let fetchHandler: (
|
|
35
35
|
url: string,
|
|
36
36
|
init?: RequestInit,
|
|
37
|
-
) => { ok: boolean; body: unknown };
|
|
37
|
+
) => { ok: boolean; body: unknown; scopes?: string };
|
|
38
38
|
|
|
39
39
|
beforeEach(() => {
|
|
40
40
|
mockSecureKeys = {};
|
|
@@ -45,10 +45,17 @@ beforeEach(() => {
|
|
|
45
45
|
globalThis.fetch = (async (input: RequestInfo | URL, init?: RequestInit) => {
|
|
46
46
|
const url = typeof input === "string" ? input : input.toString();
|
|
47
47
|
fetchCalls.push({ url, init });
|
|
48
|
-
const { ok, body } = fetchHandler(url, init);
|
|
48
|
+
const { ok, body, scopes } = fetchHandler(url, init);
|
|
49
|
+
const headers: Record<string, string> = {
|
|
50
|
+
"content-type": "application/json",
|
|
51
|
+
};
|
|
52
|
+
// Slack stamps the granted scopes on every Web API response.
|
|
53
|
+
if (scopes !== undefined) {
|
|
54
|
+
headers["x-oauth-scopes"] = scopes;
|
|
55
|
+
}
|
|
49
56
|
return new Response(JSON.stringify(body), {
|
|
50
57
|
status: ok ? 200 : 500,
|
|
51
|
-
headers
|
|
58
|
+
headers,
|
|
52
59
|
});
|
|
53
60
|
}) as typeof globalThis.fetch;
|
|
54
61
|
});
|
|
@@ -147,3 +154,144 @@ describe("slack remote probe (auth.test)", () => {
|
|
|
147
154
|
expect(authTest.message).toMatch(/ECONNREFUSED/);
|
|
148
155
|
});
|
|
149
156
|
});
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Slack can install an app with a fraction of the manifest's scopes while
|
|
160
|
+
* auth.test still succeeds — a live install produced 2 of 18, and the first
|
|
161
|
+
* real API call failed with missing_scope. auth.test passing is therefore not
|
|
162
|
+
* evidence the install is usable.
|
|
163
|
+
*/
|
|
164
|
+
describe("slack auth.test response validation", () => {
|
|
165
|
+
test("reports an unexpected shape instead of trusting the field types", async () => {
|
|
166
|
+
mockSecureKeys[credentialKey("slack_channel", "bot_token")] = "xoxb-fake";
|
|
167
|
+
// `ok` as a string slips past a cast and makes `!data.ok` decide on a
|
|
168
|
+
// truthy string rather than a boolean.
|
|
169
|
+
fetchHandler = () => ({ ok: true, body: { ok: "yes" } });
|
|
170
|
+
|
|
171
|
+
const [snapshot] = await runSlackRemoteProbe();
|
|
172
|
+
const authTest = snapshot.remoteChecks!.find(
|
|
173
|
+
(c) => c.name === "auth_test",
|
|
174
|
+
)!;
|
|
175
|
+
|
|
176
|
+
expect(authTest.passed).toBe(false);
|
|
177
|
+
expect(authTest.message).toMatch(/unexpected response shape/i);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
test("tolerates unknown fields Slack adds over time", async () => {
|
|
181
|
+
mockSecureKeys[credentialKey("slack_channel", "bot_token")] = "xoxb-fake";
|
|
182
|
+
fetchHandler = () => ({
|
|
183
|
+
ok: true,
|
|
184
|
+
body: { ok: true, team: "acme", user: "bot", some_new_field: 42 },
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
const [snapshot] = await runSlackRemoteProbe();
|
|
188
|
+
const authTest = snapshot.remoteChecks!.find(
|
|
189
|
+
(c) => c.name === "auth_test",
|
|
190
|
+
)!;
|
|
191
|
+
|
|
192
|
+
expect(authTest.passed).toBe(true);
|
|
193
|
+
});
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
describe("slack scope-grant check", () => {
|
|
197
|
+
const ALL_REQUIRED = [
|
|
198
|
+
"app_mentions:read",
|
|
199
|
+
"assistant:write",
|
|
200
|
+
"channels:history",
|
|
201
|
+
"channels:read",
|
|
202
|
+
"chat:write",
|
|
203
|
+
"groups:history",
|
|
204
|
+
"groups:read",
|
|
205
|
+
"im:history",
|
|
206
|
+
"im:read",
|
|
207
|
+
"im:write",
|
|
208
|
+
"mpim:history",
|
|
209
|
+
"mpim:read",
|
|
210
|
+
"users:read",
|
|
211
|
+
];
|
|
212
|
+
|
|
213
|
+
function okWithScopes(scopes: string) {
|
|
214
|
+
return () => ({
|
|
215
|
+
ok: true,
|
|
216
|
+
body: { ok: true, team_id: "T123", team: "acme", user: "apollobot" },
|
|
217
|
+
scopes,
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
test("passes when every required scope was granted", async () => {
|
|
222
|
+
mockSecureKeys[credentialKey("slack_channel", "bot_token")] = "xoxb-fake";
|
|
223
|
+
fetchHandler = okWithScopes(ALL_REQUIRED.join(","));
|
|
224
|
+
|
|
225
|
+
const [snapshot] = await runSlackRemoteProbe();
|
|
226
|
+
const scopeCheck = snapshot.remoteChecks!.find(
|
|
227
|
+
(c) => c.name === "scopes_granted",
|
|
228
|
+
)!;
|
|
229
|
+
|
|
230
|
+
expect(scopeCheck.passed).toBe(true);
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
test("ignores declinable scopes the workspace opted out of", async () => {
|
|
234
|
+
mockSecureKeys[credentialKey("slack_channel", "bot_token")] = "xoxb-fake";
|
|
235
|
+
// No files:read / reactions:* / channels:join — all marked optional in the
|
|
236
|
+
// manifest, so declining them is a choice, not a fault.
|
|
237
|
+
fetchHandler = okWithScopes(ALL_REQUIRED.join(","));
|
|
238
|
+
|
|
239
|
+
const [snapshot] = await runSlackRemoteProbe();
|
|
240
|
+
const scopeCheck = snapshot.remoteChecks!.find(
|
|
241
|
+
(c) => c.name === "scopes_granted",
|
|
242
|
+
)!;
|
|
243
|
+
|
|
244
|
+
expect(scopeCheck.passed).toBe(true);
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
test("catches the silent drop that auth.test reports as healthy", async () => {
|
|
248
|
+
mockSecureKeys[credentialKey("slack_channel", "bot_token")] = "xoxb-fake";
|
|
249
|
+
// The live symptom: token came back with a couple of scopes.
|
|
250
|
+
fetchHandler = okWithScopes("channels:history,chat:write");
|
|
251
|
+
|
|
252
|
+
const [snapshot] = await runSlackRemoteProbe();
|
|
253
|
+
const authTest = snapshot.remoteChecks!.find(
|
|
254
|
+
(c) => c.name === "auth_test",
|
|
255
|
+
)!;
|
|
256
|
+
const scopeCheck = snapshot.remoteChecks!.find(
|
|
257
|
+
(c) => c.name === "scopes_granted",
|
|
258
|
+
)!;
|
|
259
|
+
|
|
260
|
+
// auth.test is happy — that is exactly why this check has to exist.
|
|
261
|
+
expect(authTest.passed).toBe(true);
|
|
262
|
+
expect(scopeCheck.passed).toBe(false);
|
|
263
|
+
expect(scopeCheck.message).toContain("assistant:write");
|
|
264
|
+
expect(scopeCheck.message).not.toContain("chat:write,");
|
|
265
|
+
// Recovery order matters: the update prompt gates the reinstall.
|
|
266
|
+
expect(scopeCheck.message).toMatch(/update prompt/i);
|
|
267
|
+
expect(scopeCheck.message).toMatch(/Reinstall to Workspace/i);
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
test("stays passing when Slack sends no scope header", async () => {
|
|
271
|
+
mockSecureKeys[credentialKey("slack_channel", "bot_token")] = "xoxb-fake";
|
|
272
|
+
fetchHandler = () => ({
|
|
273
|
+
ok: true,
|
|
274
|
+
body: { ok: true, team_id: "T123", team: "acme", user: "apollobot" },
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
const [snapshot] = await runSlackRemoteProbe();
|
|
278
|
+
const scopeCheck = snapshot.remoteChecks!.find(
|
|
279
|
+
(c) => c.name === "scopes_granted",
|
|
280
|
+
)!;
|
|
281
|
+
|
|
282
|
+
expect(scopeCheck.passed).toBe(true);
|
|
283
|
+
expect(scopeCheck.message).toMatch(/skipped/i);
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
test("tolerates whitespace in the comma-separated header", async () => {
|
|
287
|
+
mockSecureKeys[credentialKey("slack_channel", "bot_token")] = "xoxb-fake";
|
|
288
|
+
fetchHandler = okWithScopes(` ${ALL_REQUIRED.join(" , ")} ,, `);
|
|
289
|
+
|
|
290
|
+
const [snapshot] = await runSlackRemoteProbe();
|
|
291
|
+
const scopeCheck = snapshot.remoteChecks!.find(
|
|
292
|
+
(c) => c.name === "scopes_granted",
|
|
293
|
+
)!;
|
|
294
|
+
|
|
295
|
+
expect(scopeCheck.passed).toBe(true);
|
|
296
|
+
});
|
|
297
|
+
});
|
|
@@ -189,6 +189,10 @@ function seedFailedSlackEvent(opts: {
|
|
|
189
189
|
externalChatId: string;
|
|
190
190
|
channelTs: string;
|
|
191
191
|
requesterIdentifier?: string;
|
|
192
|
+
/** Stands in for the `slackInbound` the live path captures onto the payload. */
|
|
193
|
+
slackInbound?: Record<string, unknown>;
|
|
194
|
+
/** Extra `sourceMetadata` fields, as the gateway forwards them. */
|
|
195
|
+
sourceMetadata?: Record<string, unknown>;
|
|
192
196
|
}): string {
|
|
193
197
|
const inbound = deliveryCrud.recordInbound(
|
|
194
198
|
"slack",
|
|
@@ -203,7 +207,11 @@ function seedFailedSlackEvent(opts: {
|
|
|
203
207
|
externalMessageId: opts.channelTs,
|
|
204
208
|
// `sourceMetadata.messageId` is the Slack `ts`; the live path derives the
|
|
205
209
|
// idempotency key's `channelTs` from it (falling back to externalMessageId).
|
|
206
|
-
sourceMetadata: {
|
|
210
|
+
sourceMetadata: {
|
|
211
|
+
messageId: opts.channelTs,
|
|
212
|
+
...(opts.sourceMetadata ?? {}),
|
|
213
|
+
},
|
|
214
|
+
...(opts.slackInbound ? { slackInbound: opts.slackInbound } : {}),
|
|
207
215
|
trustCtx: {
|
|
208
216
|
trustClass: opts.trustClass,
|
|
209
217
|
sourceChannel: "slack",
|
|
@@ -434,6 +442,85 @@ describe("channel-retry-sweep", () => {
|
|
|
434
442
|
expect(capturedOptions?.slackInbound?.channelTs).toBe("1700000000.000200");
|
|
435
443
|
});
|
|
436
444
|
|
|
445
|
+
test("replays the sender's Slack app context from the captured slackInbound", async () => {
|
|
446
|
+
seedFailedSlackEvent({
|
|
447
|
+
trustClass: "guardian",
|
|
448
|
+
content: "summarize this",
|
|
449
|
+
externalChatId: "D7654321",
|
|
450
|
+
channelTs: "1700000000.000300",
|
|
451
|
+
slackInbound: {
|
|
452
|
+
channelId: "D7654321",
|
|
453
|
+
channelTs: "1700000000.000300",
|
|
454
|
+
appContext: {
|
|
455
|
+
entities: [{ type: "slack#/types/channel_id", value: "C0123ABC" }],
|
|
456
|
+
},
|
|
457
|
+
},
|
|
458
|
+
});
|
|
459
|
+
|
|
460
|
+
let capturedContent: string | undefined;
|
|
461
|
+
let capturedOptions: { displayContent?: string } | undefined;
|
|
462
|
+
await sweepFailedEvents(async (conversationId, content, options) => {
|
|
463
|
+
capturedContent = content;
|
|
464
|
+
capturedOptions = options as { displayContent?: string };
|
|
465
|
+
const messageId = "message-app-context-slack";
|
|
466
|
+
getDb()
|
|
467
|
+
.insert(messages)
|
|
468
|
+
.values({
|
|
469
|
+
id: messageId,
|
|
470
|
+
conversationId,
|
|
471
|
+
role: "user",
|
|
472
|
+
content: JSON.stringify([{ type: "text", text: content }]),
|
|
473
|
+
createdAt: Date.now(),
|
|
474
|
+
})
|
|
475
|
+
.run();
|
|
476
|
+
return { messageId };
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
// Without this the replayed turn loses the context that made "summarize
|
|
480
|
+
// this" resolvable — the model would see a bare deictic reference.
|
|
481
|
+
expect(capturedContent).toContain("channel: C0123ABC");
|
|
482
|
+
expect(capturedContent).toContain("summarize this");
|
|
483
|
+
expect(capturedOptions?.displayContent).toBe("summarize this");
|
|
484
|
+
});
|
|
485
|
+
|
|
486
|
+
test("recovers app context from sourceMetadata when the capture never ran", async () => {
|
|
487
|
+
// `storePayload` runs at the top of the handler; `storeInboundSlackMetadata`
|
|
488
|
+
// runs on dispatch, after the awaited Slack backfills. A crash in between
|
|
489
|
+
// leaves an orphan with full sourceMetadata and no slackInbound, which
|
|
490
|
+
// recovery promotes onto the sweep — the fallback has to rebuild the
|
|
491
|
+
// turn-shaping fields or the replayed turn is impoverished.
|
|
492
|
+
seedFailedSlackEvent({
|
|
493
|
+
trustClass: "guardian",
|
|
494
|
+
content: "summarize this",
|
|
495
|
+
externalChatId: "D7654322",
|
|
496
|
+
channelTs: "1700000000.000400",
|
|
497
|
+
sourceMetadata: {
|
|
498
|
+
appContext: {
|
|
499
|
+
entities: [{ type: "slack#/types/channel_id", value: "C0456DEF" }],
|
|
500
|
+
},
|
|
501
|
+
},
|
|
502
|
+
});
|
|
503
|
+
|
|
504
|
+
let capturedContent: string | undefined;
|
|
505
|
+
await sweepFailedEvents(async (conversationId, content) => {
|
|
506
|
+
capturedContent = content;
|
|
507
|
+
const messageId = "message-app-context-recovered";
|
|
508
|
+
getDb()
|
|
509
|
+
.insert(messages)
|
|
510
|
+
.values({
|
|
511
|
+
id: messageId,
|
|
512
|
+
conversationId,
|
|
513
|
+
role: "user",
|
|
514
|
+
content: JSON.stringify([{ type: "text", text: content }]),
|
|
515
|
+
createdAt: Date.now(),
|
|
516
|
+
})
|
|
517
|
+
.run();
|
|
518
|
+
return { messageId };
|
|
519
|
+
});
|
|
520
|
+
|
|
521
|
+
expect(capturedContent).toContain("channel: C0456DEF");
|
|
522
|
+
});
|
|
523
|
+
|
|
437
524
|
test("skips retry delivery when a dedup replay's sibling event already owns delivery", async () => {
|
|
438
525
|
const eventId = seedFailedSlackEvent({
|
|
439
526
|
trustClass: "guardian",
|
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import { describe, expect, test } from "bun:test";
|
|
12
12
|
|
|
13
13
|
import type { OpenPanelEvent } from "../api/events/open-panel.js";
|
|
14
|
+
import type { AssistantEvent } from "../api/index.js";
|
|
14
15
|
import {
|
|
15
16
|
createSurfaceMutex,
|
|
16
17
|
handleSurfaceAction,
|
|
@@ -18,10 +19,12 @@ import {
|
|
|
18
19
|
type SurfaceConversationContext,
|
|
19
20
|
surfaceProxyResolver,
|
|
20
21
|
} from "../daemon/conversation-surfaces.js";
|
|
21
|
-
import type {
|
|
22
|
+
import type {
|
|
23
|
+
SurfaceType,
|
|
24
|
+
} from "../daemon/message-protocol.js";
|
|
22
25
|
|
|
23
26
|
function makeContext(
|
|
24
|
-
sent:
|
|
27
|
+
sent: AssistantEvent[] = [],
|
|
25
28
|
overrides: Partial<SurfaceConversationContext> = {},
|
|
26
29
|
): SurfaceConversationContext {
|
|
27
30
|
return {
|
|
@@ -48,12 +51,12 @@ function makeContext(
|
|
|
48
51
|
};
|
|
49
52
|
}
|
|
50
53
|
|
|
51
|
-
function findOpenPanel(sent:
|
|
54
|
+
function findOpenPanel(sent: AssistantEvent[]): OpenPanelEvent | undefined {
|
|
52
55
|
return sent.find((msg): msg is OpenPanelEvent => msg.type === "open_panel");
|
|
53
56
|
}
|
|
54
57
|
|
|
55
58
|
async function waitForOpenPanel(
|
|
56
|
-
sent:
|
|
59
|
+
sent: AssistantEvent[],
|
|
57
60
|
): Promise<OpenPanelEvent> {
|
|
58
61
|
for (let i = 0; i < 20 && !findOpenPanel(sent); i++) {
|
|
59
62
|
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
@@ -65,7 +68,7 @@ async function waitForOpenPanel(
|
|
|
65
68
|
|
|
66
69
|
describe("ui_show channel_setup acknowledgment", () => {
|
|
67
70
|
test("emits open_panel with a surfaceId and succeeds once the client acks", async () => {
|
|
68
|
-
const sent:
|
|
71
|
+
const sent: AssistantEvent[] = [];
|
|
69
72
|
const ctx = makeContext(sent);
|
|
70
73
|
|
|
71
74
|
const resultPromise = surfaceProxyResolver(ctx, "ui_show", {
|
|
@@ -100,7 +103,7 @@ describe("ui_show channel_setup acknowledgment", () => {
|
|
|
100
103
|
});
|
|
101
104
|
|
|
102
105
|
test("returns a tool error when the client nacks", async () => {
|
|
103
|
-
const sent:
|
|
106
|
+
const sent: AssistantEvent[] = [];
|
|
104
107
|
const ctx = makeContext(sent);
|
|
105
108
|
|
|
106
109
|
const resultPromise = surfaceProxyResolver(ctx, "ui_show", {
|
|
@@ -120,7 +123,7 @@ describe("ui_show channel_setup acknowledgment", () => {
|
|
|
120
123
|
});
|
|
121
124
|
|
|
122
125
|
test("fails closed without emitting when no interactive client is connected", async () => {
|
|
123
|
-
const sent:
|
|
126
|
+
const sent: AssistantEvent[] = [];
|
|
124
127
|
const ctx = makeContext(sent, { hasNoClient: true });
|
|
125
128
|
|
|
126
129
|
const result = await surfaceProxyResolver(ctx, "ui_show", {
|
|
@@ -134,7 +137,7 @@ describe("ui_show channel_setup acknowledgment", () => {
|
|
|
134
137
|
});
|
|
135
138
|
|
|
136
139
|
test("times out into a tool error when no client acknowledges", async () => {
|
|
137
|
-
const sent:
|
|
140
|
+
const sent: AssistantEvent[] = [];
|
|
138
141
|
const ctx = makeContext(sent);
|
|
139
142
|
|
|
140
143
|
const ack = await openChannelSetupPanel(
|
|
@@ -155,7 +158,7 @@ describe("ui_show channel_setup acknowledgment", () => {
|
|
|
155
158
|
});
|
|
156
159
|
|
|
157
160
|
test("resolves cancelled when the turn is aborted mid-wait", async () => {
|
|
158
|
-
const sent:
|
|
161
|
+
const sent: AssistantEvent[] = [];
|
|
159
162
|
const ctx = makeContext(sent);
|
|
160
163
|
const controller = new AbortController();
|
|
161
164
|
|
|
@@ -73,22 +73,19 @@ mock.module("../plugins/defaults/memory/memory-recall-log-store.js", () => ({
|
|
|
73
73
|
backfillMemoryRecallLogMessageId: () => {},
|
|
74
74
|
}));
|
|
75
75
|
|
|
76
|
-
mock.module(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
backfillMemoryV2ActivationMessageId: () => {},
|
|
80
|
-
}),
|
|
81
|
-
);
|
|
76
|
+
mock.module("../plugins/defaults/memory/v2/activation-log-store.js", () => ({
|
|
77
|
+
backfillMemoryV2ActivationMessageId: () => {},
|
|
78
|
+
}));
|
|
82
79
|
|
|
83
80
|
// ── Imports (after mocks) ────────────────────────────────────────────────
|
|
84
81
|
|
|
85
82
|
import type { AgentEvent } from "../agent/loop.js";
|
|
83
|
+
import type { AssistantEvent } from "../api/index.js";
|
|
86
84
|
import type { EventHandlerDeps } from "../daemon/conversation-agent-loop-handlers.js";
|
|
87
85
|
import {
|
|
88
86
|
createEventHandlerState,
|
|
89
87
|
dispatchAgentEvent,
|
|
90
88
|
} from "../daemon/conversation-agent-loop-handlers.js";
|
|
91
|
-
import type { ServerMessage } from "../daemon/message-protocol.js";
|
|
92
89
|
import { _resetStreamStateForTesting } from "../runtime/assistant-stream-state.js";
|
|
93
90
|
import {
|
|
94
91
|
recordForChatMint,
|
|
@@ -107,16 +104,16 @@ import {
|
|
|
107
104
|
SYNTHETIC_OPENAI_PROJECT_KEY,
|
|
108
105
|
} from "./secret-fixtures.js";
|
|
109
106
|
|
|
110
|
-
function toolResults(events:
|
|
107
|
+
function toolResults(events: AssistantEvent[]): string[] {
|
|
111
108
|
return events
|
|
112
109
|
.filter(
|
|
113
|
-
(e): e is Extract<
|
|
110
|
+
(e): e is Extract<AssistantEvent, { type: "tool_result" }> =>
|
|
114
111
|
(e as { type?: string }).type === "tool_result",
|
|
115
112
|
)
|
|
116
113
|
.map((e) => (typeof e.result === "string" ? e.result : ""));
|
|
117
114
|
}
|
|
118
115
|
|
|
119
|
-
function createMockDeps(collected:
|
|
116
|
+
function createMockDeps(collected: AssistantEvent[]): EventHandlerDeps {
|
|
120
117
|
return {
|
|
121
118
|
ctx: {
|
|
122
119
|
conversationId: "test-conversation",
|
|
@@ -126,7 +123,7 @@ function createMockDeps(collected: ServerMessage[]): EventHandlerDeps {
|
|
|
126
123
|
markWorkspaceTopLevelDirty: () => {},
|
|
127
124
|
currentTurnSurfaces: [],
|
|
128
125
|
} as unknown as EventHandlerDeps["ctx"],
|
|
129
|
-
onEvent: (msg:
|
|
126
|
+
onEvent: (msg: AssistantEvent) => {
|
|
130
127
|
collected.push(msg);
|
|
131
128
|
},
|
|
132
129
|
reqId: "test-req-id",
|
|
@@ -146,10 +143,10 @@ function createMockDeps(collected: ServerMessage[]): EventHandlerDeps {
|
|
|
146
143
|
} as EventHandlerDeps;
|
|
147
144
|
}
|
|
148
145
|
|
|
149
|
-
function streamedText(events:
|
|
146
|
+
function streamedText(events: AssistantEvent[]): string {
|
|
150
147
|
return events
|
|
151
148
|
.filter(
|
|
152
|
-
(e): e is Extract<
|
|
149
|
+
(e): e is Extract<AssistantEvent, { type: "assistant_text_delta" }> =>
|
|
153
150
|
(e as { type?: string }).type === "assistant_text_delta",
|
|
154
151
|
)
|
|
155
152
|
.map((e) => e.text)
|
|
@@ -182,7 +179,7 @@ beforeEach(() => {
|
|
|
182
179
|
|
|
183
180
|
describe("live reveal guard priming barrier", () => {
|
|
184
181
|
test("a text delta dispatched while priming is pending waits for the guard and emits the sentinel", async () => {
|
|
185
|
-
const events:
|
|
182
|
+
const events: AssistantEvent[] = [];
|
|
186
183
|
const state = createEventHandlerState();
|
|
187
184
|
const deps = createMockDeps(events);
|
|
188
185
|
|
|
@@ -223,7 +220,7 @@ describe("live reveal guard priming barrier", () => {
|
|
|
223
220
|
});
|
|
224
221
|
|
|
225
222
|
test("a plaintext echo cannot beat the guard onto the wire", async () => {
|
|
226
|
-
const events:
|
|
223
|
+
const events: AssistantEvent[] = [];
|
|
227
224
|
const state = createEventHandlerState();
|
|
228
225
|
const deps = createMockDeps(events);
|
|
229
226
|
|
|
@@ -250,7 +247,7 @@ describe("live reveal guard priming barrier", () => {
|
|
|
250
247
|
});
|
|
251
248
|
|
|
252
249
|
test("a denied or failed reveal never reads the store and stays unrevealable", async () => {
|
|
253
|
-
const events:
|
|
250
|
+
const events: AssistantEvent[] = [];
|
|
254
251
|
const state = createEventHandlerState();
|
|
255
252
|
const deps = createMockDeps(events);
|
|
256
253
|
|
|
@@ -308,7 +305,7 @@ describe("live reveal guard priming barrier", () => {
|
|
|
308
305
|
});
|
|
309
306
|
|
|
310
307
|
test("a proven reveal primes even when the enclosing command exits non-zero", async () => {
|
|
311
|
-
const events:
|
|
308
|
+
const events: AssistantEvent[] = [];
|
|
312
309
|
const state = createEventHandlerState();
|
|
313
310
|
const deps = createMockDeps(events);
|
|
314
311
|
|
|
@@ -340,7 +337,7 @@ describe("live reveal guard priming barrier", () => {
|
|
|
340
337
|
});
|
|
341
338
|
|
|
342
339
|
test("steady-state deltas with no priming in flight emit synchronously", async () => {
|
|
343
|
-
const events:
|
|
340
|
+
const events: AssistantEvent[] = [];
|
|
344
341
|
const state = createEventHandlerState();
|
|
345
342
|
const deps = createMockDeps(events);
|
|
346
343
|
|
|
@@ -354,7 +351,7 @@ describe("live reveal guard priming barrier", () => {
|
|
|
354
351
|
});
|
|
355
352
|
|
|
356
353
|
test("a rotate-and-re-reveal in one window guards both served values", async () => {
|
|
357
|
-
const events:
|
|
354
|
+
const events: AssistantEvent[] = [];
|
|
358
355
|
const state = createEventHandlerState();
|
|
359
356
|
const deps = createMockDeps(events);
|
|
360
357
|
|
|
@@ -395,7 +392,7 @@ describe("live reveal guard priming barrier", () => {
|
|
|
395
392
|
|
|
396
393
|
describe("reveal stdout redaction on the live tool_result", () => {
|
|
397
394
|
test("an opaque revealed value in the reveal's own stdout is redacted before emit", async () => {
|
|
398
|
-
const events:
|
|
395
|
+
const events: AssistantEvent[] = [];
|
|
399
396
|
const state = createEventHandlerState();
|
|
400
397
|
const deps = createMockDeps(events);
|
|
401
398
|
|
|
@@ -424,7 +421,7 @@ describe("reveal stdout redaction on the live tool_result", () => {
|
|
|
424
421
|
});
|
|
425
422
|
|
|
426
423
|
test("buffers the RAW tool result so persist redacts exactly once", async () => {
|
|
427
|
-
const events:
|
|
424
|
+
const events: AssistantEvent[] = [];
|
|
428
425
|
const state = createEventHandlerState();
|
|
429
426
|
const deps = createMockDeps(events);
|
|
430
427
|
|
|
@@ -454,7 +451,7 @@ describe("reveal stdout redaction on the live tool_result", () => {
|
|
|
454
451
|
});
|
|
455
452
|
|
|
456
453
|
test("a tool_result that never revealed anything is forwarded unchanged", async () => {
|
|
457
|
-
const events:
|
|
454
|
+
const events: AssistantEvent[] = [];
|
|
458
455
|
const state = createEventHandlerState();
|
|
459
456
|
const deps = createMockDeps(events);
|
|
460
457
|
|
|
@@ -478,10 +475,10 @@ describe("reveal stdout redaction on the live tool_result", () => {
|
|
|
478
475
|
});
|
|
479
476
|
});
|
|
480
477
|
|
|
481
|
-
function outputChunks(events:
|
|
478
|
+
function outputChunks(events: AssistantEvent[]): string[] {
|
|
482
479
|
return events
|
|
483
480
|
.filter(
|
|
484
|
-
(e): e is Extract<
|
|
481
|
+
(e): e is Extract<AssistantEvent, { type: "tool_output_chunk" }> =>
|
|
485
482
|
(e as { type?: string }).type === "tool_output_chunk",
|
|
486
483
|
)
|
|
487
484
|
.map((e) => e.chunk);
|
|
@@ -489,7 +486,7 @@ function outputChunks(events: ServerMessage[]): string[] {
|
|
|
489
486
|
|
|
490
487
|
describe("live tool output chunk redaction", () => {
|
|
491
488
|
test("reveal stdout chunks are redacted before forwarding", async () => {
|
|
492
|
-
const events:
|
|
489
|
+
const events: AssistantEvent[] = [];
|
|
493
490
|
const state = createEventHandlerState();
|
|
494
491
|
const deps = createMockDeps(events);
|
|
495
492
|
|
|
@@ -517,7 +514,7 @@ describe("live tool output chunk redaction", () => {
|
|
|
517
514
|
});
|
|
518
515
|
|
|
519
516
|
test("a value split across chunks is held back, then flushed redacted", async () => {
|
|
520
|
-
const events:
|
|
517
|
+
const events: AssistantEvent[] = [];
|
|
521
518
|
const state = createEventHandlerState();
|
|
522
519
|
const deps = createMockDeps(events);
|
|
523
520
|
|
|
@@ -549,7 +546,7 @@ describe("live tool output chunk redaction", () => {
|
|
|
549
546
|
});
|
|
550
547
|
|
|
551
548
|
test("a held remainder is DISCARDED at tool_result, never emitted raw", async () => {
|
|
552
|
-
const events:
|
|
549
|
+
const events: AssistantEvent[] = [];
|
|
553
550
|
const state = createEventHandlerState();
|
|
554
551
|
const deps = createMockDeps(events);
|
|
555
552
|
|
|
@@ -587,7 +584,7 @@ describe("live tool output chunk redaction", () => {
|
|
|
587
584
|
});
|
|
588
585
|
|
|
589
586
|
test("chunks from a tool with no reveal candidates pass through verbatim", async () => {
|
|
590
|
-
const events:
|
|
587
|
+
const events: AssistantEvent[] = [];
|
|
591
588
|
const state = createEventHandlerState();
|
|
592
589
|
const deps = createMockDeps(events);
|
|
593
590
|
|
|
@@ -608,7 +605,7 @@ describe("live tool output chunk redaction", () => {
|
|
|
608
605
|
});
|
|
609
606
|
|
|
610
607
|
test("a later tool echoing an already-promoted value is redacted too", async () => {
|
|
611
|
-
const events:
|
|
608
|
+
const events: AssistantEvent[] = [];
|
|
612
609
|
const state = createEventHandlerState();
|
|
613
610
|
const deps = createMockDeps(events);
|
|
614
611
|
|
|
@@ -662,7 +659,7 @@ describe("for-chat re-mint authority (two legs: staged AND executed)", () => {
|
|
|
662
659
|
} as Extract<AgentEvent, { type: "tool_result" }>;
|
|
663
660
|
|
|
664
661
|
test("staged by this run + route-minted: the echoed sentinel re-mints on the live wire", async () => {
|
|
665
|
-
const events:
|
|
662
|
+
const events: AssistantEvent[] = [];
|
|
666
663
|
const state = createEventHandlerState();
|
|
667
664
|
const deps = createMockDeps(events);
|
|
668
665
|
|
|
@@ -694,7 +691,7 @@ describe("for-chat re-mint authority (two legs: staged AND executed)", () => {
|
|
|
694
691
|
// same identity. That mint passes the watermark and staging checks but
|
|
695
692
|
// carries the OTHER conversation's nonce, so it grants nothing here
|
|
696
693
|
// and the echoed sentinel neutralizes like any forgery.
|
|
697
|
-
const events:
|
|
694
|
+
const events: AssistantEvent[] = [];
|
|
698
695
|
const state = createEventHandlerState();
|
|
699
696
|
const deps = createMockDeps(events);
|
|
700
697
|
|
|
@@ -721,7 +718,7 @@ describe("for-chat re-mint authority (two legs: staged AND executed)", () => {
|
|
|
721
718
|
// other conversation's mint lands later. This run's own mint must
|
|
722
719
|
// still re-mint its echoed sentinel — an identity-only dedupe in the
|
|
723
720
|
// registry would have dropped it in favor of the foreign-nonce record.
|
|
724
|
-
const events:
|
|
721
|
+
const events: AssistantEvent[] = [];
|
|
725
722
|
const state = createEventHandlerState();
|
|
726
723
|
const deps = createMockDeps(events);
|
|
727
724
|
|
|
@@ -750,7 +747,7 @@ describe("for-chat re-mint authority (two legs: staged AND executed)", () => {
|
|
|
750
747
|
});
|
|
751
748
|
|
|
752
749
|
test("a mint alone — identity never staged by this run — neutralizes", async () => {
|
|
753
|
-
const events:
|
|
750
|
+
const events: AssistantEvent[] = [];
|
|
754
751
|
const state = createEventHandlerState();
|
|
755
752
|
const deps = createMockDeps(events);
|
|
756
753
|
|
|
@@ -771,7 +768,7 @@ describe("for-chat re-mint authority (two legs: staged AND executed)", () => {
|
|
|
771
768
|
});
|
|
772
769
|
|
|
773
770
|
test("staging alone — a quoted command that never executed — neutralizes", async () => {
|
|
774
|
-
const events:
|
|
771
|
+
const events: AssistantEvent[] = [];
|
|
775
772
|
const state = createEventHandlerState();
|
|
776
773
|
const deps = createMockDeps(events);
|
|
777
774
|
|
|
@@ -41,7 +41,7 @@ mock.module("../ipc/cli-client.js", () => ({
|
|
|
41
41
|
}));
|
|
42
42
|
|
|
43
43
|
let seedCallCount = 0;
|
|
44
|
-
mock.module("../plugins/defaults/memory/
|
|
44
|
+
mock.module("../plugins/defaults/memory/substrate/skill-store.js", () => ({
|
|
45
45
|
seedV2SkillEntries: async () => {
|
|
46
46
|
seedCallCount += 1;
|
|
47
47
|
},
|
|
@@ -88,7 +88,7 @@ async function runCommand(args: string[]): Promise<{ exitCode: number }> {
|
|
|
88
88
|
const program = buildProgram();
|
|
89
89
|
await program.parseAsync(["node", "assistant", ...args]);
|
|
90
90
|
} catch {
|
|
91
|
-
if (process.exitCode === 0) process.exitCode = 1;
|
|
91
|
+
if (process.exitCode === 0) {process.exitCode = 1;}
|
|
92
92
|
} finally {
|
|
93
93
|
process.stdout.write = originalStdoutWrite;
|
|
94
94
|
process.stderr.write = originalStderrWrite;
|