@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
|
@@ -9,8 +9,8 @@ import { basename } from "node:path";
|
|
|
9
9
|
import { eq, inArray } from "drizzle-orm";
|
|
10
10
|
|
|
11
11
|
import type { AcpSessionUpdateEvent } from "../api/events/acp-session-update.js";
|
|
12
|
+
import type { AssistantEvent } from "../api/index.js";
|
|
12
13
|
import { findConversation } from "../daemon/conversation-registry.js";
|
|
13
|
-
import type { ServerMessage } from "../daemon/message-protocol.js";
|
|
14
14
|
import { getDb } from "../persistence/db-connection.js";
|
|
15
15
|
import { acpSessionHistory } from "../persistence/schema/index.js";
|
|
16
16
|
import * as pendingInteractions from "../runtime/pending-interactions.js";
|
|
@@ -69,7 +69,7 @@ interface SessionEntry {
|
|
|
69
69
|
state: AcpSessionState;
|
|
70
70
|
clientHandler: VellumAcpClientHandler;
|
|
71
71
|
/** Wrapped sender that also appends to the ring buffer. */
|
|
72
|
-
sendToVellum: (msg:
|
|
72
|
+
sendToVellum: (msg: AssistantEvent) => void;
|
|
73
73
|
currentPrompt: Promise<unknown> | null;
|
|
74
74
|
parentConversationId: string;
|
|
75
75
|
cwd: string;
|
|
@@ -195,7 +195,7 @@ export class AcpSessionManager {
|
|
|
195
195
|
task: string,
|
|
196
196
|
cwd: string,
|
|
197
197
|
parentConversationId: string,
|
|
198
|
-
sendToVellum: (msg:
|
|
198
|
+
sendToVellum: (msg: AssistantEvent) => void,
|
|
199
199
|
parentToolUseId?: string,
|
|
200
200
|
): Promise<{ acpSessionId: string; protocolSessionId: string }> {
|
|
201
201
|
this.assertCapacity();
|
|
@@ -275,7 +275,7 @@ export class AcpSessionManager {
|
|
|
275
275
|
parentConversationId: string;
|
|
276
276
|
cwd: string;
|
|
277
277
|
startedAt: number;
|
|
278
|
-
sendToVellum: (msg:
|
|
278
|
+
sendToVellum: (msg: AssistantEvent) => void;
|
|
279
279
|
parentToolUseId?: string;
|
|
280
280
|
task?: string;
|
|
281
281
|
}): SessionEntry {
|
|
@@ -287,7 +287,7 @@ export class AcpSessionManager {
|
|
|
287
287
|
// Wrap the sender so every emitted message is mirrored into the buffer
|
|
288
288
|
// when it's an `acp_session_update`. The wrapper preserves the original
|
|
289
289
|
// call semantics: it forwards every message unchanged.
|
|
290
|
-
const wrappedSend = (msg:
|
|
290
|
+
const wrappedSend = (msg: AssistantEvent) => {
|
|
291
291
|
if (msg.type === "acp_session_update") {
|
|
292
292
|
this.appendToBuffer(acpSessionId, msg);
|
|
293
293
|
} else if (msg.type === "acp_session_usage") {
|
|
@@ -383,7 +383,7 @@ export class AcpSessionManager {
|
|
|
383
383
|
*/
|
|
384
384
|
async resumeFromHistory(
|
|
385
385
|
acpSessionId: string,
|
|
386
|
-
sendToVellum: (msg:
|
|
386
|
+
sendToVellum: (msg: AssistantEvent) => void,
|
|
387
387
|
): Promise<void> {
|
|
388
388
|
if (
|
|
389
389
|
this.sessions.has(acpSessionId) ||
|
|
@@ -448,7 +448,7 @@ export class AcpSessionManager {
|
|
|
448
448
|
private async performResume(
|
|
449
449
|
acpSessionId: string,
|
|
450
450
|
row: ResumableHistoryRow,
|
|
451
|
-
sendToVellum: (msg:
|
|
451
|
+
sendToVellum: (msg: AssistantEvent) => void,
|
|
452
452
|
): Promise<void> {
|
|
453
453
|
// Resolve the adapter, silently auto-installing a missing allowlisted
|
|
454
454
|
// binary via the same sandboxed `bun` path as spawn (see
|
|
@@ -658,7 +658,7 @@ export class AcpSessionManager {
|
|
|
658
658
|
async steerOrResume(
|
|
659
659
|
acpSessionId: string,
|
|
660
660
|
instruction: string,
|
|
661
|
-
sendToVellum: (msg:
|
|
661
|
+
sendToVellum: (msg: AssistantEvent) => void,
|
|
662
662
|
): Promise<{ resumed: boolean }> {
|
|
663
663
|
try {
|
|
664
664
|
await this.steer(acpSessionId, instruction);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `subagent_event` SSE event.
|
|
3
3
|
*
|
|
4
|
-
* Server → client envelope wrapping any inner `
|
|
4
|
+
* Server → client envelope wrapping any inner `AssistantEvent`
|
|
5
5
|
* emitted by a subagent's conversation. The daemon's subagent
|
|
6
6
|
* manager rebroadcasts the subagent's own stream through the
|
|
7
7
|
* parent conversation's `sendToClient`, tagged with the subagent's
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* to route inner events to the appropriate inline subagent surface.
|
|
10
10
|
*
|
|
11
11
|
* The inner `event` is opaque on the wire — it is itself a fully
|
|
12
|
-
* structured `
|
|
12
|
+
* structured `AssistantEvent` (any member of the canonical event
|
|
13
13
|
* union) and re-validating it here would duplicate work and
|
|
14
14
|
* tightly couple subagent canonicalization to every other event
|
|
15
15
|
* schema. Clients re-parse `event` through the same event parser
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Wire contract for the memory v2 activation log surfaced in the
|
|
3
3
|
* inspector's Memory tab. Mirrors the return value of
|
|
4
4
|
* `getMemoryV2ActivationLogByMessageIds` in
|
|
5
|
-
* `assistant/src/memory/
|
|
5
|
+
* `assistant/src/plugins/defaults/memory/v2/activation-log-store.ts`.
|
|
6
6
|
*
|
|
7
7
|
* Canonical wire-contract source. Assistant code imports the types
|
|
8
8
|
* directly from this file via relative paths; external consumers
|
|
@@ -20,7 +20,7 @@ import { z } from "zod";
|
|
|
20
20
|
/**
|
|
21
21
|
* One concept row in the V2 activation log. Mirrors
|
|
22
22
|
* `MemoryV2ConceptRowRecord` from
|
|
23
|
-
* `assistant/src/memory/
|
|
23
|
+
* `assistant/src/plugins/defaults/memory/v2/activation-log-store.ts`.
|
|
24
24
|
*
|
|
25
25
|
* `source` and `status` are open-ended strings on the wire — the
|
|
26
26
|
* daemon emits known values like `prior_state`, `ann_top50`, `both`
|
|
@@ -58,6 +58,19 @@ export const SubagentDetailResponseSchema = z.object({
|
|
|
58
58
|
status: SubagentStatusSchema.optional(),
|
|
59
59
|
usage: SubagentUsageStatsSchema.optional(),
|
|
60
60
|
events: z.array(SubagentDetailEventSchema),
|
|
61
|
+
/**
|
|
62
|
+
* The subagent's task label, from the live manager state. Lets a client
|
|
63
|
+
* that missed the `subagent_spawned` event (SSE gap, store reset, page
|
|
64
|
+
* reload mid-run) recover the display name it would otherwise only learn
|
|
65
|
+
* at spawn time.
|
|
66
|
+
*/
|
|
67
|
+
label: z.string().optional(),
|
|
68
|
+
/**
|
|
69
|
+
* Tool-use id of the spawning `subagent_spawn` call, from the live manager
|
|
70
|
+
* state. Lets a recovering client re-anchor the inline card to the exact
|
|
71
|
+
* spawn tool call (same role as the field on `subagent_spawned`).
|
|
72
|
+
*/
|
|
73
|
+
parentToolUseId: z.string().optional(),
|
|
61
74
|
});
|
|
62
75
|
|
|
63
76
|
export type SubagentDetailResponse = z.infer<
|
package/src/approvals/AGENTS.md
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# Approvals & Guardian Rules
|
|
2
2
|
|
|
3
|
+
The end-to-end lifecycle of interactive guardian requests (approvals, questions) — promotion, notification cards, reply routing, resolution — is mapped in [docs/guardian-request-flow.md](../../docs/guardian-request-flow.md). Read it before extending any decision or card-delivery path.
|
|
4
|
+
|
|
3
5
|
## Approval Flow Resilience
|
|
4
6
|
|
|
5
7
|
- **Rich delivery failures must degrade gracefully.** If delivering a rich approval prompt (e.g., Telegram inline buttons) fails, fall back to plain text with instructions (e.g., `Reply "yes" to approve`) — never auto-deny.
|
|
@@ -26,6 +26,7 @@ import { getGuardianRequestOrNull } from "../channels/gateway-guardian-requests.
|
|
|
26
26
|
import { findContactChannel } from "../contacts/contact-store.js";
|
|
27
27
|
import { findConversation } from "../daemon/conversation-registry.js";
|
|
28
28
|
import { emitNotificationSignal } from "../notifications/emit-signal.js";
|
|
29
|
+
import { parseQuestionAnswerActionId } from "../notifications/guardian-question-mode.js";
|
|
29
30
|
import {
|
|
30
31
|
isNotificationSourceChannel,
|
|
31
32
|
type NotificationSourceChannel,
|
|
@@ -34,6 +35,7 @@ import type {
|
|
|
34
35
|
TrustedContactDecisionPayload,
|
|
35
36
|
TrustedContactVerificationSentPayload,
|
|
36
37
|
} from "../notifications/trusted-contact-payloads.js";
|
|
38
|
+
import type { QuestionBatchSubmission } from "../permissions/question-prompter.js";
|
|
37
39
|
import type { UserDecision } from "../permissions/types.js";
|
|
38
40
|
import { DAEMON_INTERNAL_ASSISTANT_ID } from "../runtime/assistant-scope.js";
|
|
39
41
|
import {
|
|
@@ -48,6 +50,10 @@ import {
|
|
|
48
50
|
resolveTrustBinding,
|
|
49
51
|
} from "../runtime/introduction-policy.js";
|
|
50
52
|
import * as pendingInteractions from "../runtime/pending-interactions.js";
|
|
53
|
+
import {
|
|
54
|
+
readBatchMetadata,
|
|
55
|
+
resolvePendingQuestion,
|
|
56
|
+
} from "../runtime/question-resolution.js";
|
|
51
57
|
import { TC_GRANT_WAIT_MAX_MS } from "../tools/tool-approval-handler.js";
|
|
52
58
|
import { getLogger } from "../util/logger.js";
|
|
53
59
|
import { resolveDeliverCallbackUrlForChannel } from "./guardian-channel-delivery.js";
|
|
@@ -409,11 +415,16 @@ const pendingInteractionResolver: GuardianRequestResolver = {
|
|
|
409
415
|
};
|
|
410
416
|
|
|
411
417
|
/**
|
|
412
|
-
* Resolves `pending_question` requests
|
|
418
|
+
* Resolves `pending_question` requests. Two variants share the kind,
|
|
419
|
+
* distinguished by provenance fields:
|
|
420
|
+
*
|
|
421
|
+
* - Voice-call questions carry a `callSessionId` (+ `pendingQuestionId`);
|
|
422
|
+
* the answer is delivered to the live call session via `answerCall`.
|
|
423
|
+
* - `ask_question` prompts carry neither — the request id IS the pending
|
|
424
|
+
* `question` interaction's requestId (mirroring `tool_approval` rows), and
|
|
425
|
+
* the answer resolves that interaction so the parked tool call returns.
|
|
413
426
|
*
|
|
414
|
-
*
|
|
415
|
-
* are present and delivers the answer to the live call session. An
|
|
416
|
-
* `answerCall` failure surfaces as `resolverFailed` — the committed decision
|
|
427
|
+
* Side-effect failures surface as `resolverFailed` — the committed decision
|
|
417
428
|
* stands (no reopen).
|
|
418
429
|
*/
|
|
419
430
|
const pendingQuestionResolver: GuardianRequestResolver = {
|
|
@@ -423,10 +434,7 @@ const pendingQuestionResolver: GuardianRequestResolver = {
|
|
|
423
434
|
const { request, decision, actor: _actor } = ctx;
|
|
424
435
|
|
|
425
436
|
if (!request.callSessionId) {
|
|
426
|
-
return
|
|
427
|
-
ok: false,
|
|
428
|
-
reason: "pending_question request missing callSessionId",
|
|
429
|
-
};
|
|
437
|
+
return resolveAskQuestionInteraction(request, decision);
|
|
430
438
|
}
|
|
431
439
|
|
|
432
440
|
if (!request.pendingQuestionId) {
|
|
@@ -487,6 +495,100 @@ const pendingQuestionResolver: GuardianRequestResolver = {
|
|
|
487
495
|
},
|
|
488
496
|
};
|
|
489
497
|
|
|
498
|
+
/**
|
|
499
|
+
* Resolve an `ask_question` pending interaction from a guardian decision.
|
|
500
|
+
*
|
|
501
|
+
* The decision's `userText` carries either an answer-option token
|
|
502
|
+
* (`answer_<idx>` / `answer_skip`, from a tapped card button — see
|
|
503
|
+
* {@link parseQuestionAnswerActionId}) or the guardian's free-typed answer.
|
|
504
|
+
* A reject decision with no text is an explicit skip. Submission validation
|
|
505
|
+
* and the prompter hand-off go through the shared
|
|
506
|
+
* {@link resolvePendingQuestion}, the same core `/v1/question-response` uses,
|
|
507
|
+
* so an app-card answer and a channel answer resolve identically.
|
|
508
|
+
*/
|
|
509
|
+
async function resolveAskQuestionInteraction(
|
|
510
|
+
request: GuardianRequestWire,
|
|
511
|
+
decision: ResolverDecision,
|
|
512
|
+
): Promise<ResolverResult> {
|
|
513
|
+
const interaction = pendingInteractions.get(request.id);
|
|
514
|
+
if (!interaction || interaction.kind !== "question") {
|
|
515
|
+
// The parked prompt is gone (answered elsewhere, timed out, or the daemon
|
|
516
|
+
// restarted). The committed decision stands; there is just nothing left to
|
|
517
|
+
// resume.
|
|
518
|
+
return { ok: false, reason: "no_pending_question_interaction" };
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
const { orderedIds, optionsById } = readBatchMetadata(interaction);
|
|
522
|
+
if (orderedIds.length !== 1) {
|
|
523
|
+
// Channel cards are only created for single-question batches (the
|
|
524
|
+
// promotion gate enforces it); a multi-question interaction cannot be
|
|
525
|
+
// answered by one decision.
|
|
526
|
+
return { ok: false, reason: "question_batch_not_single" };
|
|
527
|
+
}
|
|
528
|
+
const questionId = orderedIds[0]!;
|
|
529
|
+
|
|
530
|
+
let submission: QuestionBatchSubmission;
|
|
531
|
+
const answerSelection = decision.userText
|
|
532
|
+
? parseQuestionAnswerActionId(decision.userText.trim())
|
|
533
|
+
: null;
|
|
534
|
+
if (answerSelection?.kind === "skip") {
|
|
535
|
+
submission = { questionId, kind: "skip" };
|
|
536
|
+
} else if (answerSelection?.kind === "option") {
|
|
537
|
+
const optionId = (optionsById[questionId] ?? [])[answerSelection.index];
|
|
538
|
+
if (!optionId) {
|
|
539
|
+
return { ok: false, reason: "question_option_index_out_of_range" };
|
|
540
|
+
}
|
|
541
|
+
submission = { questionId, kind: "option", optionId };
|
|
542
|
+
} else if (decision.userText && decision.userText.trim().length > 0) {
|
|
543
|
+
submission = {
|
|
544
|
+
questionId,
|
|
545
|
+
kind: "free_text",
|
|
546
|
+
text: decision.userText.trim(),
|
|
547
|
+
};
|
|
548
|
+
} else if (DENYING_ACTION_SET.has(decision.action)) {
|
|
549
|
+
submission = { questionId, kind: "skip" };
|
|
550
|
+
} else {
|
|
551
|
+
// Bare approval with no text (e.g. "CODE approve") — affirm without
|
|
552
|
+
// inventing content; the model reads the affirmation in context.
|
|
553
|
+
submission = { questionId, kind: "free_text", text: "Yes" };
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
const outcome = resolvePendingQuestion(request.id, {
|
|
557
|
+
kind: "submit",
|
|
558
|
+
submissions: [submission],
|
|
559
|
+
});
|
|
560
|
+
if (outcome.status !== "resolved") {
|
|
561
|
+
log.warn(
|
|
562
|
+
{
|
|
563
|
+
event: "resolver_ask_question_not_resolved",
|
|
564
|
+
requestId: request.id,
|
|
565
|
+
outcome: outcome.status,
|
|
566
|
+
...(outcome.status === "invalid" ? { message: outcome.message } : {}),
|
|
567
|
+
},
|
|
568
|
+
"Ask-question resolver: pending interaction did not resolve",
|
|
569
|
+
);
|
|
570
|
+
return {
|
|
571
|
+
ok: false,
|
|
572
|
+
reason:
|
|
573
|
+
outcome.status === "invalid"
|
|
574
|
+
? "question_submission_invalid"
|
|
575
|
+
: "no_pending_question_interaction",
|
|
576
|
+
};
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
log.info(
|
|
580
|
+
{
|
|
581
|
+
event: "resolver_ask_question_applied",
|
|
582
|
+
requestId: request.id,
|
|
583
|
+
action: decision.action,
|
|
584
|
+
submissionKind: submission.kind,
|
|
585
|
+
conversationId: outcome.conversationId,
|
|
586
|
+
},
|
|
587
|
+
"Ask-question resolver: pending interaction resolved",
|
|
588
|
+
);
|
|
589
|
+
return { ok: true, applied: true };
|
|
590
|
+
}
|
|
591
|
+
|
|
490
592
|
/**
|
|
491
593
|
* The four introduction-card outcomes for an access request. The generic
|
|
492
594
|
* decision pair maps onto them: `approve_once` → `verify_code` (handshake),
|
|
@@ -658,9 +760,9 @@ async function deliverRequesterNotice(params: {
|
|
|
658
760
|
}
|
|
659
761
|
|
|
660
762
|
/**
|
|
661
|
-
* Emit the guardian-facing denial lifecycle
|
|
763
|
+
* Emit the guardian-facing denial lifecycle signal and, unless suppressed,
|
|
662
764
|
* deliver the "declined" notice to the requester. Both the `leave_unverified`
|
|
663
|
-
* and `block` outcomes call this for the lifecycle
|
|
765
|
+
* and `block` outcomes call this for the lifecycle signal, but the requester
|
|
664
766
|
* notice is delivered only for `block` (in denied mode) — `leave_unverified`
|
|
665
767
|
* always passes `suppressRequesterNotice: true`, staying a silent park at
|
|
666
768
|
* `unverified`. The notice text is a plain decline that does not reveal whether
|
|
@@ -712,6 +814,12 @@ async function notifyRequesterOfDenial(params: {
|
|
|
712
814
|
});
|
|
713
815
|
}
|
|
714
816
|
|
|
817
|
+
// Exactly one signal per denial: the payload's `decision: "denied"`
|
|
818
|
+
// carries the verdict, and the pipeline can only dedupe within a single
|
|
819
|
+
// event stream — a second event name would materialize a second
|
|
820
|
+
// conversation for the same decision. The approve path holds the same
|
|
821
|
+
// one-signal invariant via `verification_sent` standing in for
|
|
822
|
+
// `guardian_decision`.
|
|
715
823
|
if (channelDeliveryContext) {
|
|
716
824
|
void emitNotificationSignal({
|
|
717
825
|
sourceEventName: "ingress.trusted_contact.guardian_decision",
|
|
@@ -726,20 +834,6 @@ async function notifyRequesterOfDenial(params: {
|
|
|
726
834
|
contextPayload: deniedPayload,
|
|
727
835
|
dedupeKey: `trusted-contact:guardian-decision:${requestId}`,
|
|
728
836
|
});
|
|
729
|
-
|
|
730
|
-
void emitNotificationSignal({
|
|
731
|
-
sourceEventName: "ingress.trusted_contact.denied",
|
|
732
|
-
sourceChannel: channel,
|
|
733
|
-
sourceContextId: conversationId ?? "",
|
|
734
|
-
attentionHints: {
|
|
735
|
-
requiresAction: false,
|
|
736
|
-
urgency: "low",
|
|
737
|
-
isAsyncBackground: false,
|
|
738
|
-
visibleInSourceNow: false,
|
|
739
|
-
},
|
|
740
|
-
contextPayload: deniedPayload,
|
|
741
|
-
dedupeKey: `trusted-contact:denied:${requestId}`,
|
|
742
|
-
});
|
|
743
837
|
}
|
|
744
838
|
}
|
|
745
839
|
|
package/src/apps/app-store.ts
CHANGED
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
resolve,
|
|
35
35
|
} from "node:path";
|
|
36
36
|
|
|
37
|
+
import { resolveConversationLineage } from "../daemon/conversation-lineage.js";
|
|
37
38
|
import { rawAll } from "../persistence/raw-query.js";
|
|
38
39
|
import { isPluginDisabled } from "../plugins/disabled-state.js";
|
|
39
40
|
import type { EditEngineResult } from "../tools/shared/filesystem/edit-engine.js";
|
|
@@ -41,6 +42,8 @@ import { applyEdit } from "../tools/shared/filesystem/edit-engine.js";
|
|
|
41
42
|
import { getLogger } from "../util/logger.js";
|
|
42
43
|
import { getDataDir, getWorkspacePluginsDir } from "../util/platform.js";
|
|
43
44
|
|
|
45
|
+
const log = getLogger("app-store");
|
|
46
|
+
|
|
44
47
|
export interface AppDefinition {
|
|
45
48
|
id: string;
|
|
46
49
|
name: string;
|
|
@@ -60,6 +63,12 @@ export interface AppDefinition {
|
|
|
60
63
|
dirName?: string;
|
|
61
64
|
/** Conversation IDs that have interacted with this app (create/open/refresh). */
|
|
62
65
|
conversationIds?: string[];
|
|
66
|
+
/**
|
|
67
|
+
* The subset of {@link conversationIds} the app reached only by lineage —
|
|
68
|
+
* ancestors of the conversation that actually interacted with it. Absent
|
|
69
|
+
* means every association is direct.
|
|
70
|
+
*/
|
|
71
|
+
inheritedConversationIds?: string[];
|
|
63
72
|
}
|
|
64
73
|
|
|
65
74
|
/**
|
|
@@ -1218,12 +1227,17 @@ export function editAppFile(
|
|
|
1218
1227
|
* Associate a conversation with an app. Writes directly to the JSON metadata
|
|
1219
1228
|
* file without bumping `updatedAt` so the app list ordering is preserved.
|
|
1220
1229
|
*
|
|
1230
|
+
* `inherited` marks an association the app reached through a descendant's
|
|
1231
|
+
* lineage rather than through work done in the conversation itself. A direct
|
|
1232
|
+
* association supersedes an inherited one for the same conversation.
|
|
1233
|
+
*
|
|
1221
1234
|
* @returns `true` if the association was added, `false` if the app was not
|
|
1222
1235
|
* found or the conversationId was already present (dedup).
|
|
1223
1236
|
*/
|
|
1224
1237
|
export function addAppConversationId(
|
|
1225
1238
|
appId: string,
|
|
1226
1239
|
conversationId: string,
|
|
1240
|
+
options?: { inherited?: boolean },
|
|
1227
1241
|
): boolean {
|
|
1228
1242
|
const app = getApp(appId);
|
|
1229
1243
|
if (!app) return false;
|
|
@@ -1243,17 +1257,83 @@ export function addAppConversationId(
|
|
|
1243
1257
|
const onDiskIds = Array.isArray(parsed.conversationIds)
|
|
1244
1258
|
? (parsed.conversationIds as string[])
|
|
1245
1259
|
: [];
|
|
1260
|
+
// An absent list means the record holds only direct associations.
|
|
1261
|
+
const onDiskInherited = Array.isArray(parsed.inheritedConversationIds)
|
|
1262
|
+
? (parsed.inheritedConversationIds as string[])
|
|
1263
|
+
: [];
|
|
1264
|
+
const inherited = options?.inherited === true;
|
|
1246
1265
|
|
|
1247
|
-
if (onDiskIds.includes(conversationId))
|
|
1266
|
+
if (onDiskIds.includes(conversationId)) {
|
|
1267
|
+
if (inherited || !onDiskInherited.includes(conversationId)) {
|
|
1268
|
+
return false;
|
|
1269
|
+
}
|
|
1270
|
+
parsed.inheritedConversationIds = onDiskInherited.filter(
|
|
1271
|
+
(id) => id !== conversationId,
|
|
1272
|
+
);
|
|
1273
|
+
writeFileSync(jsonPath, JSON.stringify(parsed, null, 2));
|
|
1274
|
+
return false;
|
|
1275
|
+
}
|
|
1248
1276
|
|
|
1249
1277
|
parsed.conversationIds = [...onDiskIds, conversationId];
|
|
1278
|
+
if (inherited) {
|
|
1279
|
+
parsed.inheritedConversationIds = [...onDiskInherited, conversationId];
|
|
1280
|
+
}
|
|
1250
1281
|
writeFileSync(jsonPath, JSON.stringify(parsed, null, 2));
|
|
1251
1282
|
|
|
1252
1283
|
return true;
|
|
1253
1284
|
}
|
|
1254
1285
|
|
|
1255
1286
|
/**
|
|
1256
|
-
*
|
|
1287
|
+
* Associate an app with the conversation that produced it and every subagent
|
|
1288
|
+
* ancestor above it. A background subagent (e.g. the live-voice duplex
|
|
1289
|
+
* continuation) runs in a forked conversation the user never sees, so linking
|
|
1290
|
+
* only the fork leaves the app unopenable from the thread the user actually
|
|
1291
|
+
* has in front of them. Associations are additive and de-duplicated, so
|
|
1292
|
+
* linking the whole chain is safe.
|
|
1293
|
+
*
|
|
1294
|
+
* The seed conversation's association is direct; every ancestor's is
|
|
1295
|
+
* inherited, so an implicit "the app I am working on" lookup in an ancestor
|
|
1296
|
+
* thread is not captured by a background run's app.
|
|
1297
|
+
*
|
|
1298
|
+
* Best-effort per id: a link failure must never break app creation or opening.
|
|
1299
|
+
* Returns the number of associations added.
|
|
1300
|
+
*/
|
|
1301
|
+
export function linkAppToConversationLineage(
|
|
1302
|
+
appId: string,
|
|
1303
|
+
conversationId: string,
|
|
1304
|
+
): number {
|
|
1305
|
+
// Lineage resolution reaches the conversation store; an unexpected throw
|
|
1306
|
+
// there degrades to the conversation itself rather than breaking the link.
|
|
1307
|
+
let lineage: string[];
|
|
1308
|
+
try {
|
|
1309
|
+
lineage = resolveConversationLineage(conversationId);
|
|
1310
|
+
} catch (err) {
|
|
1311
|
+
log.warn(
|
|
1312
|
+
{ err, appId, conversationId },
|
|
1313
|
+
"Failed to resolve conversation lineage for app association",
|
|
1314
|
+
);
|
|
1315
|
+
lineage = [conversationId];
|
|
1316
|
+
}
|
|
1317
|
+
let associationsAdded = 0;
|
|
1318
|
+
for (const [index, id] of lineage.entries()) {
|
|
1319
|
+
try {
|
|
1320
|
+
if (addAppConversationId(appId, id, { inherited: index > 0 })) {
|
|
1321
|
+
associationsAdded += 1;
|
|
1322
|
+
}
|
|
1323
|
+
} catch (err) {
|
|
1324
|
+
log.warn(
|
|
1325
|
+
{ err, appId, conversationId: id },
|
|
1326
|
+
"Failed to associate app with conversation",
|
|
1327
|
+
);
|
|
1328
|
+
}
|
|
1329
|
+
}
|
|
1330
|
+
return associationsAdded;
|
|
1331
|
+
}
|
|
1332
|
+
|
|
1333
|
+
/**
|
|
1334
|
+
* Return all apps associated with a given conversation ID, whether the
|
|
1335
|
+
* association is direct or inherited from a descendant subagent run — a user
|
|
1336
|
+
* finds and opens a background run's app from the thread they can see.
|
|
1257
1337
|
*/
|
|
1258
1338
|
export function listAppsByConversation(
|
|
1259
1339
|
conversationId: string,
|
|
@@ -1263,6 +1343,19 @@ export function listAppsByConversation(
|
|
|
1263
1343
|
);
|
|
1264
1344
|
}
|
|
1265
1345
|
|
|
1346
|
+
/**
|
|
1347
|
+
* Whether an app's association with a conversation is direct — the app was
|
|
1348
|
+
* created or operated on in that conversation itself, rather than reaching it
|
|
1349
|
+
* through a descendant's lineage. A record carrying no
|
|
1350
|
+
* `inheritedConversationIds` holds only direct associations.
|
|
1351
|
+
*/
|
|
1352
|
+
export function isDirectAppConversation(
|
|
1353
|
+
app: AppDefinition,
|
|
1354
|
+
conversationId: string,
|
|
1355
|
+
): boolean {
|
|
1356
|
+
return app.inheritedConversationIds?.includes(conversationId) !== true;
|
|
1357
|
+
}
|
|
1358
|
+
|
|
1266
1359
|
// ---------------------------------------------------------------------------
|
|
1267
1360
|
// Backfill: scan message history for ui_surface blocks referencing apps
|
|
1268
1361
|
// ---------------------------------------------------------------------------
|
|
@@ -1280,8 +1373,6 @@ export function listAppsByConversation(
|
|
|
1280
1373
|
* Wrapped in try/catch so failures never block daemon start.
|
|
1281
1374
|
*/
|
|
1282
1375
|
export function backfillAppConversationIds(): void {
|
|
1283
|
-
const log = getLogger("app-store");
|
|
1284
|
-
|
|
1285
1376
|
// Check sentinel — skip the potentially expensive scan when already done.
|
|
1286
1377
|
const sentinelPath = join(getAppsDir(), ".conversation-ids-backfilled");
|
|
1287
1378
|
if (existsSync(sentinelPath)) {
|
|
@@ -4,6 +4,8 @@ import {
|
|
|
4
4
|
couldBeControlMarker,
|
|
5
5
|
ESCALATE_VERDICT_TOKEN,
|
|
6
6
|
HOLD_VERDICT_TOKEN,
|
|
7
|
+
isIncompleteControlMarkerTail,
|
|
8
|
+
MINIMIZE_ROOM_MARKER,
|
|
7
9
|
stripInternalSpeechMarkers,
|
|
8
10
|
} from "../voice-control-protocol.js";
|
|
9
11
|
|
|
@@ -46,3 +48,58 @@ describe("front-door verdict tokens", () => {
|
|
|
46
48
|
);
|
|
47
49
|
});
|
|
48
50
|
});
|
|
51
|
+
|
|
52
|
+
describe("minimize-room marker", () => {
|
|
53
|
+
test("marker constant is the expected bracketed form", () => {
|
|
54
|
+
expect(MINIMIZE_ROOM_MARKER).toBe("[-1]");
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
test("stripInternalSpeechMarkers removes the marker so it is never spoken", () => {
|
|
58
|
+
expect(
|
|
59
|
+
stripInternalSpeechMarkers("Done [-1] here").replace(/\s+/g, " "),
|
|
60
|
+
).toBe("Done here");
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test("couldBeControlMarker holds the marker and its streaming prefixes", () => {
|
|
64
|
+
for (const text of ["[", "[-", "[-1", "[-1]", "[-1] trailing"]) {
|
|
65
|
+
expect(couldBeControlMarker(text)).toBe(true);
|
|
66
|
+
}
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
test("a bracket prefix that disproves the marker is not held", () => {
|
|
70
|
+
expect(couldBeControlMarker("[- something else")).toBe(false);
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
describe("isIncompleteControlMarkerTail", () => {
|
|
75
|
+
test("strict prefixes of any marker are incomplete", () => {
|
|
76
|
+
for (const tail of ["[", "[-", "[-1", "[END_CAL", "[ASK_GUARDIAN_APPRO"]) {
|
|
77
|
+
expect(isIncompleteControlMarkerTail(tail)).toBe(true);
|
|
78
|
+
}
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
test("complete literal markers are not held", () => {
|
|
82
|
+
for (const tail of ["[-1]", "[END_CALL]", "[0] answer", "[-1] look here"]) {
|
|
83
|
+
expect(isIncompleteControlMarkerTail(tail)).toBe(false);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
test("guardian-approval is judged by the balanced parser, not the first bracket", () => {
|
|
88
|
+
const streaming =
|
|
89
|
+
'[ASK_GUARDIAN_APPROVAL: {"question": "ok]?", "options": ["a", "b"';
|
|
90
|
+
expect(isIncompleteControlMarkerTail(streaming)).toBe(true);
|
|
91
|
+
expect(isIncompleteControlMarkerTail(`${streaming}]}]`)).toBe(false);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
test("colon-style markers terminate at their first bracket", () => {
|
|
95
|
+
expect(isIncompleteControlMarkerTail("[ASK_GUARDIAN: may I")).toBe(true);
|
|
96
|
+
expect(isIncompleteControlMarkerTail("[ASK_GUARDIAN: may I?]")).toBe(false);
|
|
97
|
+
expect(isIncompleteControlMarkerTail("[USER_ANSWERED: yes")).toBe(true);
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
test("non-marker bracket text is not held", () => {
|
|
101
|
+
for (const tail of ["[- something else", "[sic]", '["a", "b"]']) {
|
|
102
|
+
expect(isIncompleteControlMarkerTail(tail)).toBe(false);
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
});
|