@vellumai/assistant 0.10.8 → 0.10.9-dev.202607152225.ec6fdbf
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 +4 -0
- package/ARCHITECTURE.md +52 -88
- package/README.md +14 -35
- package/docs/activation-funnel-telemetry.md +20 -18
- package/docs/architecture/scheduling.md +0 -86
- package/docs/runbook-trusted-contacts.md +19 -19
- package/docs/trusted-contact-access.md +70 -69
- package/docs/workspace-tools.md +4 -2
- package/eslint-rules/__tests__/cli-no-daemon-internals.test.ts +62 -360
- package/eslint-rules/cli-no-daemon-internals.js +91 -275
- package/eslint.config.mjs +4 -4
- 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__/redacted-credential.test.ts +200 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/redacted-credential.ts +226 -0
- 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__/redacted-credential.test.ts +200 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/redacted-credential.ts +226 -0
- package/node_modules/@vellumai/gateway-client/src/__tests__/guardian-request-contract.test.ts +575 -0
- package/node_modules/@vellumai/gateway-client/src/gateway-ipc-contracts.ts +20 -0
- package/node_modules/@vellumai/gateway-client/src/guardian-request-contract.ts +687 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +82 -0
- package/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/redacted-credential.test.ts +200 -0
- package/node_modules/@vellumai/service-contracts/src/redacted-credential.ts +226 -0
- package/openapi.yaml +353 -742
- package/package.json +2 -2
- package/scripts/build-test-fixtures.ts +3 -2
- package/scripts/test.ts +2 -7
- package/src/__tests__/activation-early-marking.test.ts +1 -8
- package/src/__tests__/actor-token-service.test.ts +0 -7
- package/src/__tests__/add-message-preassigned-id.test.ts +1 -1
- package/src/__tests__/add-message-skip-indexing.test.ts +164 -0
- package/src/__tests__/agent-image-optimize.test.ts +104 -1
- package/src/__tests__/agent-loop-callsite-precedence.test.ts +5 -15
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +0 -6
- package/src/__tests__/agent-loop-override-profile.test.ts +48 -50
- package/src/__tests__/agent-loop-pushes-post-hook-prompt.test.ts +4 -17
- package/src/__tests__/agent-loop-set-system-prompt.test.ts +3 -14
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +0 -4
- package/src/__tests__/agent-wake-override-profile.test.ts +40 -71
- package/src/__tests__/always-loaded-tools-guard.test.ts +4 -7
- package/src/__tests__/annotate-activity-metadata.test.ts +4 -31
- package/src/__tests__/annotate-risk-options.test.ts +4 -31
- package/src/__tests__/anthropic-provider.test.ts +11 -0
- package/src/__tests__/app-asset-bytes.test.ts +72 -0
- package/src/__tests__/app-builder-tool-scripts.test.ts +0 -1
- package/src/__tests__/app-bundler.test.ts +4 -20
- package/src/__tests__/app-conversation-ids-backfill.test.ts +1 -8
- package/src/__tests__/app-executors.test.ts +2 -49
- package/src/__tests__/app-routes-csp.test.ts +126 -157
- package/src/__tests__/approval-cascade.test.ts +0 -82
- package/src/__tests__/approval-interception-trust-gates.test.ts +0 -7
- package/src/__tests__/approval-primitive.test.ts +1 -9
- package/src/__tests__/approval-routes-http.test.ts +5 -63
- package/src/__tests__/assistant-event-hub-machine-name.test.ts +1 -19
- package/src/__tests__/assistant-events-sse-hardening.test.ts +4 -21
- package/src/__tests__/attachment-stored-path-annotation.test.ts +1 -19
- package/src/__tests__/attachment-upload-trusted-source.test.ts +0 -13
- package/src/__tests__/attachments-store-heic-normalize.test.ts +0 -13
- package/src/__tests__/attachments-store.test.ts +5 -19
- package/src/__tests__/audit-log-rotation.test.ts +1 -9
- package/src/__tests__/auth-fallback-events-store.test.ts +43 -59
- package/src/__tests__/available-skills.test.ts +7 -15
- package/src/__tests__/avatar-e2e.test.ts +0 -19
- package/src/__tests__/avatar-generator.test.ts +0 -9
- package/src/__tests__/background-shell-bash.test.ts +0 -20
- package/src/__tests__/background-shell-host-bash.test.ts +0 -34
- package/src/__tests__/background-workers-disk-pressure.test.ts +1 -43
- package/src/__tests__/browser-fill-credential.test.ts +0 -7
- package/src/__tests__/browser-manager.test.ts +1 -8
- package/src/__tests__/browser-skill-endstate.test.ts +1 -5
- package/src/__tests__/btw-routes.test.ts +7 -30
- package/src/__tests__/build-persisted-content.test.ts +96 -29
- package/src/__tests__/bundle-scanner.test.ts +27 -1
- package/src/__tests__/call-controller.test.ts +96 -149
- package/src/__tests__/call-conversation-messages.test.ts +2 -9
- package/src/__tests__/call-domain.test.ts +21 -56
- package/src/__tests__/call-pointer-message-composer.test.ts +0 -8
- package/src/__tests__/call-pointer-messages.test.ts +1 -8
- package/src/__tests__/call-recovery.test.ts +4 -11
- package/src/__tests__/call-routes-http.test.ts +12 -47
- package/src/__tests__/call-site-routing-provider.test.ts +5 -16
- package/src/__tests__/call-start-guardian-guard.test.ts +0 -10
- package/src/__tests__/call-state.test.ts +1 -8
- package/src/__tests__/call-store.test.ts +4 -11
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +0 -32
- package/src/__tests__/catalog-cache.test.ts +0 -8
- package/src/__tests__/catalog-files.test.ts +0 -8
- package/src/__tests__/catalog-install-normalize.test.ts +0 -7
- package/src/__tests__/ces-rpc-credential-backend.test.ts +0 -7
- package/src/__tests__/channel-approval-routes.test.ts +23 -34
- package/src/__tests__/channel-approvals.test.ts +0 -7
- package/src/__tests__/channel-delivery-store.test.ts +6 -17
- package/src/__tests__/channel-guardian.test.ts +0 -7
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +15 -20
- package/src/__tests__/channel-readiness-routes.test.ts +41 -67
- package/src/__tests__/channel-readiness-service.test.ts +13 -45
- package/src/__tests__/channel-readiness-slack-remote.test.ts +5 -22
- package/src/__tests__/channel-reply-delivery.test.ts +18 -5
- package/src/__tests__/channel-retry-sweep.test.ts +0 -7
- package/src/__tests__/chat-credential-redaction.test.ts +1395 -0
- package/src/__tests__/chat-reveal-guard-priming.test.ts +791 -0
- package/src/__tests__/checker.test.ts +0 -24
- package/src/__tests__/clawhub-files.test.ts +0 -8
- package/src/__tests__/clawhub.test.ts +0 -7
- package/src/__tests__/clear-all-lexical.test.ts +0 -6
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +3 -0
- package/src/__tests__/client-os-metadata-persistence.test.ts +0 -5
- package/src/__tests__/compaction-events.test.ts +26 -99
- package/src/__tests__/compaction-ledger-store.test.ts +1 -7
- package/src/__tests__/compaction-summary-head-persisted-count.test.ts +0 -27
- package/src/__tests__/compaction-trail-store.test.ts +1 -19
- package/src/__tests__/compaction.benchmark.test.ts +2 -6
- package/src/__tests__/compactor-call-site-logging.test.ts +0 -21
- package/src/__tests__/compactor-fixed-boundary.test.ts +0 -21
- package/src/__tests__/compactor-image-manifest-trust.test.ts +1 -10
- package/src/__tests__/compactor-low-watermark-cut.test.ts +0 -21
- package/src/__tests__/compactor-media-strip.test.ts +0 -21
- package/src/__tests__/compactor-preserved-tail-count.test.ts +0 -21
- package/src/__tests__/compactor-summary-call-truncation.test.ts +0 -21
- package/src/__tests__/compactor-web-search-strip.test.ts +0 -21
- package/src/__tests__/config-get-vision-flag.test.ts +24 -53
- package/src/__tests__/config-loader-backfill.test.ts +9 -25
- package/src/__tests__/config-loader-platform-defaults.test.ts +0 -21
- package/src/__tests__/config-schema-cmd.test.ts +10 -11
- package/src/__tests__/config-schema.test.ts +221 -275
- package/src/__tests__/config-set-route.test.ts +32 -62
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +44 -83
- package/src/__tests__/config-watcher-skill-reseed.test.ts +0 -16
- package/src/__tests__/config-watcher.test.ts +2 -17
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +57 -63
- package/src/__tests__/contact-store-interaction-info.test.ts +1 -8
- package/src/__tests__/contact-store-user-file.test.ts +1 -8
- package/src/__tests__/contacts-tools.test.ts +21 -26
- package/src/__tests__/contacts-write.test.ts +1 -8
- package/src/__tests__/context-search-memory-v2-source.test.ts +0 -6
- package/src/__tests__/context-window-manager-compact-retry.test.ts +0 -27
- package/src/__tests__/context-window-manager-overflow-rung.test.ts +0 -21
- package/src/__tests__/conversation-abort-tool-results.test.ts +9 -90
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +5 -41
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +16 -54
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +14 -79
- package/src/__tests__/conversation-agent-loop.test.ts +213 -136
- package/src/__tests__/conversation-app-control-instantiation.test.ts +10 -16
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +0 -43
- package/src/__tests__/conversation-attachments.test.ts +0 -17
- package/src/__tests__/conversation-attention-store.test.ts +1 -9
- package/src/__tests__/conversation-attention-telegram.test.ts +0 -8
- package/src/__tests__/conversation-clear-safety.test.ts +20 -20
- package/src/__tests__/conversation-confirmation-signals.test.ts +0 -82
- package/src/__tests__/conversation-crud-enabled-plugins.test.ts +1 -7
- package/src/__tests__/conversation-crud-inference-profile.test.ts +1 -7
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +0 -7
- package/src/__tests__/conversation-disk-view-integration.test.ts +1 -26
- package/src/__tests__/conversation-disk-view.test.ts +1 -26
- package/src/__tests__/conversation-enabledplugins-route.test.ts +3 -21
- package/src/__tests__/conversation-error.test.ts +21 -7
- package/src/__tests__/conversation-fork-crud.test.ts +35 -44
- package/src/__tests__/conversation-fork-retrospective.test.ts +9 -24
- package/src/__tests__/conversation-fork-route.test.ts +0 -32
- package/src/__tests__/conversation-history-web-search.test.ts +20 -17
- package/src/__tests__/conversation-inference-profile-list.test.ts +0 -17
- package/src/__tests__/conversation-inference-profile-route.test.ts +2 -24
- package/src/__tests__/conversation-init.benchmark.test.ts +3 -56
- package/src/__tests__/conversation-key-store-disk-view.test.ts +1 -33
- package/src/__tests__/conversation-lifecycle.test.ts +63 -103
- package/src/__tests__/conversation-list-source.test.ts +0 -18
- package/src/__tests__/conversation-load-history-repair.test.ts +39 -91
- package/src/__tests__/conversation-load-history-stripped.test.ts +12 -57
- package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +10 -20
- package/src/__tests__/conversation-message-id-uuidv7.test.ts +1 -18
- package/src/__tests__/conversation-pairing.test.ts +0 -7
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +0 -9
- package/src/__tests__/conversation-process-callsite.test.ts +15 -97
- package/src/__tests__/conversation-provider-retry-repair.test.ts +3 -84
- package/src/__tests__/conversation-queue.test.ts +12 -108
- package/src/__tests__/conversation-routes-disk-view.test.ts +8 -60
- package/src/__tests__/conversation-routes-enabled-plugins.test.ts +5 -63
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +13 -22
- package/src/__tests__/conversation-routes-hidden-queue.test.ts +5 -64
- package/src/__tests__/conversation-routes-slash-commands.test.ts +19 -87
- package/src/__tests__/conversation-runtime-assembly.test.ts +34 -37
- package/src/__tests__/conversation-seed-composer.test.ts +3 -3
- package/src/__tests__/conversation-skill-tools.test.ts +19 -32
- package/src/__tests__/conversation-slash-queue.test.ts +3 -90
- package/src/__tests__/conversation-slash-unknown.test.ts +0 -87
- package/src/__tests__/conversation-speed-override.test.ts +19 -94
- package/src/__tests__/conversation-starter-routes.test.ts +0 -7
- package/src/__tests__/conversation-store.test.ts +72 -66
- package/src/__tests__/conversation-summarize-route.test.ts +0 -11
- package/src/__tests__/conversation-summarize-up-to.test.ts +4 -89
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +131 -0
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +36 -36
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +4 -2
- package/src/__tests__/conversation-title-service.test.ts +0 -7
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +0 -1
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +37 -60
- package/src/__tests__/conversation-tool-setup-tools-disabled.test.ts +17 -17
- package/src/__tests__/conversation-unread-route.test.ts +0 -7
- package/src/__tests__/conversation-usage.test.ts +21 -71
- package/src/__tests__/conversation-wait-for-idle.test.ts +0 -82
- package/src/__tests__/conversation-workspace-cache-state.test.ts +0 -45
- package/src/__tests__/conversation-workspace-injection.test.ts +0 -88
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -88
- package/src/__tests__/conversations-defer-cli.test.ts +3 -0
- package/src/__tests__/conversations-import-system-filter.test.ts +0 -17
- package/src/__tests__/credential-broker-browser-fill.test.ts +0 -9
- package/src/__tests__/credential-broker-server-use.test.ts +0 -9
- package/src/__tests__/credential-health-service.test.ts +14 -31
- package/src/__tests__/credential-metadata-store.test.ts +0 -8
- package/src/__tests__/credential-prompt-route.test.ts +9 -15
- package/src/__tests__/credential-resolve.test.ts +0 -8
- package/src/__tests__/credential-routes.test.ts +250 -0
- package/src/__tests__/credential-security-invariants.test.ts +4 -8
- package/src/__tests__/credential-token-resolver.test.ts +0 -9
- package/src/__tests__/cross-provider-web-search.test.ts +12 -18
- package/src/__tests__/daemon-assistant-events.test.ts +1 -9
- package/src/__tests__/daemon-credential-client.test.ts +0 -7
- package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +1 -8
- package/src/__tests__/db-conversation-inference-profile-migration.test.ts +1 -7
- package/src/__tests__/db-llm-request-log-provider-migration.test.ts +0 -8
- package/src/__tests__/db-readiness-http-gate.test.ts +0 -18
- package/src/__tests__/db-rename-inference-profile-snake-case-migration.test.ts +1 -7
- package/src/__tests__/db-test-helpers.ts +10 -3
- package/src/__tests__/delete-managed-skill-tool.test.ts +0 -7
- package/src/__tests__/delete-propagation.test.ts +0 -7
- package/src/__tests__/deterministic-verification-control-plane.test.ts +0 -7
- package/src/__tests__/device-id.test.ts +1 -9
- package/src/__tests__/disk-pressure-guard.test.ts +0 -4
- package/src/__tests__/disk-pressure-routes.test.ts +0 -4
- package/src/__tests__/disk-pressure-tools.test.ts +4 -42
- package/src/__tests__/dm-backfill.test.ts +0 -7
- package/src/__tests__/dm-persistence.test.ts +0 -5
- package/src/__tests__/docker-signing-key-bootstrap.test.ts +1 -8
- package/src/__tests__/drain-requeue-on-contention.test.ts +1 -8
- package/src/__tests__/dynamic-skill-background-guard.test.ts +0 -43
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +2 -27
- package/src/__tests__/edit-propagation.test.ts +1 -8
- package/src/__tests__/email-invite-adapter.test.ts +8 -33
- package/src/__tests__/embedding-managed-proxy-selection.test.ts +0 -8
- package/src/__tests__/emit-event-signal.test.ts +1 -1
- package/src/__tests__/emit-signal-routing-intent.test.ts +0 -7
- package/src/__tests__/empty-state-greeting-cache.test.ts +9 -9
- package/src/__tests__/encrypted-store.test.ts +0 -9
- package/src/__tests__/ensure-conversation-exists.test.ts +1 -18
- package/src/__tests__/events-client-registration.test.ts +1 -19
- package/src/__tests__/events-dev-bypass-actor.test.ts +0 -7
- package/src/__tests__/events-tail-route.test.ts +1 -8
- package/src/__tests__/file-list-tool.test.ts +22 -15
- package/src/__tests__/followup-tools.test.ts +1 -16
- package/src/__tests__/gateway-only-enforcement.test.ts +3 -44
- package/src/__tests__/get-skill-detail-audit.test.ts +0 -7
- package/src/__tests__/google-calendar-watcher.test.ts +175 -0
- package/src/__tests__/guardian-action-sweep.test.ts +0 -7
- package/src/__tests__/guardian-binding-drift-heal.test.ts +0 -7
- package/src/__tests__/guardian-card-withdrawal.test.ts +60 -64
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +172 -135
- package/src/__tests__/guardian-dispatch.test.ts +58 -157
- package/src/__tests__/guardian-expiry-notifier.test.ts +56 -48
- package/src/__tests__/guardian-gateway-sim.ts +626 -0
- package/src/__tests__/guardian-outbound-http.test.ts +0 -7
- package/src/__tests__/guardian-routing-invariants.test.ts +229 -220
- package/src/__tests__/guardian-routing-state.test.ts +2 -9
- package/src/__tests__/guardian-verification-voice-binding.test.ts +0 -17
- package/src/__tests__/guardian-wait-controller.test.ts +44 -43
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +26 -91
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +18 -103
- package/src/__tests__/headless-browser-interactions.test.ts +0 -7
- package/src/__tests__/headless-browser-mode.test.ts +0 -9
- package/src/__tests__/headless-browser-navigate.test.ts +0 -7
- package/src/__tests__/headless-browser-read-tools.test.ts +0 -7
- package/src/__tests__/headless-browser-snapshot.test.ts +0 -7
- package/src/__tests__/heartbeat-disk-pressure.test.ts +9 -38
- package/src/__tests__/heartbeat-service.test.ts +83 -106
- package/src/__tests__/helpers/channel-test-adapter.ts +10 -0
- package/src/__tests__/helpers/gateway-guardian-requests-store-bridge.ts +155 -0
- package/src/__tests__/helpers/set-config.ts +40 -0
- package/src/__tests__/host-bash-proxy.test.ts +18 -34
- package/src/__tests__/host-browser-proxy.test.ts +15 -20
- package/src/__tests__/host-shell-tool.test.ts +2 -34
- package/src/__tests__/http-conversation-lineage.test.ts +3 -19
- package/src/__tests__/http-user-message-parity.test.ts +3 -95
- package/src/__tests__/identity-routes.test.ts +1 -9
- package/src/__tests__/image-recovery-hook.test.ts +36 -0
- package/src/__tests__/inbound-admitted-introduction-nudge.test.ts +6 -12
- package/src/__tests__/inbound-invite-redemption.test.ts +0 -7
- package/src/__tests__/inbound-slack-persistence.test.ts +0 -5
- package/src/__tests__/inbound-trust-verdict.test.ts +2 -8
- package/src/__tests__/inference-no-mode-boot-e2e.test.ts +52 -8
- package/src/__tests__/inference-profile-reaper.test.ts +1 -7
- package/src/__tests__/inference-profile-session-handler.test.ts +4 -30
- package/src/__tests__/inference-profile-session-ipc.test.ts +3 -20
- package/src/__tests__/ingress-url-consistency.test.ts +1 -23
- package/src/__tests__/injector-background-turn.test.ts +10 -24
- package/src/__tests__/injector-chain.test.ts +4 -13
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +19 -17
- package/src/__tests__/inline-command-runner.test.ts +0 -34
- package/src/__tests__/inline-skill-load-permissions.test.ts +1 -30
- package/src/__tests__/install-skill-routing.test.ts +7 -6
- package/src/__tests__/integration-status.test.ts +25 -17
- package/src/__tests__/intent-routing.test.ts +1 -50
- package/src/__tests__/internal-telemetry-routes.test.ts +41 -22
- package/src/__tests__/interrupted-turn-reconciler.test.ts +1 -8
- package/src/__tests__/introduction-card-resolver.test.ts +108 -117
- package/src/__tests__/invite-redeemed-ipc.test.ts +0 -7
- package/src/__tests__/invite-routes-http.test.ts +12 -23
- package/src/__tests__/jobs-store-has-pending-job.test.ts +59 -0
- package/src/__tests__/jobs-store-qdrant-breaker.test.ts +1 -14
- package/src/__tests__/jobs-store-skill-card-upsert.test.ts +191 -0
- package/src/__tests__/jobs-store-upsert-debounced.test.ts +1 -14
- package/src/__tests__/lexical-index-dual-write.test.ts +0 -6
- package/src/__tests__/list-all-apps.test.ts +200 -0
- package/src/__tests__/list-messages-attachments.test.ts +11 -20
- package/src/__tests__/list-messages-background-tool-completion.test.ts +6 -18
- package/src/__tests__/list-messages-client-message-id.test.ts +4 -16
- package/src/__tests__/list-messages-hidden-metadata.test.ts +6 -18
- package/src/__tests__/list-messages-page-latest.test.ts +3 -19
- package/src/__tests__/list-messages-queued.test.ts +1 -18
- package/src/__tests__/list-messages-tool-merge.test.ts +7 -18
- package/src/__tests__/llm-context-resolution.test.ts +32 -56
- package/src/__tests__/llm-context-route-provider.test.ts +1 -8
- package/src/__tests__/llm-request-log-agent-loop-exit-reason.test.ts +1 -19
- package/src/__tests__/llm-request-log-call-site.test.ts +1 -19
- package/src/__tests__/llm-request-log-clickhouse-routing.test.ts +114 -0
- package/src/__tests__/llm-request-log-clickhouse-writer-guards.test.ts +108 -0
- package/src/__tests__/llm-request-log-disabled-writes.test.ts +11 -30
- package/src/__tests__/llm-request-log-sink-clickhouse.test.ts +205 -0
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +1 -22
- package/src/__tests__/llm-request-log-source-factory.test.ts +23 -69
- package/src/__tests__/llm-request-log-turn-query.test.ts +1 -19
- package/src/__tests__/llm-resolver-override-or-default.test.ts +3 -52
- package/src/__tests__/llm-resolver.test.ts +342 -602
- package/src/__tests__/llm-schema.test.ts +79 -37
- package/src/__tests__/llm-usage-store.test.ts +1 -7
- package/src/__tests__/log-export-routes.test.ts +0 -7
- package/src/__tests__/log-export-workspace.test.ts +0 -7
- package/src/__tests__/managed-profile-guard.test.ts +125 -137
- package/src/__tests__/managed-skill-lifecycle.test.ts +6 -50
- package/src/__tests__/managed-speech-defaults.test.ts +138 -0
- package/src/__tests__/managed-store.test.ts +1 -16
- package/src/__tests__/mcp-auth-routes.test.ts +15 -26
- package/src/__tests__/mcp-config-secret-boundary.test.ts +49 -91
- package/src/__tests__/mcp-health-check.test.ts +14 -20
- package/src/__tests__/media-generate-image.test.ts +25 -32
- package/src/__tests__/media-stream-output.test.ts +0 -9
- package/src/__tests__/media-stream-server-integration.test.ts +19 -27
- package/src/__tests__/media-stream-stt-session.test.ts +16 -29
- package/src/__tests__/memory-jobs-worker-backoff.test.ts +6 -19
- package/src/__tests__/memory-jobs-worker-cleanup-cadence.test.ts +33 -12
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +10 -29
- package/src/__tests__/memory-recall-log-store.test.ts +1 -19
- package/src/__tests__/memory-retrieval-hook.test.ts +0 -3
- package/src/__tests__/memory-upsert-concurrency.test.ts +12 -35
- package/src/__tests__/memory-v2-static-injector.test.ts +5 -17
- package/src/__tests__/messages-after-tiebreaker.test.ts +1 -7
- package/src/__tests__/messaging-send-tool.test.ts +67 -7
- package/src/__tests__/migration-cross-version-compatibility.test.ts +0 -18
- package/src/__tests__/migration-export-http.test.ts +10 -23
- package/src/__tests__/migration-export-streaming.test.ts +0 -18
- package/src/__tests__/migration-export-to-gcs.test.ts +0 -19
- package/src/__tests__/migration-import-commit-http.test.ts +11 -23
- package/src/__tests__/migration-import-from-gcs.test.ts +0 -19
- package/src/__tests__/migration-import-from-url.test.ts +0 -19
- package/src/__tests__/migration-import-preflight-http.test.ts +10 -22
- package/src/__tests__/migration-jobs-status.test.ts +8 -23
- package/src/__tests__/migration-validate-http.test.ts +2 -19
- package/src/__tests__/mtime-cache.test.ts +116 -2
- package/src/__tests__/native-web-search.test.ts +0 -21
- package/src/__tests__/non-member-access-request.test.ts +102 -93
- package/src/__tests__/notification-broadcaster.test.ts +32 -21
- package/src/__tests__/notification-candidate-guardian-context.test.ts +36 -34
- package/src/__tests__/notification-decision-fallback.test.ts +0 -7
- package/src/__tests__/notification-decision-identity.test.ts +0 -7
- package/src/__tests__/notification-decision-recipient-context.test.ts +0 -7
- package/src/__tests__/notification-deep-link.test.ts +0 -7
- package/src/__tests__/notification-guardian-path.test.ts +48 -93
- package/src/__tests__/notification-platform-adapter.test.ts +0 -7
- package/src/__tests__/notification-routing-intent.test.ts +1 -9
- package/src/__tests__/notification-schedule-notify-dedup.test.ts +1 -9
- package/src/__tests__/notification-telegram-adapter.test.ts +0 -7
- package/src/__tests__/oauth-cli.test.ts +0 -19
- package/src/__tests__/oauth-commands-routes.test.ts +28 -43
- package/src/__tests__/oauth-connect-orchestrator.test.ts +17 -26
- package/src/__tests__/oauth-connect-routes.test.ts +19 -18
- package/src/__tests__/oauth-provider-profiles.test.ts +3 -9
- package/src/__tests__/oauth-provider-visibility.test.ts +0 -7
- package/src/__tests__/oauth-store.test.ts +0 -7
- package/src/__tests__/oauth2-gateway-transport.test.ts +41 -43
- package/src/__tests__/openai-responses-prompt-cache.test.ts +355 -0
- package/src/__tests__/openai-responses-provider.test.ts +98 -9
- package/src/__tests__/openrouter-responses-transport.test.ts +170 -0
- package/src/__tests__/outbound-slack-persistence.test.ts +13 -46
- package/src/__tests__/outlook-email-watcher.test.ts +0 -9
- package/src/__tests__/outlook-messaging-provider.test.ts +71 -0
- package/src/__tests__/path-policy.test.ts +0 -7
- package/src/__tests__/persist-media-references.test.ts +1 -6
- package/src/__tests__/persist-unsendable-image-downscale.test.ts +6 -3
- package/src/__tests__/persist-unsendable-image.test.ts +39 -7
- package/src/__tests__/persistence-secret-redaction.test.ts +7 -28
- package/src/__tests__/platform-bash-auto-approve.test.ts +0 -46
- package/src/__tests__/platform-callback-registration.test.ts +10 -9
- package/src/__tests__/platform-proxy-context.test.ts +0 -8
- package/src/__tests__/playbook-execution.test.ts +0 -14
- package/src/__tests__/playbook-tools.test.ts +0 -14
- package/src/__tests__/plugin-api-model-profiles.test.ts +12 -35
- package/src/__tests__/plugin-app-serve-routes.test.ts +315 -0
- package/src/__tests__/plugin-import-boundary-guard.test.ts +5 -3
- package/src/__tests__/plugin-import-boundary-reverse-guard.test.ts +0 -2
- package/src/__tests__/plugin-types.test.ts +0 -7
- package/src/__tests__/prechat-onboarding-contract.test.ts +0 -27
- package/src/__tests__/pricing.test.ts +45 -0
- package/src/__tests__/process-message-background-slack.test.ts +7 -21
- package/src/__tests__/process-message-display-content.test.ts +37 -6
- package/src/__tests__/processing-flag-persist-failure.test.ts +0 -44
- package/src/__tests__/provider-commit-message-generator.test.ts +57 -63
- package/src/__tests__/provider-error-scenarios.test.ts +5 -6
- package/src/__tests__/provider-platform-proxy-integration.test.ts +21 -57
- package/src/__tests__/provider-registry-ollama.test.ts +8 -18
- package/src/__tests__/provider-send-message-override-profile.test.ts +28 -39
- package/src/__tests__/provider-streaming.benchmark.test.ts +1 -6
- package/src/__tests__/provider-usage-tracking.test.ts +13 -35
- package/src/__tests__/proxy-approval-callback.test.ts +0 -16
- package/src/__tests__/prune-old-conversations-job.test.ts +29 -21
- package/src/__tests__/prune-old-tool-invocations-job.test.ts +1 -9
- package/src/__tests__/public-ingress-urls.test.ts +1 -24
- package/src/__tests__/published-app-updater.test.ts +22 -16
- package/src/__tests__/qdrant-collection-migration.test.ts +0 -7
- package/src/__tests__/qdrant-manager.test.ts +0 -8
- package/src/__tests__/ratelimit.test.ts +1 -8
- package/src/__tests__/reaction-persistence.test.ts +18 -24
- package/src/__tests__/rebuild-index-graph-nodes.test.ts +0 -14
- package/src/__tests__/recording-handler.test.ts +0 -27
- package/src/__tests__/request-secret-standalone-channel-gate.test.ts +4 -16
- package/src/__tests__/require-fresh-approval.test.ts +0 -45
- package/src/__tests__/retry-openrouter-only-normalization.test.ts +24 -36
- package/src/__tests__/retry-prompt-cache-key.test.ts +123 -0
- package/src/__tests__/retry-thinking-adaptive-only.test.ts +45 -61
- package/src/__tests__/retry-thinking-tool-choice.test.ts +60 -80
- package/src/__tests__/retry-verbosity-normalization.test.ts +27 -37
- package/src/__tests__/reveal-success-registry.test.ts +123 -0
- package/src/__tests__/run-conversation-turn-persistence.test.ts +113 -0
- package/src/__tests__/{scheduler-worker-standdown.test.ts → run-due-schedules.test.ts} +5 -77
- package/src/__tests__/runtime-attachment-metadata.test.ts +5 -18
- package/src/__tests__/runtime-events-sse-bilingual.test.ts +1 -19
- package/src/__tests__/runtime-events-sse-parity.test.ts +1 -20
- package/src/__tests__/runtime-events-sse-reconnect.test.ts +1 -19
- package/src/__tests__/runtime-events-sse.test.ts +1 -20
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +306 -5
- package/src/__tests__/schedule-retry.test.ts +22 -23
- package/src/__tests__/schedule-routes-workflow-validation.test.ts +18 -42
- package/src/__tests__/schedule-routes.test.ts +2 -150
- package/src/__tests__/schedule-store.test.ts +0 -8
- package/src/__tests__/schedule-tools.test.ts +1 -16
- package/src/__tests__/scheduler-disk-pressure.test.ts +0 -26
- package/src/__tests__/scheduler-recurrence.test.ts +43 -76
- package/src/__tests__/scheduler-reuse-conversation.test.ts +19 -35
- package/src/__tests__/scheduler-wake.test.ts +8 -24
- package/src/__tests__/scoped-approval-grants.test.ts +1 -9
- package/src/__tests__/scoped-grant-security-matrix.test.ts +1 -9
- package/src/__tests__/search-skills-unified.test.ts +0 -6
- package/src/__tests__/secret-allowlist.test.ts +1 -8
- package/src/__tests__/secret-fixtures.ts +9 -0
- package/src/__tests__/secret-ingress-channel.test.ts +4 -32
- package/src/__tests__/secret-ingress-cli.test.ts +3 -37
- package/src/__tests__/secret-ingress-http.test.ts +15 -78
- package/src/__tests__/secret-ingress.test.ts +14 -31
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +4 -10
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +3 -9
- package/src/__tests__/secret-routes-platform-proxy.test.ts +3 -40
- package/src/__tests__/secure-keys-managed-failover.test.ts +0 -7
- package/src/__tests__/secure-keys.test.ts +0 -9
- package/src/__tests__/send-endpoint-busy.test.ts +47 -91
- package/src/__tests__/sequence-store.test.ts +0 -9
- package/src/__tests__/server-history-render.test.ts +29 -8
- package/src/__tests__/set-permission-mode.test.ts +8 -16
- package/src/__tests__/settings-routes.test.ts +0 -7
- package/src/__tests__/shell-credential-ref.test.ts +0 -18
- package/src/__tests__/shell-observability.test.ts +0 -21
- package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -34
- package/src/__tests__/skill-load-feature-flag.test.ts +0 -27
- package/src/__tests__/skill-load-inline-command.test.ts +0 -25
- package/src/__tests__/skill-load-inline-includes.test.ts +0 -25
- package/src/__tests__/skill-load-plugin-scope.test.ts +0 -24
- package/src/__tests__/skill-projection-feature-flag.test.ts +14 -33
- package/src/__tests__/skill-projection.benchmark.test.ts +14 -19
- package/src/__tests__/skill-script-runner-sandbox.test.ts +1 -39
- package/src/__tests__/skills-file-content-endpoint.test.ts +0 -7
- package/src/__tests__/skills-files-catalog-fallback.test.ts +0 -14
- package/src/__tests__/slack-channel-config.test.ts +24 -79
- package/src/__tests__/slack-inbound-verification.test.ts +5 -13
- package/src/__tests__/{slack-reaction-canonical-approval.test.ts → slack-reaction-guardian-approval.test.ts} +18 -74
- package/src/__tests__/slack-share-routes.test.ts +0 -1
- package/src/__tests__/slim-skill-category.test.ts +0 -14
- package/src/__tests__/stale-approval-dedup.test.ts +0 -7
- package/src/__tests__/subagent-call-site-routing.test.ts +72 -111
- package/src/__tests__/subagent-detail.test.ts +1 -1
- package/src/__tests__/subagent-fork-prompt-role.test.ts +0 -12
- package/src/__tests__/subagent-notify-parent.test.ts +4 -6
- package/src/__tests__/subagent-spawn-and-await.test.ts +0 -18
- package/src/__tests__/subagent-tool-filtering.test.ts +21 -31
- package/src/__tests__/subagent-tool-gate-mode.test.ts +6 -32
- package/src/__tests__/subagent-tools.test.ts +92 -67
- package/src/__tests__/suggestion-routes.test.ts +28 -42
- package/src/__tests__/summarize-boundary.test.ts +2 -1
- package/src/__tests__/system-prompt-ask-mode.test.ts +0 -25
- package/src/__tests__/system-prompt.test.ts +0 -33
- package/src/__tests__/task-memory-cleanup.test.ts +18 -192
- package/src/__tests__/telegram-bot-username-resolution.test.ts +24 -48
- package/src/__tests__/telegram-config.test.ts +0 -8
- package/src/__tests__/telemetry-routes.test.ts +100 -0
- package/src/__tests__/telephony-credential-preflight.test.ts +7 -11
- package/src/__tests__/telephony-tts-guard.test.ts +38 -21
- package/src/__tests__/terminal-tools.test.ts +0 -21
- package/src/__tests__/thread-backfill.test.ts +0 -7
- package/src/__tests__/title-generate-hook.test.ts +11 -10
- package/src/__tests__/token-manager.test.ts +0 -9
- package/src/__tests__/tool-approval-handler.test.ts +0 -8
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +5 -33
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +3 -23
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -48
- package/src/__tests__/tool-executor.test.ts +3 -49
- package/src/__tests__/tool-grant-request-escalation.test.ts +51 -153
- package/src/__tests__/tool-preview-lifecycle.test.ts +2 -29
- package/src/__tests__/tool-profiler.test.ts +72 -1
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +0 -29
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +0 -1
- package/src/__tests__/tool-start-timestamp.test.ts +4 -31
- package/src/__tests__/tools-get-route.test.ts +2 -1
- package/src/__tests__/trust-context-guards.test.ts +19 -7
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +75 -79
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +14 -18
- package/src/__tests__/trusted-contact-multichannel.test.ts +0 -7
- package/src/__tests__/trusted-contact-verification.test.ts +1 -9
- package/src/__tests__/turn-boundary-resolution.test.ts +1 -19
- package/src/__tests__/turn-events-store.test.ts +1 -7
- package/src/__tests__/turn-outcome-read.test.ts +1 -7
- package/src/__tests__/twilio-config.test.ts +11 -28
- package/src/__tests__/twilio-provider.test.ts +2 -13
- package/src/__tests__/twilio-routes-twiml.test.ts +1 -8
- package/src/__tests__/twilio-routes.test.ts +52 -103
- package/src/__tests__/twilio-validation.test.ts +5 -22
- package/src/__tests__/ui-file-upload-surface.test.ts +6 -9
- package/src/__tests__/usage-attribution.test.ts +25 -56
- package/src/__tests__/usage-cache-backfill-migration.test.ts +8 -15
- package/src/__tests__/usage-routes.test.ts +1 -8
- package/src/__tests__/vbundle-pax-and-symlink.test.ts +0 -18
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +0 -24
- package/src/__tests__/vercel-config.test.ts +0 -7
- package/src/__tests__/verification-control-plane-policy.test.ts +0 -45
- package/src/__tests__/voice-approval-resolver-relay.test.ts +106 -75
- package/src/__tests__/voice-config-update.test.ts +114 -21
- package/src/__tests__/voice-ingress-preflight.test.ts +16 -15
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -30
- package/src/__tests__/voice-session-bridge-processing-wait.test.ts +1 -17
- package/src/__tests__/voice-session-bridge.test.ts +14 -46
- package/src/__tests__/web-search-backend-failure.test.ts +0 -21
- package/src/__tests__/whatsapp-invite-adapter.test.ts +11 -30
- package/src/__tests__/workspace-git-service.test.ts +801 -2
- package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +1 -26
- package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +1 -26
- package/src/__tests__/workspace-migration-028-recover-conversations-from-disk-view.test.ts +1 -26
- package/src/a2a/__tests__/e2e-a2a-channel.test.ts +1 -9
- package/src/a2a/__tests__/task-store.test.ts +0 -9
- package/src/acp/__tests__/session-manager-persistence.test.ts +1 -8
- package/src/acp/__tests__/session-manager-resume.test.ts +0 -7
- package/src/acp/__tests__/session-manager-startup.test.ts +1 -8
- package/src/agent/image-optimize.ts +80 -0
- package/src/agent/loop.ts +20 -5
- package/src/api/events/open-conversation.test.ts +64 -0
- package/src/api/events/open-conversation.ts +33 -0
- package/src/api/index.ts +6 -0
- package/src/approvals/AGENTS.md +1 -1
- package/src/approvals/guardian-card-withdrawal.ts +26 -19
- package/src/approvals/guardian-decision-primitive.ts +172 -102
- package/src/approvals/guardian-expiry-notifier.ts +20 -19
- package/src/approvals/guardian-request-resolvers.ts +305 -275
- package/src/apps/app-store.ts +320 -15
- package/src/background-wake/background-wake-routes.test.ts +2 -3
- package/src/background-wake/next-wake.test.ts +23 -20
- package/src/background-wake/wake-intent-hooks.test.ts +0 -10
- package/src/bundler/app-bundler.ts +34 -48
- package/src/bundler/app-compiler.ts +39 -4
- package/src/bundler/bundle-scanner.ts +13 -0
- package/src/bundler/manifest.ts +1 -1
- package/src/calls/__tests__/call-setup-router.test.ts +84 -88
- package/src/calls/__tests__/fish-audio-client.test.ts +6 -11
- package/src/calls/__tests__/voice-control-protocol.test.ts +47 -0
- package/src/calls/__tests__/voice-session-bridge.test.ts +151 -16
- package/src/calls/__tests__/voice-triage-escalate.test.ts +128 -0
- package/src/calls/access-request-wait.ts +35 -35
- package/src/calls/call-controller.ts +48 -45
- package/src/calls/call-setup-flow.ts +2 -2
- package/src/calls/call-setup-router.ts +1 -24
- package/src/calls/guardian-dispatch.ts +47 -30
- package/src/calls/guardian-wait-controller.ts +31 -18
- package/src/calls/media-turn-detector.ts +11 -1
- package/src/calls/telephony-credential-preflight.ts +19 -1
- package/src/calls/telephony-tts-capability.ts +18 -1
- package/src/calls/voice-control-protocol.ts +12 -0
- package/src/calls/voice-session-bridge.ts +110 -15
- package/src/calls/voice-triage-escalate.ts +136 -0
- package/src/channels/__tests__/gateway-guardian-requests.test.ts +669 -0
- package/src/channels/gateway-guardian-requests.ts +410 -0
- package/src/channels/types.ts +10 -5
- package/src/cli/AGENTS.md +77 -51
- package/src/cli/__tests__/cli-command-help-coverage.test.ts +29 -0
- package/src/cli/commands/__tests__/conversations-import.test.ts +23 -24
- package/src/cli/commands/__tests__/gateway.test.ts +55 -0
- package/src/cli/commands/__tests__/inference-models.test.ts +3 -0
- package/src/cli/commands/__tests__/inference-profiles.test.ts +3 -0
- package/src/cli/commands/__tests__/inference-providers.test.ts +3 -0
- package/src/cli/commands/__tests__/inference-send.test.ts +0 -10
- package/src/cli/commands/__tests__/inference-session.test.ts +4 -11
- package/src/cli/commands/__tests__/ui.test.ts +2 -2
- package/src/cli/commands/apps.help.ts +46 -0
- package/src/cli/commands/apps.ts +51 -0
- package/src/cli/commands/avatar.help.ts +229 -0
- package/src/cli/commands/avatar.ts +58 -250
- package/src/cli/commands/backup.help.ts +183 -0
- package/src/cli/commands/backup.ts +107 -276
- package/src/cli/commands/bash.help.ts +38 -0
- package/src/cli/commands/bash.ts +51 -75
- package/src/cli/commands/browser.help.ts +193 -0
- package/src/cli/commands/browser.ts +234 -347
- package/src/cli/commands/cache.help.ts +123 -0
- package/src/cli/commands/cache.ts +72 -166
- package/src/cli/commands/changelog.help.ts +59 -0
- package/src/cli/commands/changelog.ts +29 -61
- package/src/cli/commands/channel-verification-sessions.help.ts +178 -0
- package/src/cli/commands/channel-verification-sessions.ts +71 -226
- package/src/cli/commands/channels/index.help.ts +67 -0
- package/src/cli/commands/channels/index.ts +55 -105
- package/src/cli/commands/clients.help.ts +72 -0
- package/src/cli/commands/clients.ts +100 -153
- package/src/cli/commands/completions.help.ts +33 -0
- package/src/cli/commands/completions.ts +43 -66
- package/src/cli/commands/config.help.ts +126 -0
- package/src/cli/commands/config.ts +59 -174
- package/src/cli/commands/contacts.help.ts +327 -0
- package/src/cli/commands/contacts.ts +318 -603
- package/src/cli/commands/conversations-defer.ts +141 -202
- package/src/cli/commands/conversations-import.ts +80 -113
- package/src/cli/commands/conversations.help.ts +364 -0
- package/src/cli/commands/conversations.ts +143 -328
- package/src/cli/commands/credentials.help.ts +290 -0
- package/src/cli/commands/credentials.ts +271 -487
- package/src/cli/commands/db/index.help.ts +27 -0
- package/src/cli/commands/db/index.ts +7 -3
- package/src/cli/commands/db/refresh.ts +131 -0
- package/src/cli/commands/db/repair-step-conversation-backfill.ts +19 -9
- package/src/cli/commands/db/repair.ts +41 -43
- package/src/cli/commands/db/status.ts +79 -83
- package/src/cli/commands/domain.help.ts +34 -0
- package/src/cli/commands/domain.ts +10 -15
- package/src/cli/commands/email.help.ts +176 -0
- package/src/cli/commands/email.ts +323 -412
- package/src/cli/commands/gateway.help.ts +115 -0
- package/src/cli/commands/gateway.ts +105 -123
- package/src/cli/commands/image-generation.help.ts +72 -0
- package/src/cli/commands/image-generation.ts +13 -62
- package/src/cli/commands/inference-callsites.ts +34 -49
- package/src/cli/commands/inference-models.ts +6 -21
- package/src/cli/commands/inference-profiles.ts +95 -156
- package/src/cli/commands/inference-providers-default.ts +27 -42
- package/src/cli/commands/inference-providers.ts +25 -87
- package/src/cli/commands/inference-session.ts +189 -249
- package/src/cli/commands/inference.help.ts +485 -0
- package/src/cli/commands/inference.ts +104 -165
- package/src/cli/commands/keys.help.ts +46 -0
- package/src/cli/commands/keys.ts +37 -71
- package/src/cli/commands/mcp.help.ts +167 -0
- package/src/cli/commands/mcp.ts +123 -267
- package/src/cli/commands/memory/__tests__/memory-items.test.ts +4 -0
- package/src/cli/commands/memory/__tests__/memory-v2.test.ts +4 -0
- package/src/cli/commands/memory/__tests__/memory-v3.test.ts +4 -0
- package/src/cli/commands/memory/__tests__/worker.test.ts +12 -5
- package/src/cli/commands/memory/index.help.ts +814 -0
- package/src/cli/commands/memory/index.ts +5 -27
- package/src/cli/commands/memory/items.ts +257 -404
- package/src/cli/commands/memory/memory-retrospective.ts +31 -71
- package/src/cli/commands/memory/memory-v2-compare-render.ts +2 -2
- package/src/cli/commands/memory/memory-v2.ts +435 -646
- package/src/cli/commands/memory/memory-v3.ts +158 -283
- package/src/cli/commands/memory/nodes.ts +154 -249
- package/src/cli/commands/memory/worker.ts +83 -128
- package/src/cli/commands/monitoring.help.ts +57 -0
- package/src/cli/commands/monitoring.ts +17 -41
- package/src/cli/commands/notifications.help.ts +293 -0
- package/src/cli/commands/notifications.ts +420 -657
- package/src/cli/commands/oauth/apps.ts +182 -315
- package/src/cli/commands/oauth/connect.ts +4 -35
- package/src/cli/commands/oauth/disconnect.ts +44 -71
- package/src/cli/commands/oauth/index.help.ts +855 -0
- package/src/cli/commands/oauth/index.ts +5 -31
- package/src/cli/commands/oauth/mode.ts +5 -28
- package/src/cli/commands/oauth/ping.ts +44 -66
- package/src/cli/commands/oauth/providers.ts +413 -772
- package/src/cli/commands/oauth/request.ts +6 -35
- package/src/cli/commands/oauth/shared.ts +1 -1
- package/src/cli/commands/oauth/status.test.ts +6 -6
- package/src/cli/commands/oauth/status.ts +45 -62
- package/src/cli/commands/oauth/token.ts +32 -71
- package/src/cli/commands/pending.help.ts +26 -0
- package/src/cli/commands/pending.ts +77 -78
- package/src/cli/commands/platform/__tests__/connect.test.ts +3 -1
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +4 -4
- package/src/cli/commands/platform/__tests__/status.test.ts +0 -90
- package/src/cli/commands/platform/connect.ts +10 -21
- package/src/cli/commands/platform/disconnect.ts +11 -26
- package/src/cli/commands/platform/index.help.ts +187 -0
- package/src/cli/commands/platform/index.ts +22 -169
- package/src/cli/commands/plugins.help.ts +247 -0
- package/src/cli/commands/plugins.ts +356 -437
- package/src/cli/commands/ps.help.ts +26 -0
- package/src/cli/commands/ps.ts +5 -17
- package/src/cli/commands/routes.help.ts +72 -0
- package/src/cli/commands/routes.ts +78 -125
- package/src/cli/commands/schedules-worker.ts +70 -138
- package/src/cli/commands/schedules.help.ts +514 -0
- package/src/cli/commands/schedules.ts +494 -871
- package/src/cli/commands/sequence.help.ts +183 -0
- package/src/cli/commands/sequence.ts +181 -343
- package/src/cli/commands/skills.help.ts +159 -0
- package/src/cli/commands/skills.ts +230 -368
- package/src/cli/commands/status.help.ts +32 -0
- package/src/cli/commands/status.ts +38 -3
- package/src/cli/commands/stt.help.ts +52 -0
- package/src/cli/commands/stt.ts +9 -47
- package/src/cli/commands/telemetry.help.ts +14 -0
- package/src/cli/commands/telemetry.ts +19 -17
- package/src/cli/commands/tools-run.ts +30 -45
- package/src/cli/commands/tools.help.ts +81 -0
- package/src/cli/commands/tools.ts +43 -83
- package/src/cli/commands/trust.help.ts +43 -0
- package/src/cli/commands/trust.ts +82 -109
- package/src/cli/commands/tts.help.ts +88 -0
- package/src/cli/commands/tts.ts +116 -188
- package/src/cli/commands/ui.help.ts +213 -0
- package/src/cli/commands/ui.ts +363 -380
- package/src/cli/commands/usage.help.ts +147 -0
- package/src/cli/commands/usage.ts +87 -206
- package/src/cli/commands/watchers.help.ts +211 -0
- package/src/cli/commands/watchers.ts +261 -417
- package/src/cli/commands/webhooks.help.ts +95 -0
- package/src/cli/commands/webhooks.ts +44 -115
- package/src/cli/index.help.ts +91 -0
- package/src/cli/lib/__tests__/global-json-option.test.ts +97 -0
- package/src/cli/lib/__tests__/install-from-github.test.ts +144 -4
- package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +96 -132
- package/src/cli/lib/__tests__/plugin-catalog-local.test.ts +65 -0
- package/src/cli/lib/__tests__/plugin-catalog-platform.test.ts +167 -0
- package/src/cli/lib/__tests__/plugin-catalog-resolve.test.ts +197 -0
- package/src/cli/lib/__tests__/plugin-details.test.ts +349 -240
- package/src/cli/lib/__tests__/plugin-fingerprint.test.ts +31 -0
- package/src/cli/lib/__tests__/plugin-icon-file.test.ts +50 -1
- package/src/cli/lib/__tests__/plugin-marketplace.test.ts +94 -0
- package/src/cli/lib/__tests__/plugins-install-offline.test.ts +147 -0
- package/src/cli/lib/__tests__/search-plugins.test.ts +193 -309
- package/src/cli/lib/bundled-marketplace.json +439 -0
- package/src/cli/lib/cli-command-help.ts +83 -10
- package/src/cli/lib/global-json-option.ts +41 -0
- package/src/cli/lib/install-from-github.ts +69 -2
- package/src/cli/lib/plugin-catalog-cache.ts +22 -50
- package/src/cli/lib/plugin-catalog-local.ts +71 -0
- package/src/cli/lib/plugin-catalog-platform.ts +117 -0
- package/src/cli/lib/plugin-catalog-resolve.ts +72 -0
- package/src/cli/lib/plugin-details.ts +100 -34
- package/src/cli/lib/plugin-fingerprint.ts +18 -7
- package/src/cli/lib/plugin-icon-file.ts +38 -26
- package/src/cli/lib/plugin-marketplace.ts +15 -2
- package/src/cli/lib/publish-plugin.ts +3 -3
- package/src/cli/lib/search-plugins.ts +48 -111
- package/src/cli/program.ts +7 -0
- package/src/cli.ts +22 -13
- package/src/config/__tests__/default-profile-catalog.test.ts +8 -12
- package/src/config/__tests__/default-provider.test.ts +0 -21
- package/src/config/__tests__/deployment-context-defaults.test.ts +0 -21
- package/src/config/__tests__/feature-flag-registry-bundled.test.ts +2 -2
- package/src/config/__tests__/loader-callsite-strip-fallback.test.ts +0 -21
- package/src/config/__tests__/loader-last-known-good.test.ts +0 -21
- package/src/config/__tests__/loader-sparse-array-cleanup.test.ts +0 -21
- package/src/config/__tests__/platform-rehydration.test.ts +125 -0
- package/src/config/__tests__/profile-materialization.test.ts +1 -88
- package/src/config/__tests__/seed-default-provider.test.ts +0 -21
- package/src/config/__tests__/sync-gated-profiles.test.ts +0 -21
- package/src/config/bundled-skills/app-builder/SKILL.md +24 -1
- package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +30 -0
- package/src/config/bundled-skills/contacts/SKILL.md +1 -1
- package/src/config/bundled-skills/contacts/tools/contact-merge.ts +4 -2
- package/src/config/bundled-skills/messaging/TOOLS.json +2 -2
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +28 -20
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +7 -7
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +3 -3
- package/src/config/bundled-skills/schedule/SKILL.md +0 -1
- package/src/config/bundled-skills/schedule/TOOLS.json +2 -2
- package/src/config/bundled-skills/settings/TOOLS.json +5 -3
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +84 -10
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +0 -7
- package/src/config/call-site-defaults.ts +3 -3
- package/src/config/feature-flag-registry.json +15 -63
- package/src/config/llm-resolver.ts +88 -475
- package/src/config/managed-speech-defaults.ts +115 -0
- package/src/config/platform-rehydration.ts +76 -0
- package/src/config/profile-materialization.ts +11 -11
- package/src/config/schema.ts +93 -129
- package/src/config/schemas/__tests__/live-voice.test.ts +24 -6
- package/src/config/schemas/__tests__/stt.test.ts +37 -0
- package/src/config/schemas/live-voice.ts +10 -4
- package/src/config/schemas/llm.ts +51 -15
- package/src/config/schemas/memory-lifecycle.ts +1 -13
- package/src/config/schemas/memory-retrospective.ts +8 -0
- package/src/config/schemas/memory.ts +0 -4
- package/src/config/schemas/stt.ts +33 -6
- package/src/config/schemas/tts.ts +53 -6
- package/src/config/schemas/workspace-git.ts +8 -0
- package/src/contacts/contact-store.ts +3 -58
- package/src/contacts/types.ts +1 -1
- package/src/conversations/__tests__/message-consolidation.test.ts +6 -5
- package/src/conversations/message-consolidation.ts +34 -112
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +64 -7
- package/src/daemon/__tests__/conversation-tool-setup-plugin-scope.test.ts +3 -7
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +8 -6
- package/src/daemon/__tests__/embedding-reconcile.test.ts +0 -11
- package/src/daemon/__tests__/inference-profile-notification.test.ts +5 -11
- package/src/daemon/__tests__/inflight-message-content.test.ts +219 -0
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +5 -27
- package/src/daemon/__tests__/route-conversation-post.test.ts +158 -0
- package/src/daemon/__tests__/wake-conversation-ops-completion.test.ts +0 -6
- package/src/daemon/__tests__/web-search-status-text.test.ts +0 -29
- package/src/daemon/app-source-watcher.ts +17 -23
- package/src/daemon/chat-credential-redaction.ts +1365 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +742 -77
- package/src/daemon/conversation-agent-loop.ts +10 -17
- package/src/daemon/conversation-error.ts +53 -16
- package/src/daemon/conversation-history.ts +6 -12
- package/src/daemon/conversation-messaging.ts +13 -1
- package/src/daemon/conversation-process.ts +16 -11
- package/src/daemon/conversation-runtime-assembly.ts +148 -52
- package/src/daemon/conversation-surfaces.ts +217 -100
- package/src/daemon/conversation-tool-setup.ts +59 -112
- package/src/daemon/conversation-turn-finalize.ts +18 -0
- package/src/daemon/conversation.ts +35 -66
- package/src/daemon/event-loop-watchdog.test.ts +1 -6
- package/src/daemon/external-plugins-bootstrap.ts +20 -74
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +0 -7
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +1 -8
- package/src/daemon/handlers/__tests__/config-a2a-invite.test.ts +1 -8
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +1 -8
- package/src/daemon/handlers/__tests__/config-a2a.test.ts +1 -8
- package/src/daemon/handlers/conversation-history.ts +6 -4
- package/src/daemon/handlers/conversations.ts +19 -9
- package/src/daemon/handlers/shared.ts +24 -1
- package/src/daemon/inflight-message-content.ts +228 -0
- package/src/daemon/lifecycle.ts +21 -31
- package/src/daemon/message-protocol.ts +2 -7
- package/src/daemon/message-provenance.ts +17 -8
- package/src/daemon/message-types/conversations.ts +6 -17
- package/src/daemon/message-types/host-ui-snapshot.ts +44 -0
- package/src/daemon/message-types/inbox.ts +3 -46
- package/src/daemon/orphan-reaper.test.ts +1 -6
- package/src/daemon/process-message.ts +9 -0
- package/src/daemon/providers-setup.ts +5 -75
- package/src/daemon/route-conversation-post.ts +158 -0
- package/src/daemon/shutdown-handlers.ts +11 -17
- package/src/daemon/sqlite-corruption-watchdog.test.ts +0 -6
- package/src/documents/document-comments-store.test.ts +1 -7
- package/src/export/__tests__/transcript-formatter.test.ts +8 -8
- package/src/export/formatter.ts +8 -17
- package/src/export/transcript-formatter.ts +4 -1
- package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +0 -9
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +29 -57
- package/src/home/__tests__/home-content-refresh.test.ts +0 -7
- package/src/home/__tests__/suggested-prompts.test.ts +0 -11
- package/src/ipc/__tests__/contacts-info-ipc.test.ts +12 -10
- package/src/ipc/__tests__/email-ipc.test.ts +90 -0
- package/src/ipc/assistant-server.ts +10 -22
- package/src/ipc/routes/__tests__/guardian-label-ipc-routes.test.ts +74 -0
- package/src/ipc/routes/__tests__/invite-ipc-routes.test.ts +0 -7
- package/src/ipc/routes/guardian-label-ipc-routes.ts +42 -0
- package/src/live-voice/__tests__/live-voice-archive.test.ts +1 -8
- package/src/live-voice/__tests__/live-voice-credential-preflight.test.ts +89 -49
- package/src/live-voice/__tests__/live-voice-integration.test.ts +116 -2
- package/src/live-voice/__tests__/live-voice-resume-registry.test.ts +58 -0
- package/src/live-voice/__tests__/live-voice-resume-turn.test.ts +280 -0
- package/src/live-voice/__tests__/live-voice-triage-escalate.test.ts +337 -0
- package/src/live-voice/__tests__/live-voice-tts.test.ts +0 -4
- package/src/live-voice/__tests__/live-voice-vad.test.ts +432 -12
- package/src/live-voice/__tests__/protocol.test.ts +122 -0
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +0 -41
- package/src/live-voice/live-voice-credential-preflight.ts +27 -3
- package/src/live-voice/live-voice-resume-registry.ts +54 -0
- package/src/live-voice/live-voice-session.ts +602 -61
- package/src/live-voice/protocol.ts +143 -1
- package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +3 -7
- package/src/messaging/provider-types.ts +9 -0
- package/src/messaging/providers/a2a/__tests__/deliver.test.ts +0 -9
- package/src/messaging/providers/outlook/adapter.ts +17 -2
- package/src/messaging/providers/outlook/client.ts +11 -2
- package/src/messaging/providers/outlook/types.ts +9 -0
- package/src/messaging/providers/slack/__tests__/download.test.ts +1 -8
- package/src/messaging/providers/slack/binding-metadata.test.ts +23 -21
- package/src/messaging/providers/slack/send.test.ts +0 -7
- package/src/messaging/providers/slack/withdraw.test.ts +0 -6
- package/src/messaging/providers/telegram-bot/send.test.ts +0 -7
- package/src/monitoring/__tests__/plugin-source-watch.test.ts +40 -1
- package/src/monitoring/plugin-source-watch.ts +56 -62
- package/src/monitoring/recovery/__tests__/inflight-content.test.ts +166 -0
- package/src/monitoring/recovery/inflight-content.ts +260 -0
- package/src/monitoring/recovery/run-recovery.ts +72 -0
- package/src/monitoring/worker.ts +68 -7
- package/src/notifications/AGENTS.md +1 -1
- package/src/notifications/README.md +4 -4
- package/src/notifications/__tests__/broadcaster.test.ts +4 -17
- package/src/notifications/__tests__/connected-channels.test.ts +11 -8
- package/src/notifications/__tests__/decision-engine.test.ts +0 -7
- package/src/notifications/__tests__/destination-resolver.test.ts +18 -12
- package/src/notifications/__tests__/deterministic-checks.test.ts +1 -9
- package/src/notifications/adapters/macos.ts +3 -5
- package/src/notifications/adapters/platform.ts +1 -1
- package/src/notifications/broadcaster.ts +13 -4
- package/src/notifications/conversation-candidates.ts +21 -28
- package/src/notifications/copy-composer.ts +0 -6
- package/src/notifications/decision-engine.ts +1 -1
- package/src/notifications/{canonical-delivery-recorder.ts → guardian-delivery-recorder.ts} +47 -33
- package/src/notifications/home-feed-side-effect.ts +0 -2
- package/src/notifications/signal.ts +0 -4
- package/src/oauth/byo-connection.test.ts +0 -9
- package/src/oauth/connection-resolver.test.ts +18 -46
- package/src/oauth/seed-providers.ts +6 -0
- package/src/onboarding/__tests__/onboarding-events-store.test.ts +122 -44
- package/src/onboarding/onboarding-events-store.ts +67 -115
- package/src/onboarding/onboarding-research-events-store.test.ts +222 -0
- package/src/onboarding/onboarding-research-events-store.ts +92 -0
- package/src/permissions/checker.test.ts +10 -24
- package/src/permissions/confirmation-guardian-request.test.ts +94 -0
- package/src/permissions/{confirmation-canonical-request.ts → confirmation-guardian-request.ts} +44 -29
- package/src/permissions/gateway-threshold-reader.test.ts +0 -8
- package/src/permissions/prompter.ts +6 -4
- package/src/permissions/question-prompter.test.ts +7 -14
- package/src/persistence/__tests__/bulk-write-gate.test.ts +1 -7
- package/src/persistence/__tests__/conversation-queries-search.test.ts +0 -7
- package/src/persistence/__tests__/main-db-readonly-probe.ts +80 -0
- package/src/persistence/__tests__/main-db-readonly.test.ts +35 -0
- package/src/persistence/__tests__/message-content-file.test.ts +161 -52
- package/src/persistence/__tests__/raw-query-telemetry.test.ts +74 -0
- package/src/persistence/conversation-crud.ts +175 -45
- package/src/persistence/conversation-disk-view.ts +32 -15
- package/src/persistence/conversation-group-migration.test.ts +1 -8
- package/src/persistence/conversation-title-service.ts +59 -22
- package/src/persistence/db-connection.ts +46 -1
- package/src/persistence/db-singleton.ts +7 -1
- package/src/persistence/embeddings/__tests__/messages-lexical-index.test.ts +3 -7
- package/src/persistence/embeddings/messages-lexical-index.ts +11 -0
- package/src/persistence/job-handlers/__tests__/message-lexical-backfill.test.ts +0 -7
- package/src/persistence/job-handlers/__tests__/message-lexical-enqueue.test.ts +0 -6
- package/src/persistence/job-handlers/__tests__/message-lexical.test.ts +0 -7
- package/src/persistence/job-handlers/cleanup.ts +30 -16
- package/src/persistence/job-handlers/message-lexical-backfill.ts +8 -5
- package/src/persistence/job-handlers/message-lexical.ts +2 -2
- package/src/persistence/jobs-store.ts +123 -17
- package/src/persistence/lifecycle-events-store.test.ts +84 -0
- package/src/persistence/lifecycle-events-store.ts +27 -52
- package/src/persistence/llm-request-log-sink-clickhouse.ts +325 -0
- package/src/persistence/llm-request-log-store.ts +185 -106
- package/src/persistence/llm-request-log-writer-types.ts +80 -0
- package/src/persistence/llm-usage-store.ts +5 -2
- package/src/persistence/message-content-file.ts +182 -71
- package/src/persistence/message-content.ts +18 -10
- package/src/persistence/migrations/305-drop-contact-acl-columns.ts +3 -2
- package/src/persistence/migrations/325-create-config-setting-events.ts +40 -0
- package/src/persistence/migrations/326-move-injection-events-to-memory-db.ts +104 -0
- package/src/persistence/migrations/327-create-flush-checkpoints.ts +86 -0
- package/src/persistence/migrations/328-drop-memory-v3-learned-edge-tables.ts +16 -0
- package/src/persistence/migrations/329-move-onboarding-events-to-telemetry-db.test.ts +179 -0
- package/src/persistence/migrations/329-move-onboarding-events-to-telemetry-db.ts +119 -0
- package/src/persistence/migrations/330-move-auth-fallback-events-to-telemetry-db.test.ts +197 -0
- package/src/persistence/migrations/330-move-auth-fallback-events-to-telemetry-db.ts +108 -0
- package/src/persistence/migrations/331-move-lifecycle-events-to-telemetry-db.test.ts +159 -0
- package/src/persistence/migrations/331-move-lifecycle-events-to-telemetry-db.ts +97 -0
- package/src/persistence/migrations/332-move-skill-loaded-events-to-telemetry-db.test.ts +219 -0
- package/src/persistence/migrations/332-move-skill-loaded-events-to-telemetry-db.ts +128 -0
- package/src/persistence/migrations/333-create-telemetry-events-table.test.ts +66 -0
- package/src/persistence/migrations/333-create-telemetry-events-table.ts +43 -0
- package/src/persistence/migrations/334-backfill-telemetry-events-outbox.test.ts +584 -0
- package/src/persistence/migrations/334-backfill-telemetry-events-outbox.ts +386 -0
- package/src/persistence/migrations/335-collapse-memory-embed-backlog.test.ts +181 -0
- package/src/persistence/migrations/335-collapse-memory-embed-backlog.ts +177 -0
- package/src/persistence/migrations/__tests__/327-create-flush-checkpoints.test.ts +124 -0
- package/src/persistence/raw-query.ts +27 -1
- package/src/persistence/schema/calls.ts +0 -23
- package/src/persistence/schema/conversation-starters.ts +31 -0
- package/src/persistence/schema/conversations.ts +3 -3
- package/src/persistence/schema/guardian.ts +0 -150
- package/src/persistence/schema/index.ts +1 -0
- package/src/persistence/schema/infrastructure.ts +25 -72
- package/src/persistence/schema/memory-core.ts +0 -25
- package/src/persistence/schema/memory-injection.ts +3 -1
- package/src/persistence/schema/tasks.ts +1 -60
- package/src/persistence/steps.ts +22 -0
- package/src/platform/client.test.ts +110 -0
- package/src/platform/client.ts +24 -4
- package/src/platform/consent-cache.test.ts +5 -18
- package/src/platform/consent-cache.ts +8 -6
- package/src/platform/managed-speech.test.ts +218 -0
- package/src/platform/managed-speech.ts +204 -0
- package/src/plugin-api/conversation-turn.ts +250 -0
- package/src/plugin-api/index.ts +21 -0
- package/src/plugin-api/model-profiles.test.ts +29 -28
- package/src/plugin-api/vision-support.test.ts +25 -38
- package/src/plugin-api/vision-support.ts +26 -17
- package/src/plugins/AGENTS.md +8 -0
- package/src/plugins/__tests__/source-fingerprint.test.ts +41 -0
- package/src/plugins/collect-source-versions.ts +77 -0
- package/src/plugins/defaults/image-recovery/detect.ts +32 -10
- package/src/plugins/defaults/image-recovery/hooks/post-model-call.ts +20 -18
- package/src/plugins/defaults/image-recovery/recover.ts +86 -59
- package/src/plugins/defaults/memory/__tests__/activation-session-store.test.ts +1 -8
- package/src/plugins/defaults/memory/__tests__/clear-stale-processing-flags.test.ts +1 -8
- package/src/plugins/defaults/memory/__tests__/conversation-queries.test.ts +1 -8
- package/src/plugins/defaults/memory/__tests__/conversation-row-batch-delete.test.ts +7 -18
- package/src/plugins/defaults/memory/__tests__/db-memory-attach.test.ts +22 -18
- package/src/plugins/defaults/memory/__tests__/embedding-cache.test.ts +0 -6
- package/src/plugins/defaults/memory/__tests__/find-most-recent-retrospective-for.test.ts +1 -8
- package/src/plugins/defaults/memory/__tests__/fork-message-copy.test.ts +7 -18
- package/src/plugins/defaults/memory/__tests__/jobs-store-enqueue-gate.test.ts +29 -39
- package/src/plugins/defaults/memory/__tests__/jobs-worker-memory-disabled.test.ts +11 -26
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +3 -22
- package/src/plugins/defaults/memory/__tests__/jobs-worker-v2-schedule.test.ts +215 -1
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-enqueue.test.ts +0 -7
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +114 -16
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +180 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-skill-card.test.ts +153 -519
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +0 -7
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-state.test.ts +6 -17
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-trigger-check.test.ts +0 -7
- package/src/plugins/defaults/memory/__tests__/memory-v2-activation-log-store.test.ts +1 -19
- package/src/plugins/defaults/memory/__tests__/memory-v2-concept-frequency.test.ts +0 -18
- package/src/plugins/defaults/memory/__tests__/shutdown-hook.test.ts +8 -7
- package/src/plugins/defaults/memory/__tests__/table-relocation.test.ts +49 -0
- package/src/{persistence → plugins/defaults/memory}/__tests__/worker-control.test.ts +8 -10
- package/src/plugins/defaults/memory/graph/capability-seed.ts +4 -6
- package/src/plugins/defaults/memory/graph/extraction.ts +5 -1
- package/src/plugins/defaults/memory/graph/graph-search.test.ts +2 -8
- package/src/plugins/defaults/memory/graph/tool-handlers.test.ts +0 -6
- package/src/plugins/defaults/memory/graph/tool-handlers.ts +2 -2
- package/src/plugins/defaults/memory/graph/tools.ts +47 -13
- package/src/plugins/defaults/memory/graph-topology/__tests__/build-memory-graph.test.ts +81 -2
- package/src/plugins/defaults/memory/graph-topology/build-memory-graph.ts +67 -32
- package/src/plugins/defaults/memory/hooks/shutdown.ts +8 -11
- package/src/plugins/defaults/memory/indexer.ts +2 -1
- package/src/plugins/defaults/memory/job-handlers/backfill.ts +8 -5
- package/src/plugins/defaults/memory/job-handlers/embedding.test.ts +0 -7
- package/src/plugins/defaults/memory/job-handlers/embedding.ts +2 -2
- package/src/plugins/defaults/memory/job-handlers/index-maintenance.ts +7 -2
- package/src/plugins/defaults/memory/jobs/__tests__/embed-concept-page.test.ts +73 -8
- package/src/plugins/defaults/memory/jobs/embed-concept-page.ts +5 -3
- package/src/plugins/defaults/memory/jobs/embed-pkb-file.test.ts +0 -13
- package/src/plugins/defaults/memory/jobs-worker.ts +139 -107
- package/src/plugins/defaults/memory/memory-db.ts +27 -0
- package/src/plugins/defaults/memory/memory-retrospective-constants.ts +4 -4
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +56 -180
- package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +216 -0
- package/src/plugins/defaults/memory/memory-retrospective-skill-card.ts +122 -202
- package/src/plugins/defaults/memory/message-media.ts +2 -2
- package/src/plugins/defaults/memory/paths.ts +3 -2
- package/src/plugins/defaults/memory/pkb/pkb-index.test.ts +0 -12
- package/src/plugins/defaults/memory/pkb/pkb-reconcile.test.ts +0 -9
- package/src/plugins/defaults/memory/pkb/pkb-search.test.ts +0 -6
- package/src/plugins/defaults/memory/routes/__tests__/memory-v2-simulate-route.test.ts +15 -92
- package/src/plugins/defaults/memory/routes/__tests__/memory-worker-routes.test.ts +201 -0
- package/src/plugins/defaults/memory/routes/memory-item-routes.test.ts +7 -21
- package/src/plugins/defaults/memory/routes/memory-v2-routes.ts +3 -8
- package/src/plugins/defaults/memory/routes/memory-worker-routes.ts +162 -0
- package/src/plugins/defaults/memory/startup.ts +6 -7
- package/src/plugins/defaults/memory/task-memory-cleanup.ts +11 -22
- package/src/plugins/defaults/memory/tools.test.ts +40 -8
- package/src/plugins/defaults/memory/tools.ts +12 -2
- package/src/plugins/defaults/memory/v2/__tests__/activation.test.ts +0 -19
- package/src/plugins/defaults/memory/v2/__tests__/backfill-jobs.test.ts +63 -40
- package/src/plugins/defaults/memory/v2/__tests__/cli-command-store.test.ts +61 -130
- package/src/plugins/defaults/memory/v2/__tests__/consolidation-job.test.ts +406 -10
- package/src/plugins/defaults/memory/v2/__tests__/harness-compare.test.ts +1 -10
- package/src/plugins/defaults/memory/v2/__tests__/harness-oracle.test.ts +1 -10
- package/src/plugins/defaults/memory/v2/__tests__/harness-replay-input.test.ts +1 -10
- package/src/plugins/defaults/memory/v2/__tests__/injection-events.test.ts +61 -69
- package/src/plugins/defaults/memory/v2/__tests__/injection.test.ts +0 -19
- package/src/plugins/defaults/memory/v2/__tests__/migration.test.ts +11 -10
- package/src/plugins/defaults/memory/v2/__tests__/page-index.test.ts +0 -5
- package/src/plugins/defaults/memory/v2/__tests__/qdrant.test.ts +6 -22
- package/src/plugins/defaults/memory/v2/__tests__/reranker.test.ts +3 -5
- package/src/plugins/defaults/memory/v2/__tests__/router.test.ts +7 -20
- package/src/plugins/defaults/memory/v2/__tests__/sim.test.ts +0 -24
- package/src/plugins/defaults/memory/v2/__tests__/skill-content.test.ts +17 -11
- package/src/plugins/defaults/memory/v2/__tests__/skill-store.test.ts +0 -16
- package/src/plugins/defaults/memory/v2/__tests__/static-context.test.ts +0 -10
- package/src/plugins/defaults/memory/v2/__tests__/sweep-job.test.ts +0 -6
- package/src/plugins/defaults/memory/v2/backfill-jobs.ts +5 -2
- package/src/plugins/defaults/memory/v2/cli-command-content.ts +43 -12
- package/src/plugins/defaults/memory/v2/cli-command-store.ts +34 -50
- package/src/plugins/defaults/memory/v2/consolidation-job.ts +216 -10
- package/src/plugins/defaults/memory/v2/harness/router-retriever.ts +1 -8
- package/src/plugins/defaults/memory/v2/injection-events.ts +16 -14
- package/src/plugins/defaults/memory/v2/injection.ts +1 -2
- package/src/plugins/defaults/memory/v2/memory-v2-startup.test.ts +0 -5
- package/src/plugins/defaults/memory/v2/migration.ts +55 -24
- package/src/plugins/defaults/memory/v2/prompts/consolidation.ts +4 -0
- package/src/plugins/defaults/memory/v2/router.ts +4 -14
- package/src/plugins/defaults/memory/v2/sweep-job.ts +1 -0
- package/src/plugins/defaults/memory/v3/__tests__/carry-integration.test.ts +10 -22
- package/src/plugins/defaults/memory/v3/__tests__/dense.test.ts +0 -5
- package/src/plugins/defaults/memory/v3/__tests__/injection.test.ts +18 -20
- package/src/plugins/defaults/memory/v3/__tests__/section-dense-store.test.ts +0 -5
- package/src/plugins/defaults/memory/v3/__tests__/selection-log-store.test.ts +5 -9
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +51 -31
- package/src/plugins/defaults/memory/v3/prune.test.ts +3 -11
- package/src/{persistence → plugins/defaults/memory}/worker-control.ts +12 -21
- package/src/plugins/defaults/memory/worker.ts +19 -2
- package/src/plugins/mtime-cache.ts +166 -70
- package/src/plugins/plugin-tree-walk.ts +41 -4
- package/src/plugins/source-fingerprint.ts +9 -3
- package/src/plugins/surface-import.ts +28 -0
- package/src/plugins/types.ts +9 -23
- package/src/prompts/__tests__/system-prompt.test.ts +0 -28
- package/src/prompts/__tests__/task-progress-hint-section.test.ts +0 -28
- package/src/providers/__tests__/connection-model-compat.test.ts +6 -19
- package/src/providers/__tests__/count-tokens-forwarding.test.ts +1 -21
- package/src/providers/__tests__/dispatch-connection-routing.test.ts +9 -26
- package/src/providers/__tests__/registry-native-web-search.test.ts +4 -10
- package/src/providers/__tests__/retry-callsite.test.ts +240 -235
- package/src/providers/__tests__/satellite-connection-routing.test.ts +11 -36
- package/src/providers/__tests__/vellum-mismatch-routing.test.ts +0 -5
- package/src/providers/anthropic/client.ts +9 -3
- package/src/providers/call-site-routing.ts +7 -3
- package/src/providers/connection-resolution.ts +9 -11
- package/src/providers/content-block-schema.ts +149 -0
- package/src/providers/inference/__tests__/base-url-route-validation.test.ts +7 -11
- package/src/providers/inference/__tests__/codex-token-refresh.test.ts +1 -15
- package/src/providers/inference/auth.ts +23 -0
- package/src/providers/inference/backfill.ts +25 -9
- package/src/providers/model-catalog.ts +213 -5
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +54 -0
- package/src/providers/openai/chat-completions-provider.ts +13 -2
- package/src/providers/openai/responses-provider.ts +232 -5
- package/src/providers/openrouter/client.ts +53 -0
- package/src/providers/retry.ts +25 -2
- package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +13 -0
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +211 -74
- package/src/providers/speech-to-text/__tests__/vellum-managed-realtime.test.ts +408 -0
- package/src/providers/speech-to-text/__tests__/vellum-managed.test.ts +121 -0
- package/src/providers/speech-to-text/__tests__/vellum-speech-relay-connection.test.ts +126 -0
- package/src/providers/speech-to-text/deepgram-realtime.ts +167 -37
- package/src/providers/speech-to-text/incremental-batch-stream.ts +413 -0
- package/src/providers/speech-to-text/openai-whisper-stream.ts +16 -363
- package/src/providers/speech-to-text/provider-catalog.ts +26 -1
- package/src/providers/speech-to-text/resolve.ts +74 -13
- package/src/providers/speech-to-text/vellum-managed-realtime.ts +309 -0
- package/src/providers/speech-to-text/vellum-managed.ts +71 -0
- package/src/providers/speech-to-text/vellum-speech-relay-connection.ts +174 -0
- package/src/providers/types.ts +23 -4
- package/src/providers/vellum-model-routing.test.ts +26 -0
- package/src/providers/vellum-model-routing.ts +30 -0
- package/src/runtime/AGENTS.md +1 -1
- package/src/runtime/__tests__/actor-trust-resolver.test.ts +2 -8
- package/src/runtime/__tests__/agent-wake.test.ts +100 -27
- package/src/runtime/__tests__/background-job-runner.test.ts +22 -0
- package/src/runtime/__tests__/guardian-vellum-migration.test.ts +0 -5
- package/src/runtime/__tests__/member-verdict-cache.test.ts +2 -9
- package/src/runtime/__tests__/trust-verdict-consumer.test.ts +22 -5
- package/src/runtime/access-request-helper.ts +84 -60
- package/src/runtime/actor-trust-resolver.ts +2 -2
- package/src/runtime/agent-wake.ts +75 -26
- package/src/runtime/assistant-event-hub.ts +1 -0
- package/src/runtime/auth/__tests__/middleware.test.ts +1 -10
- package/src/runtime/auth/__tests__/route-policy.test.ts +0 -7
- package/src/runtime/auth/__tests__/token-service.test.ts +1 -8
- package/src/runtime/auth/same-actor.ts +2 -1
- package/src/runtime/background-job-runner.ts +22 -0
- package/src/runtime/channel-approval-types.ts +1 -1
- package/src/runtime/channel-reply-delivery.ts +38 -19
- package/src/runtime/confirmation-request-guardian-bridge.ts +45 -39
- package/src/runtime/for-chat-mint-registry.ts +118 -0
- package/src/runtime/guardian-action-service.ts +32 -27
- package/src/runtime/guardian-decision-types.ts +2 -2
- package/src/runtime/guardian-reply-router.ts +80 -98
- package/src/runtime/http-server.ts +61 -41
- package/src/runtime/introduction-policy.ts +2 -2
- package/src/runtime/local-actor-identity.ts +19 -7
- package/src/runtime/pending-interactions.ts +1 -0
- package/src/runtime/reveal-nonce.ts +49 -0
- package/src/runtime/reveal-success-registry.ts +306 -0
- package/src/runtime/routes/__tests__/acp-routes.test.ts +0 -7
- package/src/runtime/routes/__tests__/backup-routes.test.ts +195 -125
- package/src/runtime/routes/__tests__/channel-verification-routes.test.ts +4 -1
- package/src/runtime/routes/__tests__/client-routes.test.ts +0 -7
- package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +1 -19
- package/src/runtime/routes/__tests__/consolidation-routes.test.ts +1 -8
- package/src/runtime/routes/__tests__/contact-routes-merge-relay.test.ts +186 -0
- package/src/runtime/routes/__tests__/contact-routes-update-channel-relay.test.ts +2 -3
- package/src/runtime/routes/__tests__/content-source-routes.test.ts +0 -7
- package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +5 -27
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +0 -7
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +12 -30
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +59 -56
- package/src/runtime/routes/__tests__/conversation-surface-routes.test.ts +0 -7
- package/src/runtime/routes/__tests__/default-provider-routes.test.ts +53 -73
- package/src/runtime/routes/__tests__/gateway-status-routes.test.ts +84 -0
- package/src/runtime/routes/__tests__/inference-callsites-routes.test.ts +2 -10
- package/src/runtime/routes/__tests__/inference-profiles-routes.test.ts +58 -90
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +161 -93
- package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +6 -1
- package/src/runtime/routes/__tests__/monitoring-routes.test.ts +0 -8
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +218 -64
- package/src/runtime/routes/__tests__/question-routes.test.ts +2 -4
- package/src/runtime/routes/__tests__/retrospective-routes.test.ts +1 -8
- package/src/runtime/routes/__tests__/sanity-routes.test.ts +0 -7
- package/src/runtime/routes/__tests__/schedule-routes-create.test.ts +2 -1
- package/src/runtime/routes/__tests__/schedule-worker-routes.test.ts +16 -56
- package/src/runtime/routes/__tests__/stt-routes.test.ts +0 -9
- package/src/runtime/routes/__tests__/suggest-trust-rule-routes.test.ts +0 -7
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +5 -0
- package/src/runtime/routes/__tests__/surface-content-routes.test.ts +354 -1
- package/src/runtime/routes/__tests__/tts-routes.test.ts +0 -11
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +163 -10
- package/src/runtime/routes/__tests__/user-routes-cli.test.ts +154 -0
- package/src/runtime/routes/__tests__/wake-conversation-routes.test.ts +0 -7
- package/src/runtime/routes/acp-routes.ts +21 -9
- package/src/runtime/routes/app-management-routes.ts +231 -60
- package/src/runtime/routes/app-routes.ts +130 -83
- package/src/runtime/routes/auth-routes.ts +3 -1
- package/src/runtime/routes/background-wake-routes.ts +0 -1
- package/src/runtime/routes/cache-routes.ts +3 -3
- package/src/runtime/routes/call-routes.ts +5 -1
- package/src/runtime/routes/channel-verification-routes.ts +2 -1
- package/src/runtime/routes/contact-prompt-routes.ts +11 -5
- package/src/runtime/routes/contact-routes.ts +34 -42
- package/src/runtime/routes/conversation-attention-routes.ts +1 -1
- package/src/runtime/routes/conversation-cli-routes.ts +1 -1
- package/src/runtime/routes/conversation-query-routes.ts +4 -4
- package/src/runtime/routes/conversation-routes.ts +111 -72
- package/src/runtime/routes/credential-routes.ts +116 -3
- package/src/runtime/routes/email-routes.ts +17 -1
- package/src/runtime/routes/events-routes.ts +1 -0
- package/src/runtime/routes/gateway-status-routes.ts +69 -0
- package/src/runtime/routes/guardian-action-routes.ts +18 -16
- package/src/runtime/routes/guardian-approval-interception.ts +6 -4
- package/src/runtime/routes/guardian-approval-prompt.ts +7 -5
- package/src/runtime/routes/guardian-expiry-sweep.ts +130 -0
- package/src/runtime/routes/inbound-message-handler.ts +9 -33
- package/src/runtime/routes/inbound-stages/acl-enforcement.test.ts +0 -5
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +9 -9
- package/src/runtime/routes/inbound-stages/admission-policy.test.ts +24 -6
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +0 -7
- package/src/runtime/routes/inbound-stages/bootstrap-intercept.test.ts +0 -5
- package/src/runtime/routes/inbound-stages/bootstrap-intercept.ts +6 -3
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +5 -1
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.test.ts +0 -9
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +4 -1
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +3 -12
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +16 -14
- package/src/runtime/routes/inbound-stages/reaction-intercept.test.ts +8 -2
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +15 -7
- package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +0 -9
- package/src/runtime/routes/index.ts +5 -5
- package/src/runtime/routes/inference-provider-connection-routes.ts +73 -24
- package/src/runtime/routes/inference-send-routes.ts +1 -1
- package/src/runtime/routes/internal-telemetry-routes.ts +11 -2
- package/src/runtime/routes/oauth-connect-routes.ts +27 -7
- package/src/runtime/routes/platform-routes.ts +4 -14
- package/src/runtime/routes/playground/__tests__/force-compact.test.ts +0 -4
- package/src/runtime/routes/playground/__tests__/guard.test.ts +0 -4
- package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +0 -14
- package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +0 -21
- package/src/runtime/routes/playground/__tests__/seed-conversation.test.ts +0 -4
- package/src/runtime/routes/playground/__tests__/seeded-conversations.test.ts +16 -18
- package/src/runtime/routes/playground/__tests__/state.test.ts +0 -14
- package/src/runtime/routes/playground/seed-conversation.ts +5 -4
- package/src/runtime/routes/playground/seeded-conversations.ts +3 -2
- package/src/runtime/routes/plugins-routes.ts +163 -25
- package/src/runtime/routes/profiler-routes.ts +2 -5
- package/src/runtime/routes/publish-routes.ts +15 -18
- package/src/runtime/routes/question-routes.ts +8 -4
- package/src/runtime/routes/schedule-routes.ts +20 -78
- package/src/runtime/routes/schedule-worker-routes.ts +16 -84
- package/src/runtime/routes/secret-routes.ts +14 -0
- package/src/runtime/routes/settings-routes.ts +21 -25
- package/src/runtime/routes/subagents-routes.ts +17 -18
- package/src/runtime/routes/surface-action-routes.ts +18 -39
- package/src/runtime/routes/surface-content-routes.ts +59 -1
- package/src/runtime/routes/surface-conversation-resolver.ts +148 -4
- package/src/runtime/routes/telemetry-routes.ts +74 -1
- package/src/runtime/routes/tts-routes.ts +9 -5
- package/src/runtime/routes/ui-snapshot-routes.test.ts +219 -0
- package/src/runtime/routes/ui-snapshot-routes.ts +313 -0
- package/src/runtime/routes/user-route-dispatcher.ts +52 -53
- package/src/runtime/routes/user-route-resolution.ts +141 -0
- package/src/runtime/routes/user-routes-cli.ts +56 -35
- package/src/runtime/routes/user-routes.ts +9 -2
- package/src/runtime/routes/vellum-actor-trust.ts +67 -0
- package/src/runtime/services/__tests__/auto-analysis-guard.test.ts +1 -8
- package/src/runtime/tool-grant-request-helper.ts +34 -30
- package/src/runtime/trust-verdict-consumer.ts +4 -6
- package/src/schedule/__tests__/worker-control.test.ts +3 -3
- package/src/schedule/schedule-store.ts +0 -41
- package/src/schedule/scheduler.ts +38 -257
- package/src/schedule/worker-control.ts +11 -21
- package/src/schedule/worker.ts +18 -5
- package/src/security/__tests__/oauth2-device-code.test.ts +12 -60
- package/src/security/__tests__/provider-key-env-fallback.test.ts +0 -10
- package/src/security/auth-fallback-events-store.ts +34 -72
- package/src/security/secret-scanner.ts +26 -1
- package/src/sequence/engine.ts +15 -6
- package/src/services/published-app-updater.ts +6 -11
- package/src/stt/__tests__/daemon-batch-transcriber.test.ts +24 -4
- package/src/stt/daemon-batch-transcriber.ts +33 -2
- package/src/stt/stt-stream-session.ts +17 -11
- package/src/stt/types.ts +2 -1
- package/src/subagent/manager.ts +4 -3
- package/src/telemetry/AGENTS.md +44 -0
- package/src/telemetry/__tests__/config-setting-events-store.test.ts +63 -0
- package/src/telemetry/__tests__/config-setting-snapshot.test.ts +107 -0
- package/src/telemetry/__tests__/flush-checkpoints.test.ts +56 -0
- package/src/telemetry/__tests__/outbox-test-harness.ts +83 -0
- package/src/telemetry/__tests__/telemetry-event-fixtures.ts +258 -0
- package/src/telemetry/__tests__/watchdog-events-store.test.ts +32 -122
- package/src/telemetry/config-setting-events-store.ts +40 -0
- package/src/telemetry/config-setting-snapshot.ts +135 -0
- package/src/telemetry/flush-checkpoints.ts +70 -0
- package/src/telemetry/skill-loaded-events-store.test.ts +54 -113
- package/src/telemetry/skill-loaded-events-store.ts +21 -77
- package/src/telemetry/telemetry-event-sources.test.ts +211 -0
- package/src/telemetry/telemetry-event-sources.ts +582 -0
- package/src/telemetry/telemetry-events-outbox.test.ts +330 -0
- package/src/telemetry/telemetry-events-outbox.ts +204 -0
- package/src/telemetry/telemetry-main-db.ts +48 -0
- package/src/telemetry/telemetry-wire-source.json +4 -0
- package/src/telemetry/telemetry-wire-validation.test.ts +157 -0
- package/src/telemetry/telemetry-wire-validation.ts +125 -0
- package/src/telemetry/telemetry-wire.generated.ts +433 -0
- package/src/telemetry/tool-executed-events-store.test.ts +0 -8
- package/src/telemetry/tool-executed-events-store.ts +2 -2
- package/src/telemetry/turn-trace-store.test.ts +86 -7
- package/src/telemetry/turn-trace-store.ts +29 -1
- package/src/telemetry/types.test.ts +38 -0
- package/src/telemetry/types.ts +302 -87
- package/src/telemetry/usage-telemetry-reporter.test.ts +921 -364
- package/src/telemetry/usage-telemetry-reporter.ts +235 -722
- package/src/telemetry/watchdog-direct-emit.test.ts +0 -5
- package/src/telemetry/watchdog-direct-emit.ts +7 -1
- package/src/telemetry/watchdog-events-store.ts +11 -70
- package/src/tools/acp/spawn.test.ts +0 -7
- package/src/tools/apps/definitions.ts +1 -7
- package/src/tools/apps/executors.ts +11 -36
- package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +11 -24
- package/src/tools/browser/__tests__/browser-status.test.ts +47 -33
- package/src/tools/browser/cdp-client/__tests__/cdp-inspect-client.test.ts +1 -11
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +75 -58
- package/src/tools/browser/cdp-client/__tests__/local-cdp-client.test.ts +0 -10
- package/src/tools/browser/network-recorder.test.ts +0 -11
- package/src/tools/document/document-comment-tool.test.ts +1 -7
- package/src/tools/host-terminal/host-shell.test.ts +0 -32
- package/src/tools/host-terminal/host-shell.ts +6 -2
- package/src/tools/network/__tests__/web-fetch-firecrawl.test.ts +13 -15
- package/src/tools/network/__tests__/web-search-metadata.test.ts +15 -18
- package/src/tools/network/__tests__/web-search.test.ts +39 -50
- package/src/tools/registry.ts +148 -196
- package/src/tools/skills/find-similar-skills.test.ts +0 -7
- package/src/tools/skills/sandbox-runner.ts +5 -2
- package/src/tools/skills/scaffold-managed.ts +105 -12
- package/src/tools/subagent/read.ts +6 -4
- package/src/tools/subagent/spawn.ts +20 -29
- package/src/tools/terminal/safe-env.ts +7 -2
- package/src/tools/terminal/shell.test.ts +4 -8
- package/src/tools/terminal/shell.ts +5 -2
- package/src/tools/tool-approval-handler.ts +39 -23
- package/src/tools/tool-input-summary.ts +2 -1
- package/src/tools/tool-manifest.ts +20 -6
- package/src/tools/tool-profiler.ts +37 -6
- package/src/tools/ui-surface/definitions.ts +1 -7
- package/src/tools/workflows/run-workflow.test.ts +8 -22
- package/src/tts/__tests__/provider-adapters.test.ts +28 -22
- package/src/tts/__tests__/provider-resolution.test.ts +26 -0
- package/src/tts/__tests__/synthesis-stream.test.ts +6 -6
- package/src/tts/__tests__/vellum-provider.test.ts +251 -0
- package/src/tts/provider-catalog.ts +6 -0
- package/src/tts/providers/__tests__/vellum-tts-socket.test.ts +266 -0
- package/src/tts/providers/vellum-provider.ts +220 -0
- package/src/tts/providers/vellum-tts-socket.ts +377 -0
- package/src/tts/synthesize-text.ts +15 -5
- package/src/tts/tts-config-resolver.ts +2 -7
- package/src/tts/types.ts +1 -0
- package/src/usage/attribution.ts +20 -114
- package/src/util/abort-reasons.ts +1 -3
- package/src/util/image-conversion.ts +23 -5
- package/src/util/logger.ts +8 -3
- package/src/{config/bundled-skills/messaging/tools/gmail-mime-helpers.ts → util/mime-type.ts} +4 -1
- package/src/util/platform.ts +0 -60
- package/src/util/pricing.ts +10 -1
- package/src/util/telemetry-db-path.ts +9 -7
- package/src/watcher/__tests__/telemetry.test.ts +41 -11
- package/src/watcher/providers/google-calendar.ts +81 -49
- package/src/watcher/telemetry.ts +22 -5
- package/src/workflows/engine-integration.test.ts +0 -6
- package/src/workflows/engine.test.ts +1 -9
- package/src/workflows/journal-store.test.ts +1 -9
- package/src/workflows/leaf-runner.test.ts +17 -50
- package/src/workflows/library.test.ts +1 -9
- package/src/workflows/run-manager.test.ts +1 -9
- package/src/workspace/git-service.ts +932 -37
- package/src/workspace/provider-commit-message-generator.ts +6 -4
- package/__tests__/permissions/gateway-threshold-reader.test.ts +0 -450
- package/src/__tests__/canonical-guardian-store.test.ts +0 -928
- package/src/__tests__/guardian-principal-id-roundtrip.test.ts +0 -140
- package/src/__tests__/plugin-route-contribution.test.ts +0 -245
- package/src/__tests__/skill-runtime-path.test.ts +0 -63
- package/src/__tests__/task-compiler.test.ts +0 -317
- package/src/__tests__/task-management-tools.test.ts +0 -1128
- package/src/__tests__/task-scheduler.test.ts +0 -786
- package/src/config/schemas/schedules.ts +0 -35
- package/src/contacts/canonical-guardian-store.ts +0 -902
- package/src/daemon/message-types/work-items.ts +0 -243
- package/src/runtime/routes/__tests__/memory-worker-routes.test.ts +0 -306
- package/src/runtime/routes/__tests__/task-routes.test.ts +0 -644
- package/src/runtime/routes/assets/vellum-design-system.css +0 -1959
- package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +0 -129
- package/src/runtime/routes/inbound-stages/escalation-intercept.test.ts +0 -158
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +0 -187
- package/src/runtime/routes/memory-worker-routes.ts +0 -227
- package/src/runtime/routes/task-routes.ts +0 -380
- package/src/runtime/routes/work-items-routes.test.ts +0 -75
- package/src/runtime/routes/work-items-routes.ts +0 -881
- package/src/runtime/skill-route-registry.ts +0 -131
- package/src/tasks/SPEC.md +0 -132
- package/src/tasks/task-compiler.ts +0 -194
- package/src/tasks/task-runner.ts +0 -119
- package/src/tasks/task-scheduler.ts +0 -22
- package/src/tasks/task-store.ts +0 -153
- package/src/tasks/tool-sanitizer.ts +0 -38
- package/src/tools/apps/registry.ts +0 -16
- package/src/tools/system/register.ts +0 -9
- package/src/tools/tasks/task-delete.ts +0 -121
- package/src/tools/tasks/task-list.ts +0 -56
- package/src/tools/tasks/task-run.ts +0 -122
- package/src/tools/tasks/task-save.ts +0 -64
- package/src/tools/tasks/work-item-enqueue.ts +0 -300
- package/src/tools/tasks/work-item-list.ts +0 -65
- package/src/tools/tasks/work-item-remove.ts +0 -94
- package/src/tools/tasks/work-item-run.ts +0 -99
- package/src/tools/tasks/work-item-update.ts +0 -166
- package/src/tools/ui-surface/registry.ts +0 -14
- package/src/work-items/resolve-required-tools.test.ts +0 -37
- package/src/work-items/resolve-required-tools.ts +0 -26
- package/src/work-items/work-item-runner.ts +0 -187
- package/src/work-items/work-item-store.ts +0 -416
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* testable while keeping shared mutable state bundled in EventHandlerState.
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
+
import { SENTINEL_REDACTION_VERSION } from "@vellumai/service-contracts/redacted-credential";
|
|
9
10
|
import type pino from "pino";
|
|
10
11
|
import { v4 as uuid } from "uuid";
|
|
11
12
|
|
|
@@ -15,6 +16,7 @@ import type {
|
|
|
15
16
|
TurnChannelContext,
|
|
16
17
|
TurnInterfaceContext,
|
|
17
18
|
} from "../channels/types.js";
|
|
19
|
+
import { isAssistantFeatureFlagEnabled } from "../config/assistant-feature-flags.js";
|
|
18
20
|
import { getConfig } from "../config/loader.js";
|
|
19
21
|
import { recordEstimate } from "../context/estimator-calibration.js";
|
|
20
22
|
import { stripInjectionsForCompaction } from "../context/strip-injections.js";
|
|
@@ -61,7 +63,18 @@ import type {
|
|
|
61
63
|
Message,
|
|
62
64
|
} from "../providers/types.js";
|
|
63
65
|
import { getCurrentSeq } from "../runtime/assistant-stream-state.js";
|
|
64
|
-
import {
|
|
66
|
+
import type { ForChatMint } from "../runtime/for-chat-mint-registry.js";
|
|
67
|
+
import {
|
|
68
|
+
currentForChatMintWatermark,
|
|
69
|
+
forChatMintsSince,
|
|
70
|
+
} from "../runtime/for-chat-mint-registry.js";
|
|
71
|
+
import { conversationRevealNonce } from "../runtime/reveal-nonce.js";
|
|
72
|
+
import {
|
|
73
|
+
closeRevealProofWindow,
|
|
74
|
+
currentRevealSuccessWatermark,
|
|
75
|
+
openRevealProofWindow,
|
|
76
|
+
} from "../runtime/reveal-success-registry.js";
|
|
77
|
+
import { credentialKey } from "../security/credential-key.js";
|
|
65
78
|
import { extractDomain } from "../tools/network/domain-normalize.js";
|
|
66
79
|
import {
|
|
67
80
|
classifyWebSearchFailure,
|
|
@@ -81,6 +94,26 @@ import {
|
|
|
81
94
|
cleanAssistantContent,
|
|
82
95
|
drainDirectiveDisplayBuffer,
|
|
83
96
|
} from "./assistant-attachments.js";
|
|
97
|
+
import type {
|
|
98
|
+
LiveRevealGuardEntry,
|
|
99
|
+
ResolvedRevealCandidate,
|
|
100
|
+
RevealCandidateRef,
|
|
101
|
+
} from "./chat-credential-redaction.js";
|
|
102
|
+
import {
|
|
103
|
+
buildLiveRevealGuardEntries,
|
|
104
|
+
collectRevealRefsFromCommand,
|
|
105
|
+
drainCandidateGuardedChunk,
|
|
106
|
+
drainSentinelGuardedText,
|
|
107
|
+
filterRefsByRevealProof,
|
|
108
|
+
neutralizeAndSwapLiveRevealValues,
|
|
109
|
+
redactCandidateValuesLegacy,
|
|
110
|
+
redactSecretsForChat,
|
|
111
|
+
remintAuthoritiesFromCandidates,
|
|
112
|
+
resolveProvenRevealCandidates,
|
|
113
|
+
resolveRefIdentities,
|
|
114
|
+
resolveRevealCandidates,
|
|
115
|
+
type SentinelRemintAuthority,
|
|
116
|
+
} from "./chat-credential-redaction.js";
|
|
84
117
|
import type { Conversation } from "./conversation.js";
|
|
85
118
|
import type { AssistantSurface } from "./conversation-agent-loop.js";
|
|
86
119
|
import {
|
|
@@ -90,6 +123,12 @@ import {
|
|
|
90
123
|
} from "./conversation-error.js";
|
|
91
124
|
import { buildDeferredFinalizeEffect } from "./conversation-turn-finalize.js";
|
|
92
125
|
import { resolveTurnTimezoneContext } from "./date-context.js";
|
|
126
|
+
import {
|
|
127
|
+
appendInflightSnapshot,
|
|
128
|
+
createInflightContentWriter,
|
|
129
|
+
finalizeInflightContent,
|
|
130
|
+
type InflightContentWriter,
|
|
131
|
+
} from "./inflight-message-content.js";
|
|
93
132
|
import type {
|
|
94
133
|
CardSurfaceData,
|
|
95
134
|
ServerMessage,
|
|
@@ -194,6 +233,13 @@ export interface EventHandlerState {
|
|
|
194
233
|
* absorbs the reserved row into the error message.
|
|
195
234
|
*/
|
|
196
235
|
assistantRowAwaitingFinalization: boolean;
|
|
236
|
+
/**
|
|
237
|
+
* Per-row in-flight content writers, keyed by message row id. Created
|
|
238
|
+
* lazily on the first partial flush of a row; removed when the row's
|
|
239
|
+
* finalize seam folds the file inline. Writers still present at
|
|
240
|
+
* turn-finalize (cancelled/aborted turns) are folded there.
|
|
241
|
+
*/
|
|
242
|
+
readonly inflightWriters: Map<string, InflightContentWriter>;
|
|
197
243
|
readonly pendingToolResults: Map<string, PendingToolResult>;
|
|
198
244
|
/**
|
|
199
245
|
* Reservation of the grouped `user` tool-result row for the current batch,
|
|
@@ -338,6 +384,111 @@ export interface EventHandlerState {
|
|
|
338
384
|
* every produced assistant row is indexed.
|
|
339
385
|
*/
|
|
340
386
|
readonly deferredFinalizeEffects: Array<() => Promise<void>>;
|
|
387
|
+
/**
|
|
388
|
+
* Credential refs parsed from `credentials reveal` invocations in this
|
|
389
|
+
* turn's shell-style tool commands (see `chat-credential-redaction.ts`).
|
|
390
|
+
* Staged per tool_use in {@link pendingRevealRefsByToolUse} and promoted
|
|
391
|
+
* here only when that tool's result arrives successfully; consumed at the
|
|
392
|
+
* persist seams to scope the candidate fetch for redaction-sentinel
|
|
393
|
+
* enrichment. Only ever read when the `chat-credential-reveal` feature
|
|
394
|
+
* flag is on.
|
|
395
|
+
*/
|
|
396
|
+
readonly revealCandidateRefs: RevealCandidateRef[];
|
|
397
|
+
/**
|
|
398
|
+
* Reveal refs parsed at `tool_use` time, staged until the reveal route
|
|
399
|
+
* itself proves it executed. `tool_use` is emitted BEFORE tool
|
|
400
|
+
* execution — approval denial, cancellation, or the route's
|
|
401
|
+
* untrusted-shell block can still stop the command — and candidate
|
|
402
|
+
* resolution reads plaintext straight from the store, so resolving at
|
|
403
|
+
* propose time would fetch secrets for a reveal that never ran,
|
|
404
|
+
* side-stepping the reveal route's own policy gates. The enclosing
|
|
405
|
+
* tool's success is not proof either (`reveal … || true`, or an echo of
|
|
406
|
+
* the command text), so each staging captures a reveal-success-registry
|
|
407
|
+
* watermark and `handleToolResult` promotes only the refs whose
|
|
408
|
+
* identity the route actually served after it (see
|
|
409
|
+
* `filterRefsByRevealProof`); the rest are dropped.
|
|
410
|
+
*/
|
|
411
|
+
readonly pendingRevealRefsByToolUse: Map<
|
|
412
|
+
string,
|
|
413
|
+
/** `proofWindowToken` arms registry recording for this staging's
|
|
414
|
+
* lifetime (see `openRevealProofWindow`) and is closed at result. */
|
|
415
|
+
{ refs: RevealCandidateRef[]; watermark: number; proofWindowToken: number }
|
|
416
|
+
>;
|
|
417
|
+
/**
|
|
418
|
+
* Tool stdout held back from live `tool_output_chunk` emission because
|
|
419
|
+
* it ends in a partial occurrence of a reveal candidate's plaintext
|
|
420
|
+
* (keyed by toolUseId). Re-prepended to the tool's next chunk and
|
|
421
|
+
* flushed, redacted, when its tool_result arrives — nothing can complete
|
|
422
|
+
* the partial after that. Only ever populated while proven reveal
|
|
423
|
+
* candidates exist (see `handleToolOutputChunk`).
|
|
424
|
+
*/
|
|
425
|
+
readonly toolOutputGuardBuffers: Map<string, string>;
|
|
426
|
+
/**
|
|
427
|
+
* Live text the sentinel stream guard held back from
|
|
428
|
+
* `assistant_text_delta` emission — a trailing partial `〔redacted:`
|
|
429
|
+
* trigger or reveal-candidate plaintext prefix that a later chunk may
|
|
430
|
+
* complete. Re-prepended to the next delta and flushed
|
|
431
|
+
* (neutralized + candidate-swapped) at message_complete. See
|
|
432
|
+
* `drainSentinelGuardedText`.
|
|
433
|
+
*/
|
|
434
|
+
pendingSentinelGuardBuffer: string;
|
|
435
|
+
/**
|
|
436
|
+
* Precomputed live-swap entries for this turn's reveal candidates: when
|
|
437
|
+
* the model echoes a candidate's plaintext, the stream guard replaces it
|
|
438
|
+
* with its enriched sentinel before emission so the secret never reaches
|
|
439
|
+
* the wire. Primed asynchronously when `handleToolResult` confirms a
|
|
440
|
+
* staged reveal invocation actually succeeded — before the model's next
|
|
441
|
+
* text can echo the tool's stdout. Empty when the
|
|
442
|
+
* `chat-credential-reveal` flag is off.
|
|
443
|
+
*/
|
|
444
|
+
liveRevealGuardEntries: readonly LiveRevealGuardEntry[];
|
|
445
|
+
/**
|
|
446
|
+
* Re-mint authorities derived from this turn's proven reveal candidates
|
|
447
|
+
* (see `remintAuthoritiesFromCandidates`), primed together with
|
|
448
|
+
* {@link liveRevealGuardEntries} behind the same dispatcher barrier so
|
|
449
|
+
* the live guard can consult them synchronously. Combined at each guard
|
|
450
|
+
* site with the `--for-chat` mints the reveal route recorded this run.
|
|
451
|
+
*/
|
|
452
|
+
candidateRemintAuthorities: readonly SentinelRemintAuthority[];
|
|
453
|
+
/**
|
|
454
|
+
* `--for-chat` mint-registry watermark captured when this run's state
|
|
455
|
+
* was created. `turnForChatMints` returns only mints the reveal route
|
|
456
|
+
* recorded after this point — the guard's authority for re-minting a
|
|
457
|
+
* sentinel identity is an actually-executed reveal, never a parse of
|
|
458
|
+
* the requested command (which would let a quoted/commented-out
|
|
459
|
+
* invocation allowlist a forgery).
|
|
460
|
+
*/
|
|
461
|
+
readonly forChatMintWatermark: number;
|
|
462
|
+
/**
|
|
463
|
+
* `credentialKey`-formatted identities of every reveal invocation THIS run
|
|
464
|
+
* staged from its own `tool_use` commands (`credentialKey` format). The
|
|
465
|
+
* conversation-scoping leg of re-mint authority: registry mints are
|
|
466
|
+
* global (a mint's request body carries no trustworthy conversation
|
|
467
|
+
* identity — see the registry module doc), so `turnForChatMints` accepts
|
|
468
|
+
* only mints whose identity this run itself requested. Staging parses
|
|
469
|
+
* the command the daemon actually dispatched — trusted context a
|
|
470
|
+
* subprocess env override can never rewrite.
|
|
471
|
+
*/
|
|
472
|
+
readonly stagedRevealIdentities: Set<string>;
|
|
473
|
+
/**
|
|
474
|
+
* In-flight priming of {@link liveRevealGuardEntries}. The dispatcher
|
|
475
|
+
* awaits this before processing a `text_delta` (and before the
|
|
476
|
+
* end-of-message guard flush) so a fast reveal echo can never race the
|
|
477
|
+
* guard: without the barrier, a quick tool return plus a slow store read
|
|
478
|
+
* would let `drainSentinelGuardedText` run with an empty entry list and
|
|
479
|
+
* send the plaintext over SSE even though the persisted row redacts it.
|
|
480
|
+
* Cleared once settled — steady-state deltas await nothing.
|
|
481
|
+
*/
|
|
482
|
+
liveRevealGuardPriming: Promise<void> | undefined;
|
|
483
|
+
/**
|
|
484
|
+
* Memoized resolution of {@link revealCandidateRefs} so a turn with many
|
|
485
|
+
* persist flushes fetches each candidate's plaintext once. Invalidated by
|
|
486
|
+
* ref-count when a later tool call adds more reveal invocations mid-turn.
|
|
487
|
+
*/
|
|
488
|
+
revealCandidateCache?: {
|
|
489
|
+
refCount: number;
|
|
490
|
+
candidates: Promise<ResolvedRevealCandidate[]>;
|
|
491
|
+
};
|
|
341
492
|
}
|
|
342
493
|
|
|
343
494
|
/** Immutable context shared across event handlers within a single agent loop run. */
|
|
@@ -395,6 +546,7 @@ export function createEventHandlerState(): EventHandlerState {
|
|
|
395
546
|
persistProviderErrorAsAssistantMessage: false,
|
|
396
547
|
lastAssistantMessageId: undefined,
|
|
397
548
|
assistantRowAwaitingFinalization: false,
|
|
549
|
+
inflightWriters: new Map(),
|
|
398
550
|
pendingToolResults: new Map(),
|
|
399
551
|
pendingToolResultRowReservation: undefined,
|
|
400
552
|
persistedToolUseIds: new Set(),
|
|
@@ -427,16 +579,211 @@ export function createEventHandlerState(): EventHandlerState {
|
|
|
427
579
|
compactionStartMessages: new Map(),
|
|
428
580
|
latencyCursor: 0,
|
|
429
581
|
deferredFinalizeEffects: [],
|
|
582
|
+
revealCandidateRefs: [],
|
|
583
|
+
pendingRevealRefsByToolUse: new Map(),
|
|
584
|
+
toolOutputGuardBuffers: new Map(),
|
|
585
|
+
revealCandidateCache: undefined,
|
|
586
|
+
pendingSentinelGuardBuffer: "",
|
|
587
|
+
liveRevealGuardEntries: [],
|
|
588
|
+
candidateRemintAuthorities: [],
|
|
589
|
+
forChatMintWatermark: currentForChatMintWatermark(),
|
|
590
|
+
stagedRevealIdentities: new Set(),
|
|
591
|
+
liveRevealGuardPriming: undefined,
|
|
430
592
|
};
|
|
431
593
|
}
|
|
432
594
|
|
|
595
|
+
/**
|
|
596
|
+
* Resolve this turn's reveal candidates for chat sentinel redaction.
|
|
597
|
+
*
|
|
598
|
+
* Returns `undefined` when the `chat-credential-reveal` flag is off — the
|
|
599
|
+
* persist seams then use the legacy `<redacted type="…" />` marker for
|
|
600
|
+
* SCANNER matches, byte-identical to today (the candidate-aware
|
|
601
|
+
* exact-match fallback still applies via
|
|
602
|
+
* {@link resolvedRevealCandidatesForState}, which is deliberately not
|
|
603
|
+
* flag-gated: keeping a proven revealed plaintext out of persisted rows
|
|
604
|
+
* is independent of which marker format the client renders). When the
|
|
605
|
+
* flag is on, returns the resolved candidates (possibly empty: sentinel
|
|
606
|
+
* mode with nothing revealable). Resolution is memoized on the ref count
|
|
607
|
+
* so plaintexts are fetched at most once per new batch of reveal
|
|
608
|
+
* invocations.
|
|
609
|
+
*/
|
|
610
|
+
async function chatRevealCandidates(
|
|
611
|
+
state: EventHandlerState,
|
|
612
|
+
): Promise<readonly ResolvedRevealCandidate[] | undefined> {
|
|
613
|
+
if (!isAssistantFeatureFlagEnabled("chat-credential-reveal", getConfig())) {
|
|
614
|
+
return undefined;
|
|
615
|
+
}
|
|
616
|
+
return resolvedRevealCandidatesForState(state);
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
/**
|
|
620
|
+
* Flag-independent candidate resolution for the legacy-marker fallbacks:
|
|
621
|
+
* a route-proven reveal plaintext must be kept out of persisted rows in
|
|
622
|
+
* BOTH modes, so the fallback surfaces (tool results always; assistant
|
|
623
|
+
* text when the sentinel flag is off) resolve candidates here directly.
|
|
624
|
+
* Refs only exist when the reveal route actually served the identity
|
|
625
|
+
* (see `filterRefsByRevealProof`), so with the flag off this performs no
|
|
626
|
+
* store reads until a genuine reveal has already happened. Shares the
|
|
627
|
+
* per-state memoization with {@link chatRevealCandidates}.
|
|
628
|
+
*/
|
|
629
|
+
async function resolvedRevealCandidatesForState(
|
|
630
|
+
state: EventHandlerState,
|
|
631
|
+
): Promise<readonly ResolvedRevealCandidate[]> {
|
|
632
|
+
const refCount = state.revealCandidateRefs.length;
|
|
633
|
+
if (refCount === 0) {
|
|
634
|
+
return [];
|
|
635
|
+
}
|
|
636
|
+
if (
|
|
637
|
+
state.revealCandidateCache === undefined ||
|
|
638
|
+
state.revealCandidateCache.refCount !== refCount
|
|
639
|
+
) {
|
|
640
|
+
state.revealCandidateCache = {
|
|
641
|
+
refCount,
|
|
642
|
+
candidates: resolveRevealCandidates([...state.revealCandidateRefs]),
|
|
643
|
+
};
|
|
644
|
+
}
|
|
645
|
+
return state.revealCandidateCache.candidates;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
/**
|
|
649
|
+
* Kick off (or refresh) the live stream guard's swap entries from the
|
|
650
|
+
* memoized candidate resolution. Called from `handleToolResult` once a
|
|
651
|
+
* staged reveal invocation is confirmed successful — never at propose
|
|
652
|
+
* time, since candidate resolution reads plaintext straight from the
|
|
653
|
+
* store and the tool may yet be denied or cancelled. The store read is
|
|
654
|
+
* asynchronous while the dispatcher moves on, so a slow
|
|
655
|
+
* `getSecureKeyAsync` could let the next text deltas reach the guard
|
|
656
|
+
* before entries exist. The pending promise is therefore recorded on
|
|
657
|
+
* state and awaited by the dispatcher at the delta boundary (see
|
|
658
|
+
* `dispatchAgentEvent`), turning the race into a barrier. If resolution
|
|
659
|
+
* fails, the guard stays on its previous entries and the persist seams
|
|
660
|
+
* still redact; the stream guard remains a wire-level layer, persistence
|
|
661
|
+
* the redaction boundary.
|
|
662
|
+
*/
|
|
663
|
+
function primeLiveRevealGuard(state: EventHandlerState): void {
|
|
664
|
+
const priming = chatRevealCandidates(state)
|
|
665
|
+
.then((candidates) => {
|
|
666
|
+
if (candidates !== undefined && candidates.length > 0) {
|
|
667
|
+
state.liveRevealGuardEntries = buildLiveRevealGuardEntries(candidates);
|
|
668
|
+
state.candidateRemintAuthorities =
|
|
669
|
+
remintAuthoritiesFromCandidates(candidates);
|
|
670
|
+
}
|
|
671
|
+
})
|
|
672
|
+
.catch((err: unknown) => {
|
|
673
|
+
log.debug(
|
|
674
|
+
{ err },
|
|
675
|
+
"live reveal guard priming failed; stream swap stays inactive",
|
|
676
|
+
);
|
|
677
|
+
})
|
|
678
|
+
.finally(() => {
|
|
679
|
+
// Only clear our own registration — a later reveal in the same turn
|
|
680
|
+
// may have replaced the pending promise with a fresh one.
|
|
681
|
+
if (state.liveRevealGuardPriming === priming) {
|
|
682
|
+
state.liveRevealGuardPriming = undefined;
|
|
683
|
+
}
|
|
684
|
+
});
|
|
685
|
+
state.liveRevealGuardPriming = priming;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
/**
|
|
689
|
+
* Barrier for the live reveal guard: resolves once any in-flight priming
|
|
690
|
+
* has settled. Awaited before text deltas are guarded and before the
|
|
691
|
+
* end-of-message guard flush, so echoed plaintext can never beat the
|
|
692
|
+
* guard entries onto the wire. No-op (no await, no microtask churn) when
|
|
693
|
+
* nothing is being primed.
|
|
694
|
+
*/
|
|
695
|
+
async function awaitLiveRevealGuardReady(
|
|
696
|
+
state: EventHandlerState,
|
|
697
|
+
): Promise<void> {
|
|
698
|
+
// Loop: priming that settles can be superseded by a newer registration
|
|
699
|
+
// (two reveals back-to-back) before this await resumes.
|
|
700
|
+
while (state.liveRevealGuardPriming !== undefined) {
|
|
701
|
+
await state.liveRevealGuardPriming;
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
/**
|
|
706
|
+
* `--for-chat` mints authorized for THIS run: recorded by the reveal route
|
|
707
|
+
* after this run's watermark AND matching an identity this run itself
|
|
708
|
+
* staged from its own `tool_use` commands. Both legs are load-bearing —
|
|
709
|
+
* the registry proves a reveal EXECUTED (a quoted/commented-out invocation
|
|
710
|
+
* never reaches the route), while the staging set scopes authority to the
|
|
711
|
+
* conversation that actually requested it (registry records carry no
|
|
712
|
+
* trustworthy conversation identity, so without this leg one
|
|
713
|
+
* conversation's approved reveal could authorize a concurrent
|
|
714
|
+
* conversation's forged sentinel). Read fresh at each guard site rather
|
|
715
|
+
* than cached: the route records a mint while the reveal tool is still
|
|
716
|
+
* executing, so by the time the model echoes the sentinel back the
|
|
717
|
+
* registry is already current — no priming race like the async candidate
|
|
718
|
+
* fetch has.
|
|
719
|
+
*/
|
|
720
|
+
function turnForChatMints(
|
|
721
|
+
state: EventHandlerState,
|
|
722
|
+
deps: EventHandlerDeps,
|
|
723
|
+
): ForChatMint[] {
|
|
724
|
+
if (state.stagedRevealIdentities.size === 0) {
|
|
725
|
+
return [];
|
|
726
|
+
}
|
|
727
|
+
const nonce = conversationRevealNonce(deps.ctx.conversationId);
|
|
728
|
+
return forChatMintsSince(state.forChatMintWatermark).filter(
|
|
729
|
+
(mint) =>
|
|
730
|
+
mint.nonce === nonce &&
|
|
731
|
+
state.stagedRevealIdentities.has(credentialKey(mint.service, mint.field)),
|
|
732
|
+
);
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
/**
|
|
736
|
+
* Combined re-mint authorities for the LIVE emit sites (synchronous):
|
|
737
|
+
* route-recorded `--for-chat` mints plus the candidate-derived authorities
|
|
738
|
+
* primed behind the dispatcher barrier alongside the swap entries.
|
|
739
|
+
*/
|
|
740
|
+
function liveRemintAuthorities(
|
|
741
|
+
state: EventHandlerState,
|
|
742
|
+
deps: EventHandlerDeps,
|
|
743
|
+
): SentinelRemintAuthority[] {
|
|
744
|
+
return [
|
|
745
|
+
...turnForChatMints(state, deps),
|
|
746
|
+
...state.candidateRemintAuthorities,
|
|
747
|
+
];
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
/**
|
|
751
|
+
* Combined re-mint authorities for the PERSIST sites, deriving the
|
|
752
|
+
* candidate half from the resolved candidate set the call site already
|
|
753
|
+
* fetched — persistence must not depend on whether live priming ran
|
|
754
|
+
* (a flush can outlive the stream), so it never reads the primed state.
|
|
755
|
+
*/
|
|
756
|
+
function persistRemintAuthorities(
|
|
757
|
+
state: EventHandlerState,
|
|
758
|
+
deps: EventHandlerDeps,
|
|
759
|
+
candidates: readonly ResolvedRevealCandidate[] | undefined,
|
|
760
|
+
): SentinelRemintAuthority[] {
|
|
761
|
+
return [
|
|
762
|
+
...turnForChatMints(state, deps),
|
|
763
|
+
...(candidates !== undefined && candidates.length > 0
|
|
764
|
+
? remintAuthoritiesFromCandidates(candidates)
|
|
765
|
+
: []),
|
|
766
|
+
];
|
|
767
|
+
}
|
|
768
|
+
|
|
433
769
|
// ── Partial-persistence helpers ──────────────────────────────────────
|
|
434
770
|
|
|
435
|
-
/**
|
|
771
|
+
/**
|
|
772
|
+
* Canonical persisted-content build: clean → append surfaces → redact.
|
|
773
|
+
*
|
|
774
|
+
* `revealCandidates` (defined only when the sentinel flag is on) selects
|
|
775
|
+
* sentinel-mode redaction; `legacyFallbackCandidates` feeds the
|
|
776
|
+
* flag-independent exact-match fallback in legacy mode, so a route-proven
|
|
777
|
+
* reveal plaintext the scanner cannot classify never persists raw
|
|
778
|
+
* regardless of which marker format is active.
|
|
779
|
+
*/
|
|
436
780
|
export function buildPersistedAssistantContent(
|
|
437
781
|
rawBlocks: readonly ContentBlock[],
|
|
438
782
|
surfaces: readonly AssistantSurface[],
|
|
439
783
|
activityByToolUseId?: ReadonlyMap<string, ToolActivityMetadata>,
|
|
784
|
+
revealCandidates?: readonly ResolvedRevealCandidate[],
|
|
785
|
+
legacyFallbackCandidates: readonly ResolvedRevealCandidate[] = [],
|
|
786
|
+
forChatMints: readonly SentinelRemintAuthority[] = [],
|
|
440
787
|
): ContentBlock[] {
|
|
441
788
|
const { cleanedContent } = cleanAssistantContent(rawBlocks);
|
|
442
789
|
const cleaned = cleanedContent as ContentBlock[];
|
|
@@ -457,7 +804,21 @@ export function buildPersistedAssistantContent(
|
|
|
457
804
|
return withSurfaces.map((block) => {
|
|
458
805
|
if (block.type === "text") {
|
|
459
806
|
const tb = block as Extract<ContentBlock, { type: "text" }>;
|
|
460
|
-
|
|
807
|
+
// Sentinel mode (chat-credential-reveal flag on) persists redactions
|
|
808
|
+
// the client can render as chips; legacy mode keeps the marker
|
|
809
|
+
// byte-identical to today. Detection is the same scanner either way.
|
|
810
|
+
// Both modes neutralize forged sentinel-shaped strings first so
|
|
811
|
+
// arbitrary content can never manufacture a reveal chip — only
|
|
812
|
+
// redactor-inserted sentinels survive persistence. The
|
|
813
|
+
// `_redactionVersion` rider (internal, same convention as `_startedAt`)
|
|
814
|
+
// marks the block as neutralization-aware; `renderHistoryContent`
|
|
815
|
+
// neutralizes unmarked (pre-feature) blocks at read so forged sentinels
|
|
816
|
+
// in old history rows can never chip-ify either.
|
|
817
|
+
const text =
|
|
818
|
+
revealCandidates !== undefined
|
|
819
|
+
? redactSecretsForChat(tb.text, revealCandidates, forChatMints)
|
|
820
|
+
: redactCandidateValuesLegacy(tb.text, legacyFallbackCandidates);
|
|
821
|
+
return { ...tb, text, _redactionVersion: SENTINEL_REDACTION_VERSION };
|
|
461
822
|
}
|
|
462
823
|
// Native server tools (Anthropic web_search) resolve mid-stream — their
|
|
463
824
|
// `server_tool_complete` fires before `message_complete` — so the captured
|
|
@@ -570,6 +931,45 @@ function resetPartialPersistAccumulator(state: EventHandlerState): void {
|
|
|
570
931
|
state.currentThinkingTimestamps = [];
|
|
571
932
|
state.lastPersistedContentSeq = undefined;
|
|
572
933
|
state.pendingPartialFlushPromise = undefined;
|
|
934
|
+
// If a previous LLM call (e.g. a retried/replaced stream) held back
|
|
935
|
+
// sentinel-guarded text via `drainSentinelGuardedText`, the stale
|
|
936
|
+
// bytes would be prepended to the retry's first text_delta, potentially
|
|
937
|
+
// emitting a raw credential prefix if it no longer matches a candidate.
|
|
938
|
+
// Clear alongside the other per-row accumulators so the new LLM call
|
|
939
|
+
// starts from an empty buffer.
|
|
940
|
+
state.pendingSentinelGuardBuffer = "";
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
/**
|
|
944
|
+
* Reserve a message row born in-flight: the writer (and its `{ ref }`) is
|
|
945
|
+
* created first, the reservation persists the ref into the newborn row with
|
|
946
|
+
* `finalized = 0`, and the writer is registered under the resolved row id.
|
|
947
|
+
* When the conversation can't be resolved, the row is reserved as a plain
|
|
948
|
+
* inline placeholder and null is returned — content writes then fall back
|
|
949
|
+
* to direct row writes, which stays correct at the cost of a full-blob
|
|
950
|
+
* UPDATE per flush.
|
|
951
|
+
*/
|
|
952
|
+
async function reserveInflightMessageRow(
|
|
953
|
+
state: EventHandlerState,
|
|
954
|
+
conversationId: string,
|
|
955
|
+
role: "assistant" | "user",
|
|
956
|
+
metadata: Record<string, unknown> | undefined,
|
|
957
|
+
): Promise<{ id: string }> {
|
|
958
|
+
const writer = createInflightContentWriter(conversationId);
|
|
959
|
+
const reserved = await reserveMessage(
|
|
960
|
+
conversationId,
|
|
961
|
+
role,
|
|
962
|
+
metadata,
|
|
963
|
+
writer?.ref,
|
|
964
|
+
);
|
|
965
|
+
if (writer && !state.inflightWriters.has(reserved.id)) {
|
|
966
|
+
writer.messageId = reserved.id;
|
|
967
|
+
state.inflightWriters.set(reserved.id, writer);
|
|
968
|
+
}
|
|
969
|
+
// A pre-existing entry for this id means an id collision (only test
|
|
970
|
+
// doubles reuse row ids — production ids are unique); keep the writer
|
|
971
|
+
// already tracking that id so its delta file is still finalized/cleaned.
|
|
972
|
+
return reserved;
|
|
573
973
|
}
|
|
574
974
|
|
|
575
975
|
/**
|
|
@@ -589,12 +989,20 @@ async function persistLoopMessageContent(
|
|
|
589
989
|
contentJson: string,
|
|
590
990
|
op: string,
|
|
591
991
|
rlog: pino.Logger,
|
|
992
|
+
metadataUpdates?: Record<string, unknown>,
|
|
592
993
|
): Promise<boolean> {
|
|
593
994
|
try {
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
995
|
+
// Metadata updates (e.g. the served model at finalize) ride the same
|
|
996
|
+
// write as the content — `updateMessageContent` commits both atomically —
|
|
997
|
+
// so a partial write can't leave them out of sync; the updates
|
|
998
|
+
// shallow-merge onto the channel provenance stamped at reserve.
|
|
999
|
+
await withSqliteRetry(
|
|
1000
|
+
() => updateMessageContent(messageId, contentJson, metadataUpdates),
|
|
1001
|
+
{
|
|
1002
|
+
op,
|
|
1003
|
+
context: { messageId },
|
|
1004
|
+
},
|
|
1005
|
+
);
|
|
598
1006
|
return true;
|
|
599
1007
|
} catch (err) {
|
|
600
1008
|
rlog.error(
|
|
@@ -618,23 +1026,33 @@ async function flushAccumulatedContent(
|
|
|
618
1026
|
return;
|
|
619
1027
|
}
|
|
620
1028
|
|
|
1029
|
+
const revealCandidates = await chatRevealCandidates(state);
|
|
621
1030
|
const built = buildPersistedAssistantContent(
|
|
622
1031
|
state.currentMessageContent,
|
|
623
1032
|
[],
|
|
624
1033
|
state.toolActivityMetadata,
|
|
1034
|
+
revealCandidates,
|
|
1035
|
+
await resolvedRevealCandidatesForState(state),
|
|
1036
|
+
persistRemintAuthorities(state, deps, revealCandidates),
|
|
625
1037
|
);
|
|
626
|
-
const contentJson = JSON.stringify(built);
|
|
627
1038
|
// Pair the seq with the exact content snapshot taken above: deltas that
|
|
628
1039
|
// arrive while the write is in flight bump `lastPersistedContentSeq`
|
|
629
1040
|
// again, but they are not part of this write.
|
|
630
1041
|
const flushedSeq = state.lastPersistedContentSeq;
|
|
631
1042
|
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
1043
|
+
// Partial flushes append to the in-flight delta file — a pure file
|
|
1044
|
+
// write; the row has held the `{ ref }` since it was reserved. Delta
|
|
1045
|
+
// lines are stamped with the flushed event seq so the file correlates
|
|
1046
|
+
// 1:1 with the stream.
|
|
1047
|
+
const writer = state.inflightWriters.get(messageId);
|
|
1048
|
+
const persisted = writer
|
|
1049
|
+
? appendInflightSnapshot(writer, built, flushedSeq ?? undefined, deps.rlog)
|
|
1050
|
+
: await persistLoopMessageContent(
|
|
1051
|
+
messageId,
|
|
1052
|
+
JSON.stringify(built),
|
|
1053
|
+
"partial_flush_assistant_content",
|
|
1054
|
+
deps.rlog,
|
|
1055
|
+
);
|
|
638
1056
|
// Record only after the write commits, so the snapshot seq never
|
|
639
1057
|
// claims content that is not yet durable.
|
|
640
1058
|
if (persisted && flushedSeq != null) {
|
|
@@ -868,7 +1286,8 @@ export async function handleLlmCallStarted(
|
|
|
868
1286
|
}
|
|
869
1287
|
|
|
870
1288
|
const metadata = buildAssistantChannelMetadata(state, deps);
|
|
871
|
-
const reservedRow = await
|
|
1289
|
+
const reservedRow = await reserveInflightMessageRow(
|
|
1290
|
+
state,
|
|
872
1291
|
deps.ctx.conversationId,
|
|
873
1292
|
"assistant",
|
|
874
1293
|
metadata,
|
|
@@ -908,24 +1327,43 @@ function handleTextDelta(
|
|
|
908
1327
|
statusText: "Thinking",
|
|
909
1328
|
});
|
|
910
1329
|
}
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
1330
|
+
// Live stream guard: neutralize forged sentinels (a genuine sentinel is
|
|
1331
|
+
// created at persist time, never in raw model output) and swap a reveal
|
|
1332
|
+
// candidate's echoed plaintext for its enriched sentinel so the secret
|
|
1333
|
+
// never flashes in the live transcript or crosses the wire. A trigger or
|
|
1334
|
+
// candidate prefix split across chunks is held back in
|
|
1335
|
+
// `pendingSentinelGuardBuffer` and flushed at message end.
|
|
1336
|
+
const guarded = drainSentinelGuardedText(
|
|
1337
|
+
state.pendingSentinelGuardBuffer + drained.emitText,
|
|
1338
|
+
state.liveRevealGuardEntries,
|
|
1339
|
+
liveRemintAuthorities(state, deps),
|
|
1340
|
+
);
|
|
1341
|
+
state.pendingSentinelGuardBuffer = guarded.bufferedRemainder;
|
|
1342
|
+
if (guarded.emitText.length > 0) {
|
|
1343
|
+
deps.onEvent({
|
|
1344
|
+
type: "assistant_text_delta",
|
|
1345
|
+
text: guarded.emitText,
|
|
1346
|
+
conversationId: deps.ctx.conversationId,
|
|
1347
|
+
messageId: state.lastAssistantMessageId,
|
|
1348
|
+
});
|
|
1349
|
+
// Mirror the RAW consumed bytes (not the emitted swap) into
|
|
1350
|
+
// currentMessageContent: the partial flush re-redacts them through
|
|
1351
|
+
// `redactSecretsForChat`, which derives the same enriched sentinel
|
|
1352
|
+
// from the plaintext — whereas a mirrored, already-swapped sentinel
|
|
1353
|
+
// would be indistinguishable from a forgery there and get
|
|
1354
|
+
// neutralized. Buffered bytes (partial triggers / candidate
|
|
1355
|
+
// prefixes) stay excluded until a later chunk emits them.
|
|
1356
|
+
appendTextToCurrentMessage(state, guarded.consumedRaw);
|
|
1357
|
+
// The hub stamps `seq` synchronously on the delta emitted above, so
|
|
1358
|
+
// `getCurrentSeq()` here is that delta's seq -- the position the
|
|
1359
|
+
// mirrored content now reflects. A partial flush snapshots this to
|
|
1360
|
+
// record how far the durable rows track the live stream.
|
|
1361
|
+
state.lastPersistedContentSeq = getCurrentSeq();
|
|
1362
|
+
schedulePartialFlush(state, deps);
|
|
1363
|
+
}
|
|
917
1364
|
if (deps.shouldGenerateTitle) {
|
|
918
1365
|
state.firstAssistantText += drained.emitText;
|
|
919
1366
|
}
|
|
920
|
-
// Mirror the drained delta into state.currentMessageContent so partial
|
|
921
|
-
// flushes mid-turn see the same content the user is watching live.
|
|
922
|
-
appendTextToCurrentMessage(state, drained.emitText);
|
|
923
|
-
// The hub stamps `seq` synchronously on the delta emitted above, so
|
|
924
|
-
// `getCurrentSeq()` here is that delta's seq -- the position the
|
|
925
|
-
// mirrored content now reflects. A partial flush snapshots this to
|
|
926
|
-
// record how far the durable rows track the live stream.
|
|
927
|
-
state.lastPersistedContentSeq = getCurrentSeq();
|
|
928
|
-
schedulePartialFlush(state, deps);
|
|
929
1367
|
}
|
|
930
1368
|
}
|
|
931
1369
|
|
|
@@ -981,6 +1419,46 @@ export function handleToolUse(
|
|
|
981
1419
|
if (event.name === "app_create" || event.name === "app_refresh") {
|
|
982
1420
|
state.appBuildToolUsedThisRun = true;
|
|
983
1421
|
}
|
|
1422
|
+
// Record `credentials reveal` invocations so the persist seams can enrich
|
|
1423
|
+
// redaction sentinels with a proven vault identity (chat-credential-reveal).
|
|
1424
|
+
// Tool-name agnostic on purpose: any shell-style tool (bash, host_bash)
|
|
1425
|
+
// carries the command in `input.command`. Pure string parse — no store
|
|
1426
|
+
// access happens here: `tool_use` precedes execution, and the refs are
|
|
1427
|
+
// only STAGED until `handleToolResult` sees the reveal actually succeed
|
|
1428
|
+
// (see `pendingRevealRefsByToolUse` — priming at propose time would read
|
|
1429
|
+
// plaintext for a command that approval/cancellation may still block).
|
|
1430
|
+
const command = (event.input as { command?: unknown } | undefined)?.command;
|
|
1431
|
+
if (typeof command === "string" && command.length > 0) {
|
|
1432
|
+
// Id-form refs resolve to service/field NOW (metadata-only lookup): the
|
|
1433
|
+
// same compound command may remove the credential after revealing it,
|
|
1434
|
+
// and by result time the id would no longer resolve — dropping the
|
|
1435
|
+
// proof for a value the tool already printed.
|
|
1436
|
+
const refs = resolveRefIdentities(collectRevealRefsFromCommand(command));
|
|
1437
|
+
if (refs.length > 0) {
|
|
1438
|
+
state.pendingRevealRefsByToolUse.set(event.id, {
|
|
1439
|
+
refs,
|
|
1440
|
+
// Captured before execution: only reveal-route successes recorded
|
|
1441
|
+
// AFTER this point can prove these refs at result time.
|
|
1442
|
+
watermark: currentRevealSuccessWatermark(),
|
|
1443
|
+
// Arms registry recording for this staging's lifetime — the route
|
|
1444
|
+
// retains plaintext only while some tool's proof is pending.
|
|
1445
|
+
proofWindowToken: openRevealProofWindow(),
|
|
1446
|
+
});
|
|
1447
|
+
// The conversation-scoping leg of `--for-chat` re-mint authority:
|
|
1448
|
+
// record which identities THIS run's own commands named. Retained for
|
|
1449
|
+
// the whole run (unlike the staging entry, which handleToolResult
|
|
1450
|
+
// consumes) — the model echoes the sentinel back only after the tool
|
|
1451
|
+
// completes. Parse-only, so by itself this authorizes nothing; a
|
|
1452
|
+
// registry mint (an executed reveal) must also exist.
|
|
1453
|
+
for (const ref of refs) {
|
|
1454
|
+
if (ref.service !== undefined && ref.field !== undefined) {
|
|
1455
|
+
state.stagedRevealIdentities.add(
|
|
1456
|
+
credentialKey(ref.service, ref.field),
|
|
1457
|
+
);
|
|
1458
|
+
}
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
984
1462
|
const startedAt = Date.now();
|
|
985
1463
|
state.toolCallTimestamps.set(event.id, { startedAt });
|
|
986
1464
|
state.currentToolUseId = event.id;
|
|
@@ -1121,15 +1599,59 @@ function handleToolOutputChunk(
|
|
|
1121
1599
|
subToolIsError: structured.subToolIsError,
|
|
1122
1600
|
subToolId: structured.subToolId,
|
|
1123
1601
|
});
|
|
1124
|
-
|
|
1125
|
-
deps.onEvent({
|
|
1126
|
-
type: "tool_output_chunk",
|
|
1127
|
-
chunk: event.chunk,
|
|
1128
|
-
conversationId: deps.ctx.conversationId,
|
|
1129
|
-
toolUseId: event.toolUseId,
|
|
1130
|
-
messageId: state.lastAssistantMessageId,
|
|
1131
|
-
});
|
|
1602
|
+
return;
|
|
1132
1603
|
}
|
|
1604
|
+
|
|
1605
|
+
// Redact revealed plaintext from the LIVE stdout stream. The final
|
|
1606
|
+
// tool_result is redacted at its seam, but these chunks reach the client
|
|
1607
|
+
// first and the web drawer renders them until the result replaces them —
|
|
1608
|
+
// without this guard a `credentials reveal` value flashes raw for the
|
|
1609
|
+
// whole tool run. By the time printed bytes arrive here the route has
|
|
1610
|
+
// already recorded any success (the record precedes the CLI receiving
|
|
1611
|
+
// the plaintext), so proven candidates are available SYNCHRONOUSLY from
|
|
1612
|
+
// the registry — no vault read, and the reveal-free path stays untouched.
|
|
1613
|
+
// Covers both this tool's own staged reveals and values already promoted
|
|
1614
|
+
// by an earlier tool in the turn (a later `echo <value>` streams too). A
|
|
1615
|
+
// trailing partial occurrence is held back for the next chunk; the
|
|
1616
|
+
// tool_result seam flushes the remainder. Structured control frames
|
|
1617
|
+
// above are forwarded untouched — they are parsed subtool events, not
|
|
1618
|
+
// reveal stdout, and rewriting their raw JSON could corrupt them.
|
|
1619
|
+
let chunk = event.chunk;
|
|
1620
|
+
const staged = state.pendingRevealRefsByToolUse.get(event.toolUseId);
|
|
1621
|
+
const guardRefs =
|
|
1622
|
+
staged === undefined
|
|
1623
|
+
? state.revealCandidateRefs
|
|
1624
|
+
: [
|
|
1625
|
+
...state.revealCandidateRefs,
|
|
1626
|
+
...filterRefsByRevealProof(
|
|
1627
|
+
staged.refs,
|
|
1628
|
+
staged.watermark,
|
|
1629
|
+
conversationRevealNonce(deps.ctx.conversationId),
|
|
1630
|
+
),
|
|
1631
|
+
];
|
|
1632
|
+
if (guardRefs.length > 0) {
|
|
1633
|
+
const candidates = resolveProvenRevealCandidates(guardRefs);
|
|
1634
|
+
if (candidates.length > 0) {
|
|
1635
|
+
const held = state.toolOutputGuardBuffers.get(event.toolUseId) ?? "";
|
|
1636
|
+
const drained = drainCandidateGuardedChunk(held + chunk, candidates);
|
|
1637
|
+
state.toolOutputGuardBuffers.set(
|
|
1638
|
+
event.toolUseId,
|
|
1639
|
+
drained.bufferedRemainder,
|
|
1640
|
+
);
|
|
1641
|
+
if (drained.emitText.length === 0) {
|
|
1642
|
+
return;
|
|
1643
|
+
}
|
|
1644
|
+
chunk = drained.emitText;
|
|
1645
|
+
}
|
|
1646
|
+
}
|
|
1647
|
+
|
|
1648
|
+
deps.onEvent({
|
|
1649
|
+
type: "tool_output_chunk",
|
|
1650
|
+
chunk,
|
|
1651
|
+
conversationId: deps.ctx.conversationId,
|
|
1652
|
+
toolUseId: event.toolUseId,
|
|
1653
|
+
messageId: state.lastAssistantMessageId,
|
|
1654
|
+
});
|
|
1133
1655
|
}
|
|
1134
1656
|
|
|
1135
1657
|
export function handleInputJsonDelta(
|
|
@@ -1161,17 +1683,30 @@ export function handleInputJsonDelta(
|
|
|
1161
1683
|
*/
|
|
1162
1684
|
function buildToolResultBlocks(
|
|
1163
1685
|
pending: ReadonlyMap<string, PendingToolResult>,
|
|
1686
|
+
revealCandidates: readonly ResolvedRevealCandidate[] = [],
|
|
1164
1687
|
) {
|
|
1688
|
+
// Tool results keep the legacy `<redacted type/>` marker (NOT sentinels):
|
|
1689
|
+
// history maps tool_result content to `toolCall.result`, which the tool
|
|
1690
|
+
// detail panel renders via CodeBlock — a path with no markdown/chip
|
|
1691
|
+
// support, where a sentinel would show as an inert glyph string. Convert
|
|
1692
|
+
// here only once that surface can render chips. Forged sentinel-shaped
|
|
1693
|
+
// strings in tool output are still neutralized so they can never reach a
|
|
1694
|
+
// chip-enabled surface via quoting. Proven reveal-candidate plaintexts
|
|
1695
|
+
// the scanner cannot classify (opaque manual tokens in the reveal's own
|
|
1696
|
+
// stdout) get a candidate-aware legacy-marker fallback — the tool detail
|
|
1697
|
+
// panel and history must not retain a value every other surface redacts.
|
|
1698
|
+
const redact = (text: string): string =>
|
|
1699
|
+
redactCandidateValuesLegacy(text, revealCandidates);
|
|
1165
1700
|
return Array.from(pending.entries()).map(([toolUseId, result]) => ({
|
|
1166
1701
|
type: "tool_result",
|
|
1167
1702
|
tool_use_id: toolUseId,
|
|
1168
|
-
content:
|
|
1703
|
+
content: redact(result.content),
|
|
1169
1704
|
is_error: result.isError,
|
|
1170
1705
|
...(result.contentBlocks
|
|
1171
1706
|
? {
|
|
1172
1707
|
contentBlocks: result.contentBlocks.map((block) =>
|
|
1173
1708
|
block.type === "text"
|
|
1174
|
-
? { ...block, text:
|
|
1709
|
+
? { ...block, text: redact(block.text) }
|
|
1175
1710
|
: block,
|
|
1176
1711
|
),
|
|
1177
1712
|
}
|
|
@@ -1212,7 +1747,8 @@ function ensureToolResultRowReserved(
|
|
|
1212
1747
|
metadata: Record<string, unknown>,
|
|
1213
1748
|
): Promise<string> {
|
|
1214
1749
|
if (state.pendingToolResultRowReservation === undefined) {
|
|
1215
|
-
state.pendingToolResultRowReservation =
|
|
1750
|
+
state.pendingToolResultRowReservation = reserveInflightMessageRow(
|
|
1751
|
+
state,
|
|
1216
1752
|
conversationId,
|
|
1217
1753
|
"user",
|
|
1218
1754
|
metadata,
|
|
@@ -1249,14 +1785,22 @@ async function persistPendingToolResultRow(
|
|
|
1249
1785
|
deps.ctx.conversationId,
|
|
1250
1786
|
buildToolResultMetadata(deps),
|
|
1251
1787
|
);
|
|
1252
|
-
//
|
|
1253
|
-
// concurrent writers reflects the fullest batch.
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
);
|
|
1788
|
+
// Snapshot the batch after the reservation resolves so the last of the
|
|
1789
|
+
// concurrent writers reflects the fullest batch. On-arrival writes go to
|
|
1790
|
+
// the in-flight delta file; the finalize seam folds the row inline.
|
|
1791
|
+
const batchBlocks = buildToolResultBlocks(
|
|
1792
|
+
state.pendingToolResults,
|
|
1793
|
+
await resolvedRevealCandidatesForState(state),
|
|
1794
|
+
) as ContentBlock[];
|
|
1795
|
+
const writer = state.inflightWriters.get(rowId);
|
|
1796
|
+
const persisted = writer
|
|
1797
|
+
? appendInflightSnapshot(writer, batchBlocks, seq, deps.rlog)
|
|
1798
|
+
: await persistLoopMessageContent(
|
|
1799
|
+
rowId,
|
|
1800
|
+
JSON.stringify(batchBlocks),
|
|
1801
|
+
"persist_tool_result_row",
|
|
1802
|
+
deps.rlog,
|
|
1803
|
+
);
|
|
1260
1804
|
if (persisted) {
|
|
1261
1805
|
recordConversationPersistedSeq(deps.ctx.conversationId, seq);
|
|
1262
1806
|
}
|
|
@@ -1296,7 +1840,10 @@ export async function finalizePendingToolResultRow(
|
|
|
1296
1840
|
// for workspace references so the blob stays in the attachment store, out of
|
|
1297
1841
|
// this row and the lexical index. Runs once, here at finalize (on-arrival
|
|
1298
1842
|
// writes keep base64 for durability); the send boundary re-inflates the refs.
|
|
1299
|
-
const blocks = buildToolResultBlocks(
|
|
1843
|
+
const blocks = buildToolResultBlocks(
|
|
1844
|
+
state.pendingToolResults,
|
|
1845
|
+
await resolvedRevealCandidatesForState(state),
|
|
1846
|
+
);
|
|
1300
1847
|
const contentJson = JSON.stringify(
|
|
1301
1848
|
conv != null
|
|
1302
1849
|
? referenceMediaBlocksForPersist(
|
|
@@ -1307,12 +1854,18 @@ export async function finalizePendingToolResultRow(
|
|
|
1307
1854
|
)
|
|
1308
1855
|
: blocks,
|
|
1309
1856
|
);
|
|
1310
|
-
await
|
|
1857
|
+
const toolRowFinalized = await finalizeInflightContent(
|
|
1858
|
+
state.inflightWriters.get(rowId),
|
|
1311
1859
|
rowId,
|
|
1312
1860
|
contentJson,
|
|
1313
|
-
"finalize_tool_result_row",
|
|
1314
1861
|
rlog,
|
|
1315
1862
|
);
|
|
1863
|
+
// Keep the writer on a failed finalize (e.g. persistent SQLITE_BUSY) so
|
|
1864
|
+
// the turn tail's stranded fold can retry — deleting it would leave the
|
|
1865
|
+
// row `finalized = 0` in a live daemon until crash recovery.
|
|
1866
|
+
if (toolRowFinalized) {
|
|
1867
|
+
state.inflightWriters.delete(rowId);
|
|
1868
|
+
}
|
|
1316
1869
|
// Sync the row to the JSONL disk view so it stays in lockstep with the DB.
|
|
1317
1870
|
if (conv != null) {
|
|
1318
1871
|
syncMessageToDisk(conversationId, rowId, conv.createdAt);
|
|
@@ -1379,6 +1932,76 @@ export async function handleToolResult(
|
|
|
1379
1932
|
deps: EventHandlerDeps,
|
|
1380
1933
|
event: Extract<AgentEvent, { type: "tool_result" }>,
|
|
1381
1934
|
): Promise<void> {
|
|
1935
|
+
// Promote staged reveal refs now that the tool has finished: a ref is
|
|
1936
|
+
// promoted only if the reveal ROUTE recorded a success for its identity
|
|
1937
|
+
// after the staging watermark — the enclosing tool's exit status proves
|
|
1938
|
+
// nothing (`reveal … || true` succeeds when the route failed; an echo of
|
|
1939
|
+
// the command text never calls the route; conversely, a compound command
|
|
1940
|
+
// can print the secret and then exit non-zero, in which case the model
|
|
1941
|
+
// HAS the plaintext and the guard entry is protective). Only then may
|
|
1942
|
+
// candidate resolution read the plaintext from the store. Synchronous —
|
|
1943
|
+
// the dispatcher awaits `tool_result` before any later `text_delta`, so
|
|
1944
|
+
// the priming promise is registered before the barrier can be consulted.
|
|
1945
|
+
const stagedReveal = state.pendingRevealRefsByToolUse.get(event.toolUseId);
|
|
1946
|
+
if (stagedReveal !== undefined) {
|
|
1947
|
+
state.pendingRevealRefsByToolUse.delete(event.toolUseId);
|
|
1948
|
+
const provenRefs = filterRefsByRevealProof(
|
|
1949
|
+
stagedReveal.refs,
|
|
1950
|
+
stagedReveal.watermark,
|
|
1951
|
+
conversationRevealNonce(deps.ctx.conversationId),
|
|
1952
|
+
);
|
|
1953
|
+
// The proof is consumed (proven values now ride the refs), so this
|
|
1954
|
+
// staging no longer needs the registry to record.
|
|
1955
|
+
closeRevealProofWindow(stagedReveal.proofWindowToken);
|
|
1956
|
+
if (provenRefs.length > 0) {
|
|
1957
|
+
state.revealCandidateRefs.push(...provenRefs);
|
|
1958
|
+
primeLiveRevealGuard(state);
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1961
|
+
|
|
1962
|
+
// Redact THIS tool's own stdout before it leaves the daemon. The reveal
|
|
1963
|
+
// command that just proved a candidate printed the plaintext into its own
|
|
1964
|
+
// `event.content`; priming the assistant-text guard only protects a later
|
|
1965
|
+
// echo, not this result. The persist path already redacts via
|
|
1966
|
+
// `buildToolResultBlocks`, but the LIVE `tool_result` SSE below forwards
|
|
1967
|
+
// `event.content` verbatim and the web reducer stores `event.result`
|
|
1968
|
+
// directly — so an opaque/manual value the scanner cannot classify would
|
|
1969
|
+
// flash in the tool card until a history refetch. Apply the same
|
|
1970
|
+
// candidate-aware legacy redaction the persisted tool-result row uses, to
|
|
1971
|
+
// both the buffered content and the emitted result, so wire and storage
|
|
1972
|
+
// agree from the first frame.
|
|
1973
|
+
//
|
|
1974
|
+
// Guard the resolution behind the ref count: candidate resolution is async
|
|
1975
|
+
// (it reads the vault), and awaiting it here would push every side effect
|
|
1976
|
+
// below — the cancellation emit, the pending-result buffering, the
|
|
1977
|
+
// activity/risk metadata capture, `annotatePersistedAssistantMessage`, and
|
|
1978
|
+
// the live `tool_result` emit — onto a later microtask. Callers that drive
|
|
1979
|
+
// this handler synchronously (the dispatcher, and the metadata/preview
|
|
1980
|
+
// tests) rely on those effects landing before the returned promise's first
|
|
1981
|
+
// suspension, so a reveal-free tool result must stay fully synchronous and
|
|
1982
|
+
// pass its content through untouched — exactly as before this guard shipped.
|
|
1983
|
+
// The refs are non-empty only after the reveal route actually served an
|
|
1984
|
+
// identity this turn, which is precisely when redaction must fire.
|
|
1985
|
+
let redactedContent = event.content;
|
|
1986
|
+
// DISCARD (never emit) stdout the live chunk guard held back for this
|
|
1987
|
+
// tool. The buffer was held precisely because it contains or ends in a
|
|
1988
|
+
// PARTIAL occurrence of a candidate's plaintext, and complete-value
|
|
1989
|
+
// redaction cannot mask a partial — flushing it would put up to
|
|
1990
|
+
// value-length-minus-one raw credential bytes on the wire. Nothing is
|
|
1991
|
+
// lost: the redacted `event.content` emitted below carries the full
|
|
1992
|
+
// output and supersedes the streamed view immediately.
|
|
1993
|
+
state.toolOutputGuardBuffers.delete(event.toolUseId);
|
|
1994
|
+
if (state.revealCandidateRefs.length > 0) {
|
|
1995
|
+
const revealCandidatesForResult =
|
|
1996
|
+
await resolvedRevealCandidatesForState(state);
|
|
1997
|
+
if (revealCandidatesForResult.length > 0) {
|
|
1998
|
+
redactedContent = redactCandidateValuesLegacy(
|
|
1999
|
+
event.content,
|
|
2000
|
+
revealCandidatesForResult,
|
|
2001
|
+
);
|
|
2002
|
+
}
|
|
2003
|
+
}
|
|
2004
|
+
|
|
1382
2005
|
// A synthesized cancellation (the tool never executed) is captured for
|
|
1383
2006
|
// persistence and forwarded to the client like any result, but skips every
|
|
1384
2007
|
// side effect that assumes the tool ran. A real result already captured or
|
|
@@ -1390,6 +2013,10 @@ export async function handleToolResult(
|
|
|
1390
2013
|
) {
|
|
1391
2014
|
return;
|
|
1392
2015
|
}
|
|
2016
|
+
// Buffer the RAW content: every persist path redacts exactly once via
|
|
2017
|
+
// `buildToolResultBlocks`, and buffering already-redacted bytes would
|
|
2018
|
+
// redact twice — a candidate value overlapping the marker's own text
|
|
2019
|
+
// would corrupt the persisted marker on the second pass.
|
|
1393
2020
|
state.pendingToolResults.set(event.toolUseId, {
|
|
1394
2021
|
content: event.content,
|
|
1395
2022
|
isError: event.isError,
|
|
@@ -1398,7 +2025,7 @@ export async function handleToolResult(
|
|
|
1398
2025
|
deps.onEvent({
|
|
1399
2026
|
type: "tool_result",
|
|
1400
2027
|
toolName: "",
|
|
1401
|
-
result:
|
|
2028
|
+
result: redactedContent,
|
|
1402
2029
|
isError: event.isError,
|
|
1403
2030
|
conversationId: deps.ctx.conversationId,
|
|
1404
2031
|
messageId: state.lastAssistantMessageId,
|
|
@@ -1432,6 +2059,12 @@ export async function handleToolResult(
|
|
|
1432
2059
|
// Perform state mutations before deps.onEvent() so that if onEvent throws
|
|
1433
2060
|
// (e.g. SSE disconnection) and the error is suppressed by dispatchAgentEvent,
|
|
1434
2061
|
// critical state like pendingToolResults and currentToolUseId is still updated.
|
|
2062
|
+
// Buffer the RAW content: every persist path redacts exactly once via
|
|
2063
|
+
// `buildToolResultBlocks` (with the fullest candidate set at flush time),
|
|
2064
|
+
// so wire and storage still agree. Buffering the already-redacted bytes
|
|
2065
|
+
// would redact twice — a candidate value that overlaps the marker's own
|
|
2066
|
+
// text (e.g. a manual value `redacted`) would match inside the
|
|
2067
|
+
// first-pass marker and corrupt the persisted row.
|
|
1435
2068
|
state.pendingToolResults.set(event.toolUseId, {
|
|
1436
2069
|
content: event.content,
|
|
1437
2070
|
isError: event.isError,
|
|
@@ -1539,10 +2172,12 @@ export async function handleToolResult(
|
|
|
1539
2172
|
}
|
|
1540
2173
|
|
|
1541
2174
|
// Send to client last so state is consistent even if onEvent throws.
|
|
2175
|
+
// `result` carries the reveal-redacted stdout (see above) so the live tool
|
|
2176
|
+
// card never shows a revealed plaintext the persisted row hides.
|
|
1542
2177
|
deps.onEvent({
|
|
1543
2178
|
type: "tool_result",
|
|
1544
2179
|
toolName: "",
|
|
1545
|
-
result:
|
|
2180
|
+
result: redactedContent,
|
|
1546
2181
|
isError: event.isError,
|
|
1547
2182
|
diff: event.diff,
|
|
1548
2183
|
status: event.status,
|
|
@@ -1604,12 +2239,7 @@ function recordToolStartOnPersistedMessage(
|
|
|
1604
2239
|
return;
|
|
1605
2240
|
}
|
|
1606
2241
|
|
|
1607
|
-
|
|
1608
|
-
try {
|
|
1609
|
-
content = JSON.parse(row.content) as ContentBlock[];
|
|
1610
|
-
} catch {
|
|
1611
|
-
return;
|
|
1612
|
-
}
|
|
2242
|
+
const content: ContentBlock[] = row.content;
|
|
1613
2243
|
|
|
1614
2244
|
for (const block of content) {
|
|
1615
2245
|
if (block.type !== "tool_use") {
|
|
@@ -1663,12 +2293,7 @@ function recordToolPreviewStartOnPersistedMessage(
|
|
|
1663
2293
|
return;
|
|
1664
2294
|
}
|
|
1665
2295
|
|
|
1666
|
-
|
|
1667
|
-
try {
|
|
1668
|
-
content = JSON.parse(row.content) as ContentBlock[];
|
|
1669
|
-
} catch {
|
|
1670
|
-
return;
|
|
1671
|
-
}
|
|
2296
|
+
const content: ContentBlock[] = row.content;
|
|
1672
2297
|
|
|
1673
2298
|
for (const block of content) {
|
|
1674
2299
|
if (block.type !== "tool_use") {
|
|
@@ -1717,12 +2342,7 @@ function annotatePersistedAssistantMessage(
|
|
|
1717
2342
|
return;
|
|
1718
2343
|
}
|
|
1719
2344
|
|
|
1720
|
-
|
|
1721
|
-
try {
|
|
1722
|
-
content = JSON.parse(row.content) as ContentBlock[];
|
|
1723
|
-
} catch {
|
|
1724
|
-
return;
|
|
1725
|
-
}
|
|
2345
|
+
const content: ContentBlock[] = row.content;
|
|
1726
2346
|
|
|
1727
2347
|
let modified = false;
|
|
1728
2348
|
for (const block of content) {
|
|
@@ -1993,18 +2613,42 @@ export async function handleMessageComplete(
|
|
|
1993
2613
|
state.pendingPartialFlushPromise = undefined;
|
|
1994
2614
|
}
|
|
1995
2615
|
|
|
1996
|
-
// Flush any remaining directive display buffer
|
|
1997
|
-
|
|
2616
|
+
// Flush any remaining directive display buffer, prepending live text the
|
|
2617
|
+
// sentinel guard held back (a split trigger or candidate-prefix tail).
|
|
2618
|
+
// The concatenation is candidate-swapped and gap-neutralized as a whole:
|
|
2619
|
+
// at end-of-message nothing can complete a partial trigger (a completed
|
|
2620
|
+
// one here would be a forged sentinel), and a reveal-candidate plaintext
|
|
2621
|
+
// that completes across the two buffers still swaps to its sentinel.
|
|
2622
|
+
const trailingLiveText =
|
|
2623
|
+
state.pendingSentinelGuardBuffer + state.pendingDirectiveDisplayBuffer;
|
|
2624
|
+
if (trailingLiveText.length > 0) {
|
|
2625
|
+
// Same barrier as the text-delta path: the flush below swaps against
|
|
2626
|
+
// `liveRevealGuardEntries`, so an in-flight priming must settle first.
|
|
2627
|
+
await awaitLiveRevealGuardReady(state);
|
|
1998
2628
|
deps.onEvent({
|
|
1999
2629
|
type: "assistant_text_delta",
|
|
2000
|
-
text:
|
|
2630
|
+
text: neutralizeAndSwapLiveRevealValues(
|
|
2631
|
+
trailingLiveText,
|
|
2632
|
+
state.liveRevealGuardEntries,
|
|
2633
|
+
liveRemintAuthorities(state, deps),
|
|
2634
|
+
),
|
|
2001
2635
|
conversationId: deps.ctx.conversationId,
|
|
2002
2636
|
messageId: state.lastAssistantMessageId,
|
|
2003
2637
|
});
|
|
2638
|
+
// The hub stamps `seq` synchronously on the delta emitted above, so
|
|
2639
|
+
// `getCurrentSeq()` is that delta's position — advance the persisted-seq
|
|
2640
|
+
// mirror exactly like the normal text-delta path. The finalize below
|
|
2641
|
+
// records this value; without the advance it would record the PREVIOUS
|
|
2642
|
+
// emitted chunk's seq, so a `/messages` snapshot could contain this tail
|
|
2643
|
+
// while advertising a seq before the delta that carried it — and a
|
|
2644
|
+
// reconnecting client applying `seq > snapshot.seq` would append the
|
|
2645
|
+
// tail a second time.
|
|
2646
|
+
state.lastPersistedContentSeq = getCurrentSeq();
|
|
2004
2647
|
if (deps.shouldGenerateTitle) {
|
|
2005
2648
|
state.firstAssistantText += state.pendingDirectiveDisplayBuffer;
|
|
2006
2649
|
}
|
|
2007
2650
|
state.pendingDirectiveDisplayBuffer = "";
|
|
2651
|
+
state.pendingSentinelGuardBuffer = "";
|
|
2008
2652
|
}
|
|
2009
2653
|
|
|
2010
2654
|
// Finalize the grouped tool-result row. Each result was persisted into this
|
|
@@ -2051,11 +2695,15 @@ export async function handleMessageComplete(
|
|
|
2051
2695
|
// redacted) via the shared helper. The partial-persist flush uses
|
|
2052
2696
|
// the same helper with `surfaces=[]` so a mid-turn snapshot lands in
|
|
2053
2697
|
// the same shape as the finalize.
|
|
2698
|
+
const finalRevealCandidates = await chatRevealCandidates(state);
|
|
2054
2699
|
const contentForPersistence = stampThinkingTiming(
|
|
2055
2700
|
buildPersistedAssistantContent(
|
|
2056
2701
|
event.message.content as ContentBlock[],
|
|
2057
2702
|
deps.ctx.currentTurnSurfaces,
|
|
2058
2703
|
state.toolActivityMetadata,
|
|
2704
|
+
finalRevealCandidates,
|
|
2705
|
+
await resolvedRevealCandidatesForState(state),
|
|
2706
|
+
persistRemintAuthorities(state, deps, finalRevealCandidates),
|
|
2059
2707
|
),
|
|
2060
2708
|
state.currentThinkingTimestamps,
|
|
2061
2709
|
);
|
|
@@ -2074,12 +2722,24 @@ export async function handleMessageComplete(
|
|
|
2074
2722
|
);
|
|
2075
2723
|
}
|
|
2076
2724
|
const contentJson = JSON.stringify(contentForPersistence);
|
|
2077
|
-
|
|
2725
|
+
// Stamp the served model carried on the event (`response.model`, the same
|
|
2726
|
+
// value `llm_usage` records) onto the row alongside the content, so turn-trace
|
|
2727
|
+
// assembly can attribute each assistant message to the model that actually
|
|
2728
|
+
// ran it — including per-call reroutes by a `pre-model-call` hook. Absent on
|
|
2729
|
+
// synthesized completions with no provider response; the key is omitted then.
|
|
2730
|
+
const persisted = await finalizeInflightContent(
|
|
2731
|
+
state.inflightWriters.get(assistantMessageId),
|
|
2078
2732
|
assistantMessageId,
|
|
2079
2733
|
contentJson,
|
|
2080
|
-
"finalize_assistant_message",
|
|
2081
2734
|
deps.rlog,
|
|
2735
|
+
event.model ? { model: event.model } : undefined,
|
|
2082
2736
|
);
|
|
2737
|
+
// Keep the writer on a failed finalize (e.g. persistent SQLITE_BUSY) so
|
|
2738
|
+
// the turn tail's stranded fold can retry — deleting it would leave the
|
|
2739
|
+
// row `finalized = 0` in a live daemon until crash recovery.
|
|
2740
|
+
if (persisted) {
|
|
2741
|
+
state.inflightWriters.delete(assistantMessageId);
|
|
2742
|
+
}
|
|
2083
2743
|
state.assistantRowAwaitingFinalization = false;
|
|
2084
2744
|
// The assistant row now holds the authoritative content (text + thinking +
|
|
2085
2745
|
// tool_use blocks from `event.message`), and any drained tool-result rows
|
|
@@ -2359,6 +3019,11 @@ export async function dispatchAgentEvent(
|
|
|
2359
3019
|
await handleLlmCallStarted(state, deps);
|
|
2360
3020
|
break;
|
|
2361
3021
|
case "text_delta":
|
|
3022
|
+
// Reveal-guard barrier: if a `credentials reveal` tool_use just
|
|
3023
|
+
// started priming the live guard, resolve it before this delta is
|
|
3024
|
+
// guarded — otherwise a fast reveal echo could cross SSE with an
|
|
3025
|
+
// empty entry list. Steady state awaits nothing.
|
|
3026
|
+
await awaitLiveRevealGuardReady(state);
|
|
2362
3027
|
handleTextDelta(state, deps, event);
|
|
2363
3028
|
break;
|
|
2364
3029
|
case "thinking_delta":
|