@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
|
@@ -2,6 +2,7 @@ import { execFile, spawn, spawnSync } from "node:child_process";
|
|
|
2
2
|
import {
|
|
3
3
|
chmodSync,
|
|
4
4
|
existsSync,
|
|
5
|
+
lstatSync,
|
|
5
6
|
mkdirSync,
|
|
6
7
|
readFileSync,
|
|
7
8
|
unlinkSync,
|
|
@@ -60,6 +61,7 @@ function cleanGitEnv(workspaceDir: string): Record<string, string> {
|
|
|
60
61
|
* These are written to .gitignore on init and appended to existing .gitignore files.
|
|
61
62
|
*/
|
|
62
63
|
const WORKSPACE_GITIGNORE_RULES = [
|
|
64
|
+
// Runtime state directories
|
|
63
65
|
"data/db/",
|
|
64
66
|
"data/qdrant/",
|
|
65
67
|
"data/monitoring/",
|
|
@@ -69,25 +71,130 @@ const WORKSPACE_GITIGNORE_RULES = [
|
|
|
69
71
|
"data/apps/*/records/",
|
|
70
72
|
"data/apps/*/dist/",
|
|
71
73
|
"data/apps/*.preview",
|
|
72
|
-
|
|
74
|
+
// Runtime-managed installs and caches — large and restorable
|
|
75
|
+
"/embedding-models/",
|
|
76
|
+
"/external/",
|
|
77
|
+
"/bin/",
|
|
78
|
+
"/plugins-data/",
|
|
79
|
+
"node_modules/",
|
|
80
|
+
"__pycache__/",
|
|
81
|
+
".venv/",
|
|
82
|
+
// Logs and process state
|
|
73
83
|
"logs/",
|
|
74
84
|
"*.log",
|
|
85
|
+
"*.jsonl",
|
|
75
86
|
"*.sock",
|
|
76
87
|
"*.pid",
|
|
77
|
-
"
|
|
78
|
-
"*.sqlite-journal",
|
|
79
|
-
"*.sqlite-wal",
|
|
80
|
-
"*.sqlite-shm",
|
|
81
|
-
"*.db",
|
|
82
|
-
"*.db-journal",
|
|
83
|
-
"*.db-wal",
|
|
84
|
-
"*.db-shm",
|
|
85
|
-
"vellum.pid",
|
|
88
|
+
"daemon-startup.lock",
|
|
86
89
|
"session-token",
|
|
90
|
+
// Databases (covers sidecar -journal/-wal/-shm files)
|
|
91
|
+
"*.sqlite*",
|
|
92
|
+
"*.db",
|
|
93
|
+
"*.db-*",
|
|
94
|
+
// OS junk
|
|
95
|
+
".DS_Store",
|
|
96
|
+
// Archives and disk images
|
|
97
|
+
"*.zip",
|
|
98
|
+
"*.tar",
|
|
99
|
+
"*.gz",
|
|
100
|
+
"*.tgz",
|
|
101
|
+
"*.bz2",
|
|
102
|
+
"*.xz",
|
|
103
|
+
"*.7z",
|
|
104
|
+
"*.rar",
|
|
105
|
+
"*.dmg",
|
|
106
|
+
"*.iso",
|
|
107
|
+
// Images (svg is text-based and stays tracked)
|
|
108
|
+
"*.png",
|
|
109
|
+
"*.jpg",
|
|
110
|
+
"*.jpeg",
|
|
111
|
+
"*.gif",
|
|
112
|
+
"*.webp",
|
|
113
|
+
"*.heic",
|
|
114
|
+
"*.bmp",
|
|
115
|
+
"*.tiff",
|
|
116
|
+
// Audio and video
|
|
117
|
+
"*.mp3",
|
|
118
|
+
"*.wav",
|
|
119
|
+
"*.m4a",
|
|
120
|
+
"*.flac",
|
|
121
|
+
"*.ogg",
|
|
122
|
+
"*.mp4",
|
|
123
|
+
"*.mov",
|
|
124
|
+
"*.avi",
|
|
125
|
+
"*.mkv",
|
|
126
|
+
"*.webm",
|
|
127
|
+
// Documents and model weights
|
|
128
|
+
"*.pdf",
|
|
129
|
+
"*.gguf",
|
|
130
|
+
"*.onnx",
|
|
131
|
+
"*.safetensors",
|
|
132
|
+
"*.pt",
|
|
133
|
+
"*.pth",
|
|
134
|
+
// Canonical user state re-included despite the extension rules above.
|
|
135
|
+
// Must stay after the extension rules: last matching pattern wins.
|
|
136
|
+
// (Not a broad !data/apps/** — that would also re-include dist/.)
|
|
137
|
+
// conversations/ holds the messages.jsonl disk view that DB recovery
|
|
138
|
+
// rebuilds from, so it survives the *.jsonl rule.
|
|
139
|
+
"!data/avatar/**",
|
|
140
|
+
"!data/sounds/**",
|
|
141
|
+
"!data/apps/*/icon.png",
|
|
142
|
+
"!conversations/**",
|
|
143
|
+
];
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Paths exempt from the oversized-file guard. Mirrors the `!` re-include
|
|
147
|
+
* rules in WORKSPACE_GITIGNORE_RULES above: canonical state the product
|
|
148
|
+
* explicitly insists on tracking (e.g. conversation disk views that DB
|
|
149
|
+
* recovery rebuilds from) must keep committing even past
|
|
150
|
+
* workspaceGit.maxFileSizeBytes. Keep in sync with the negation rules.
|
|
151
|
+
*/
|
|
152
|
+
const SIZE_GUARD_EXEMPT_PATTERNS: RegExp[] = [
|
|
153
|
+
/^conversations\//,
|
|
154
|
+
/^data\/avatar\//,
|
|
155
|
+
/^data\/sounds\//,
|
|
156
|
+
/^data\/apps\/[^/]+\/icon\.png$/,
|
|
87
157
|
];
|
|
88
158
|
|
|
159
|
+
function isSizeGuardExempt(relPath: string): boolean {
|
|
160
|
+
return SIZE_GUARD_EXEMPT_PATTERNS.some((re) => re.test(relPath));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** Default identity for automated workspace commits. */
|
|
164
|
+
const DEFAULT_GIT_NAME = "Vellum Assistant";
|
|
165
|
+
// generic-examples:ignore-next-line — reason: real daemon commit identity, not an example
|
|
166
|
+
const DEFAULT_GIT_EMAIL = "assistant@vellum.ai";
|
|
167
|
+
|
|
89
168
|
const NULL_GIT_OID = "0000000000000000000000000000000000000000";
|
|
90
169
|
|
|
170
|
+
/**
|
|
171
|
+
* Git's well-known empty tree object id, used as the diff/reset base when
|
|
172
|
+
* HEAD does not exist yet (unborn branch, before the initial commit).
|
|
173
|
+
*/
|
|
174
|
+
const EMPTY_TREE_OID = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
|
|
175
|
+
|
|
176
|
+
const DEFAULT_MAX_FILE_SIZE_BYTES = 256000;
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* History compaction keeps commits younger than this; older ones are
|
|
180
|
+
* squashed into a scrubbed base commit so oversized blobs referenced only
|
|
181
|
+
* by old history can be pruned from .git.
|
|
182
|
+
*/
|
|
183
|
+
const HISTORY_RETENTION_DAYS = 7;
|
|
184
|
+
|
|
185
|
+
/** Timeout for one-shot history rewrite / gc operations. */
|
|
186
|
+
const HISTORY_COMPACTION_TIMEOUT_MS = 10 * 60_000;
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Delay between init and the first compaction attempt, so boot-time
|
|
190
|
+
* foreground work (first turn commit, status reads) never queues on the
|
|
191
|
+
* git mutex behind a detection scan or rewrite.
|
|
192
|
+
*/
|
|
193
|
+
const HISTORY_COMPACTION_INITIAL_DELAY_MS = 60_000;
|
|
194
|
+
|
|
195
|
+
/** Lower bound between compaction retries while blobs wait out retention. */
|
|
196
|
+
const HISTORY_COMPACTION_MIN_RETRY_MS = 60 * 60_000;
|
|
197
|
+
|
|
91
198
|
const WORKSPACE_BRANCH_GUARD_HOOK = `#!/bin/sh
|
|
92
199
|
set -eu
|
|
93
200
|
|
|
@@ -121,6 +228,32 @@ done
|
|
|
121
228
|
exit 0
|
|
122
229
|
`;
|
|
123
230
|
|
|
231
|
+
/**
|
|
232
|
+
* Parse NUL-terminated `git status --porcelain -z` output into status/path
|
|
233
|
+
* pairs. NUL termination is required so paths with special characters
|
|
234
|
+
* (non-ASCII, quotes, newlines) arrive verbatim instead of C-style quoted.
|
|
235
|
+
* A rename/copy record is followed by a bare origin-path entry, which is
|
|
236
|
+
* skipped.
|
|
237
|
+
*/
|
|
238
|
+
function parsePorcelainZ(
|
|
239
|
+
stdout: string,
|
|
240
|
+
): Array<{ status: string; path: string }> {
|
|
241
|
+
const entries = stdout.split("\0");
|
|
242
|
+
const parsed: Array<{ status: string; path: string }> = [];
|
|
243
|
+
for (let i = 0; i < entries.length; i++) {
|
|
244
|
+
const entry = entries[i] ?? "";
|
|
245
|
+
if (entry.length < 4) {
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
const status = entry.substring(0, 2);
|
|
249
|
+
parsed.push({ status, path: entry.substring(3) });
|
|
250
|
+
if (status[0] === "R" || status[0] === "C") {
|
|
251
|
+
i++;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return parsed;
|
|
255
|
+
}
|
|
256
|
+
|
|
124
257
|
/** Properties added by Node's child_process errors. */
|
|
125
258
|
interface ExecError extends Error {
|
|
126
259
|
killed?: boolean;
|
|
@@ -155,6 +288,7 @@ interface GitStatus {
|
|
|
155
288
|
* - Mutex-protected operations: prevents concurrent git command conflicts
|
|
156
289
|
* - Handles both new and existing workspaces transparently
|
|
157
290
|
* - Synchronous initial commit within mutex to prevent races
|
|
291
|
+
* - Size guard: files over workspaceGit.maxFileSizeBytes never enter commits
|
|
158
292
|
*/
|
|
159
293
|
export class WorkspaceGitService {
|
|
160
294
|
private readonly workspaceDir: string;
|
|
@@ -165,6 +299,10 @@ export class WorkspaceGitService {
|
|
|
165
299
|
private nextAllowedAttemptMs = 0;
|
|
166
300
|
private initConsecutiveFailures = 0;
|
|
167
301
|
private initNextAllowedAttemptMs = 0;
|
|
302
|
+
/** Oversized paths already logged, to avoid re-warning every commit cycle. */
|
|
303
|
+
private readonly warnedOversizedPaths = new Set<string>();
|
|
304
|
+
private historyCompactionTimer: ReturnType<typeof setTimeout> | null = null;
|
|
305
|
+
private historyCompactionDueAtMs = 0;
|
|
168
306
|
|
|
169
307
|
constructor(workspaceDir: string) {
|
|
170
308
|
this.workspaceDir = workspaceDir;
|
|
@@ -434,13 +572,19 @@ export class WorkspaceGitService {
|
|
|
434
572
|
// created before these helpers existed, or by external tools.
|
|
435
573
|
// These calls are OUTSIDE the rev-parse try/catch so that
|
|
436
574
|
// normalization errors are not misclassified as "no commits".
|
|
437
|
-
this.ensureGitignoreRulesLocked();
|
|
438
575
|
this.ensureBranchGuardHookLocked();
|
|
439
576
|
await this.ensureCommitIdentityLocked();
|
|
440
577
|
await this.ensureBranchGuardConfigLocked();
|
|
441
578
|
await this.ensureOnMainLocked();
|
|
579
|
+
// After the main switch: ensureOnMainLocked can discard
|
|
580
|
+
// local changes, which would wipe appended gitignore rules
|
|
581
|
+
// and staged deletions alike.
|
|
582
|
+
this.ensureGitignoreRulesLocked();
|
|
583
|
+
await this.untrackIgnoredFilesLocked();
|
|
584
|
+
await this.untrackOversizedFilesLocked();
|
|
442
585
|
this.initialized = true;
|
|
443
586
|
this.recordInitSuccess();
|
|
587
|
+
this.scheduleHistoryCompaction();
|
|
444
588
|
return;
|
|
445
589
|
}
|
|
446
590
|
}
|
|
@@ -450,15 +594,20 @@ export class WorkspaceGitService {
|
|
|
450
594
|
// Initialize new git repository
|
|
451
595
|
await this.execGit(["init", "-b", "main"]);
|
|
452
596
|
|
|
453
|
-
// Run normalization (
|
|
597
|
+
// Run normalization (identity + branch enforcement + gitignore).
|
|
454
598
|
// For fresh `git init -b main` the branch is already main, but
|
|
455
599
|
// in the corruption-recovery path we fall through here after
|
|
456
600
|
// removing .git, so branch enforcement is still useful.
|
|
457
|
-
this.ensureGitignoreRulesLocked();
|
|
458
601
|
this.ensureBranchGuardHookLocked();
|
|
459
602
|
await this.ensureCommitIdentityLocked();
|
|
460
603
|
await this.ensureBranchGuardConfigLocked();
|
|
461
604
|
await this.ensureOnMainLocked();
|
|
605
|
+
// After the main switch (see above). A partial init (`.git`
|
|
606
|
+
// exists, no commit) can carry staged now-ignored paths from an
|
|
607
|
+
// interrupted `git add -A`; untracking must precede the initial
|
|
608
|
+
// commit.
|
|
609
|
+
this.ensureGitignoreRulesLocked();
|
|
610
|
+
await this.untrackIgnoredFilesLocked();
|
|
462
611
|
|
|
463
612
|
// Create initial commit synchronously within the lock to prevent
|
|
464
613
|
// races with the first commitChanges() call. Without this, the
|
|
@@ -474,7 +623,7 @@ export class WorkspaceGitService {
|
|
|
474
623
|
(f) => !autoCreatedInitFiles.has(f),
|
|
475
624
|
);
|
|
476
625
|
|
|
477
|
-
await this.
|
|
626
|
+
await this.stageAllLocked();
|
|
478
627
|
|
|
479
628
|
const message = hasExistingFiles
|
|
480
629
|
? "Initial commit: migrated existing workspace"
|
|
@@ -506,8 +655,8 @@ export class WorkspaceGitService {
|
|
|
506
655
|
await this.mutex.withLock(async () => {
|
|
507
656
|
this.cleanStaleLockFile();
|
|
508
657
|
|
|
509
|
-
// Stage all changes
|
|
510
|
-
await this.
|
|
658
|
+
// Stage all changes (minus oversized files)
|
|
659
|
+
await this.stageAllLocked();
|
|
511
660
|
|
|
512
661
|
// Build commit message with metadata if provided
|
|
513
662
|
let fullMessage = message;
|
|
@@ -652,7 +801,7 @@ export class WorkspaceGitService {
|
|
|
652
801
|
return { committed: false, status, didRunGit: true as const };
|
|
653
802
|
}
|
|
654
803
|
|
|
655
|
-
await this.
|
|
804
|
+
await this.stageAllLocked();
|
|
656
805
|
|
|
657
806
|
// Verify something was actually staged. Another service instance
|
|
658
807
|
// (or external process) could have committed between our status
|
|
@@ -709,18 +858,23 @@ export class WorkspaceGitService {
|
|
|
709
858
|
private async getStatusInternal(): Promise<GitStatus> {
|
|
710
859
|
// Streamed via spawn (not execFile) so an oversized status from a bloated
|
|
711
860
|
// working tree cannot exceed Node's default 1 MB maxBuffer and fail.
|
|
712
|
-
|
|
861
|
+
// --untracked-files=all enumerates files inside untracked directories
|
|
862
|
+
// instead of a "dir/" placeholder, so the per-file size filter below can
|
|
863
|
+
// see them — otherwise a directory holding only oversized files would
|
|
864
|
+
// keep the workspace dirty forever. -z delivers special-character paths
|
|
865
|
+
// verbatim (unquoted) for the same reason.
|
|
866
|
+
const { stdout } = await this.execGitStreaming([
|
|
867
|
+
"status",
|
|
868
|
+
"--porcelain",
|
|
869
|
+
"--untracked-files=all",
|
|
870
|
+
"-z",
|
|
871
|
+
]);
|
|
713
872
|
|
|
714
873
|
const staged: string[] = [];
|
|
715
874
|
const modified: string[] = [];
|
|
716
875
|
const untracked: string[] = [];
|
|
717
876
|
|
|
718
|
-
for (const
|
|
719
|
-
if (!line) continue;
|
|
720
|
-
|
|
721
|
-
const status = line.substring(0, 2);
|
|
722
|
-
const file = line.substring(3);
|
|
723
|
-
|
|
877
|
+
for (const { status, path: file } of parsePorcelainZ(stdout)) {
|
|
724
878
|
// First character is staged status, second is working tree status
|
|
725
879
|
const stagedStatus = status[0];
|
|
726
880
|
const workingStatus = status[1];
|
|
@@ -728,10 +882,16 @@ export class WorkspaceGitService {
|
|
|
728
882
|
if (stagedStatus !== " " && stagedStatus !== "?") {
|
|
729
883
|
staged.push(file);
|
|
730
884
|
}
|
|
885
|
+
// Oversized files are invisible to auto-commit: they can never be
|
|
886
|
+
// committed (stageAllLocked unstages them), so reporting them here
|
|
887
|
+
// would keep the workspace permanently dirty and make every turn /
|
|
888
|
+
// heartbeat cycle re-attempt a commit that stages nothing.
|
|
731
889
|
if (workingStatus === "M" || workingStatus === "D") {
|
|
732
|
-
|
|
890
|
+
if (!this.isOversized(file)) {
|
|
891
|
+
modified.push(file);
|
|
892
|
+
}
|
|
733
893
|
}
|
|
734
|
-
if (status === "??") {
|
|
894
|
+
if (status === "??" && !this.isOversized(file)) {
|
|
735
895
|
untracked.push(file);
|
|
736
896
|
}
|
|
737
897
|
}
|
|
@@ -745,6 +905,627 @@ export class WorkspaceGitService {
|
|
|
745
905
|
};
|
|
746
906
|
}
|
|
747
907
|
|
|
908
|
+
private maxFileSizeBytes(): number {
|
|
909
|
+
return (
|
|
910
|
+
getConfig().workspaceGit?.maxFileSizeBytes ?? DEFAULT_MAX_FILE_SIZE_BYTES
|
|
911
|
+
);
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
/**
|
|
915
|
+
* Working-tree size check for a repo-relative path. Uses lstat so a
|
|
916
|
+
* symlink is measured by the link itself, not its target. Missing or
|
|
917
|
+
* unreadable paths (deletions, races) are treated as not oversized.
|
|
918
|
+
*/
|
|
919
|
+
private isOversized(relPath: string): boolean {
|
|
920
|
+
if (isSizeGuardExempt(relPath)) {
|
|
921
|
+
return false;
|
|
922
|
+
}
|
|
923
|
+
try {
|
|
924
|
+
const stats = lstatSync(join(this.workspaceDir, relPath));
|
|
925
|
+
return stats.isFile() && stats.size > this.maxFileSizeBytes();
|
|
926
|
+
} catch {
|
|
927
|
+
return false;
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
/**
|
|
932
|
+
* Resolve the base for staged-change comparisons: HEAD when it exists,
|
|
933
|
+
* the empty tree on an unborn branch. Transient git errors propagate so
|
|
934
|
+
* callers abort instead of diffing/resetting against the wrong base.
|
|
935
|
+
*/
|
|
936
|
+
private async resolveStagedDiffBaseLocked(): Promise<string> {
|
|
937
|
+
try {
|
|
938
|
+
await this.execGit(["rev-parse", "--quiet", "--verify", "HEAD"]);
|
|
939
|
+
return "HEAD";
|
|
940
|
+
} catch (err) {
|
|
941
|
+
if ((err as ExecError).code === 1) {
|
|
942
|
+
return EMPTY_TREE_OID;
|
|
943
|
+
}
|
|
944
|
+
throw err;
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
/**
|
|
949
|
+
* Drop tracked files whose on-disk size exceeds
|
|
950
|
+
* workspaceGit.maxFileSizeBytes from the index (working tree untouched) —
|
|
951
|
+
* files committed before the size guard existed, or before a limit
|
|
952
|
+
* decrease. Blobs referenced by older commits remain in .git. Like
|
|
953
|
+
* {@link untrackIgnoredFilesLocked}, the staged deletions ride along with
|
|
954
|
+
* the next commit and failures are logged, never blocking init. Must be
|
|
955
|
+
* called with the mutex lock held.
|
|
956
|
+
*/
|
|
957
|
+
private async untrackOversizedFilesLocked(): Promise<void> {
|
|
958
|
+
try {
|
|
959
|
+
const tracked = await this.execGitStreaming(["ls-files", "-z"]);
|
|
960
|
+
const oversized = tracked.stdout
|
|
961
|
+
.split("\0")
|
|
962
|
+
.filter((p) => p.length > 0 && this.isOversized(p));
|
|
963
|
+
if (oversized.length === 0) {
|
|
964
|
+
return;
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
await this.execGitStreaming(
|
|
968
|
+
[
|
|
969
|
+
"rm",
|
|
970
|
+
"--cached",
|
|
971
|
+
"-q",
|
|
972
|
+
"--ignore-unmatch",
|
|
973
|
+
"--pathspec-from-file=-",
|
|
974
|
+
"--pathspec-file-nul",
|
|
975
|
+
],
|
|
976
|
+
{ input: oversized.map((p) => `:(literal)${p}`).join("\0") },
|
|
977
|
+
);
|
|
978
|
+
|
|
979
|
+
for (const p of oversized) {
|
|
980
|
+
this.warnedOversizedPaths.add(p);
|
|
981
|
+
}
|
|
982
|
+
log.warn(
|
|
983
|
+
{
|
|
984
|
+
workspaceDir: this.workspaceDir,
|
|
985
|
+
files: oversized,
|
|
986
|
+
maxFileSizeBytes: this.maxFileSizeBytes(),
|
|
987
|
+
},
|
|
988
|
+
"Untracked oversized files from workspace index",
|
|
989
|
+
);
|
|
990
|
+
} catch (err) {
|
|
991
|
+
log.warn({ err }, "Failed to untrack oversized files");
|
|
992
|
+
}
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
/**
|
|
996
|
+
* Schedule a background history compaction attempt. The delay keeps the
|
|
997
|
+
* run off the git mutex during boot, so foreground commits and status
|
|
998
|
+
* reads are never queued behind a rewrite. When blobs exist but all
|
|
999
|
+
* history is still within retention, the attempt reschedules itself for
|
|
1000
|
+
* when the oldest commit ages past the cutoff. Best-effort like the
|
|
1001
|
+
* untrack sweeps: failures are logged and never affect commits.
|
|
1002
|
+
*/
|
|
1003
|
+
private scheduleHistoryCompaction(
|
|
1004
|
+
delayMs = HISTORY_COMPACTION_INITIAL_DELAY_MS,
|
|
1005
|
+
): void {
|
|
1006
|
+
const dueAtMs = Date.now() + delayMs;
|
|
1007
|
+
if (this.historyCompactionTimer) {
|
|
1008
|
+
if (dueAtMs >= this.historyCompactionDueAtMs) {
|
|
1009
|
+
// An earlier-or-equal run is already pending; it covers this request.
|
|
1010
|
+
return;
|
|
1011
|
+
}
|
|
1012
|
+
// A retention retry can be days out — a fresh request (e.g. a newly
|
|
1013
|
+
// unstaged external blob) must not wait behind it.
|
|
1014
|
+
clearTimeout(this.historyCompactionTimer);
|
|
1015
|
+
this.historyCompactionTimer = null;
|
|
1016
|
+
}
|
|
1017
|
+
const timer = setTimeout(() => {
|
|
1018
|
+
void (async () => {
|
|
1019
|
+
let retryAfterMs: number | undefined;
|
|
1020
|
+
try {
|
|
1021
|
+
const result = await this.compactHistoryNow();
|
|
1022
|
+
retryAfterMs = result.retryAfterMs;
|
|
1023
|
+
} catch (err) {
|
|
1024
|
+
log.warn(
|
|
1025
|
+
{ err, workspaceDir: this.workspaceDir },
|
|
1026
|
+
"Workspace history compaction failed",
|
|
1027
|
+
);
|
|
1028
|
+
}
|
|
1029
|
+
this.historyCompactionTimer = null;
|
|
1030
|
+
if (retryAfterMs !== undefined) {
|
|
1031
|
+
this.scheduleHistoryCompaction(retryAfterMs);
|
|
1032
|
+
}
|
|
1033
|
+
})();
|
|
1034
|
+
}, delayMs);
|
|
1035
|
+
// Never keep the process alive just for maintenance.
|
|
1036
|
+
timer.unref?.();
|
|
1037
|
+
this.historyCompactionTimer = timer;
|
|
1038
|
+
this.historyCompactionDueAtMs = dueAtMs;
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
/**
|
|
1042
|
+
* Rewrite workspace history so blobs over workspaceGit.maxFileSizeBytes
|
|
1043
|
+
* stop occupying .git. Commits older than HISTORY_RETENTION_DAYS are
|
|
1044
|
+
* squashed into a single base commit whose tree is scrubbed of oversized
|
|
1045
|
+
* entries; younger commits are replayed verbatim (trees, messages,
|
|
1046
|
+
* authors, and dates preserved); reflogs are then expired and unreachable
|
|
1047
|
+
* objects pruned. Runs only when the object store contains an oversized
|
|
1048
|
+
* blob that is actionable — unreachable, or reachable at a non-exempt
|
|
1049
|
+
* path (see SIZE_GUARD_EXEMPT_PATTERNS) — so the steady state is a cheap
|
|
1050
|
+
* detection scan and exempt canonical state never triggers rewrites.
|
|
1051
|
+
*
|
|
1052
|
+
* Oversized blobs still referenced by replayed recent commits survive
|
|
1053
|
+
* until those commits age past retention — the result carries
|
|
1054
|
+
* `retryAfterMs` so the background scheduler re-runs then, and bloat
|
|
1055
|
+
* disappears automatically within the retention window. The working
|
|
1056
|
+
* tree and index are never touched (the tip tree is reused unchanged).
|
|
1057
|
+
* Git notes attached to rewritten commits are orphaned; enrichment only
|
|
1058
|
+
* targets commits created after the rewrite, so this is cosmetic.
|
|
1059
|
+
*/
|
|
1060
|
+
async compactHistoryNow(): Promise<{
|
|
1061
|
+
rewrote: boolean;
|
|
1062
|
+
squashedCommits: number;
|
|
1063
|
+
keptCommits: number;
|
|
1064
|
+
/** Set when blobs remain but history must first age past retention. */
|
|
1065
|
+
retryAfterMs?: number;
|
|
1066
|
+
}> {
|
|
1067
|
+
await this.ensureInitialized();
|
|
1068
|
+
return this.mutex.withLock(() => this.compactHistoryLocked());
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
/**
|
|
1072
|
+
* Expire all reflogs and prune unreachable objects so dropped blobs are
|
|
1073
|
+
* physically deleted from .git. Hooks are disabled for the same reason as
|
|
1074
|
+
* in {@link buildSafeCommitArgs} — workspace hooks are model-writable and
|
|
1075
|
+
* untrusted, and gc's pack-refs would otherwise run the branch guard
|
|
1076
|
+
* against legacy refs. Must be called with the mutex lock held.
|
|
1077
|
+
*/
|
|
1078
|
+
private async expireReflogsAndPruneLocked(): Promise<void> {
|
|
1079
|
+
await this.execGit(
|
|
1080
|
+
[
|
|
1081
|
+
"-c",
|
|
1082
|
+
"core.hooksPath=/dev/null",
|
|
1083
|
+
"reflog",
|
|
1084
|
+
"expire",
|
|
1085
|
+
"--expire=now",
|
|
1086
|
+
"--expire-unreachable=now",
|
|
1087
|
+
"--all",
|
|
1088
|
+
],
|
|
1089
|
+
{ timeoutMs: HISTORY_COMPACTION_TIMEOUT_MS },
|
|
1090
|
+
);
|
|
1091
|
+
await this.execGit(
|
|
1092
|
+
["-c", "core.hooksPath=/dev/null", "gc", "--prune=now", "--quiet"],
|
|
1093
|
+
{ timeoutMs: HISTORY_COMPACTION_TIMEOUT_MS },
|
|
1094
|
+
);
|
|
1095
|
+
}
|
|
1096
|
+
|
|
1097
|
+
/**
|
|
1098
|
+
* Object ids of every blob in the object store exceeding the size limit.
|
|
1099
|
+
* Reads object metadata only — no history walk.
|
|
1100
|
+
*/
|
|
1101
|
+
private async collectOversizedBlobOidsLocked(
|
|
1102
|
+
limit: number,
|
|
1103
|
+
): Promise<Set<string>> {
|
|
1104
|
+
const objects = await this.execGitStreaming(
|
|
1105
|
+
[
|
|
1106
|
+
"cat-file",
|
|
1107
|
+
"--batch-all-objects",
|
|
1108
|
+
"--unordered",
|
|
1109
|
+
"--batch-check=%(objectname) %(objecttype) %(objectsize)",
|
|
1110
|
+
],
|
|
1111
|
+
{ timeoutMs: HISTORY_COMPACTION_TIMEOUT_MS },
|
|
1112
|
+
);
|
|
1113
|
+
const oids = new Set<string>();
|
|
1114
|
+
for (const line of objects.stdout.split("\n")) {
|
|
1115
|
+
const [oid, type, size] = line.split(" ");
|
|
1116
|
+
if (oid && type === "blob" && Number(size) > limit) {
|
|
1117
|
+
oids.add(oid);
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
return oids;
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
/**
|
|
1124
|
+
* Classify the given oversized blobs for compaction:
|
|
1125
|
+
* - "rewrite": at least one is reachable from main at a non-exempt path —
|
|
1126
|
+
* only a history rewrite removes it.
|
|
1127
|
+
* - "prunable": none require a rewrite, but at least one is referenced by
|
|
1128
|
+
* no ref at all — reflog expiry + gc reclaims it without touching
|
|
1129
|
+
* history (no hash changes, no orphaned notes).
|
|
1130
|
+
* - "none": everything is exempt canonical state (conversation disk
|
|
1131
|
+
* views) or retained by non-main refs that rewriting main can never
|
|
1132
|
+
* free — nothing to do and nothing to retry.
|
|
1133
|
+
*/
|
|
1134
|
+
private async classifyOversizedBlobsLocked(
|
|
1135
|
+
oversized: Set<string>,
|
|
1136
|
+
): Promise<"none" | "prunable" | "rewrite"> {
|
|
1137
|
+
if (oversized.size === 0) {
|
|
1138
|
+
return "none";
|
|
1139
|
+
}
|
|
1140
|
+
// Lines are "<oid>" for commits and "<oid> <path>" for trees/blobs.
|
|
1141
|
+
const fromMain = await this.execGitStreaming(
|
|
1142
|
+
["rev-list", "--objects", "main"],
|
|
1143
|
+
{ timeoutMs: HISTORY_COMPACTION_TIMEOUT_MS },
|
|
1144
|
+
);
|
|
1145
|
+
const remaining = new Set(oversized);
|
|
1146
|
+
for (const line of fromMain.stdout.split("\n")) {
|
|
1147
|
+
if (!line) {
|
|
1148
|
+
continue;
|
|
1149
|
+
}
|
|
1150
|
+
const spaceIdx = line.indexOf(" ");
|
|
1151
|
+
const oid = spaceIdx === -1 ? line : line.substring(0, spaceIdx);
|
|
1152
|
+
if (!remaining.has(oid)) {
|
|
1153
|
+
continue;
|
|
1154
|
+
}
|
|
1155
|
+
const path = spaceIdx === -1 ? "" : line.substring(spaceIdx + 1);
|
|
1156
|
+
if (isSizeGuardExempt(path)) {
|
|
1157
|
+
remaining.delete(oid);
|
|
1158
|
+
} else {
|
|
1159
|
+
return "rewrite";
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
if (remaining.size === 0) {
|
|
1163
|
+
return "none";
|
|
1164
|
+
}
|
|
1165
|
+
// Drop blobs retained by any other ref — gc keeps them regardless of
|
|
1166
|
+
// what happens to main. Whatever is left is truly unreferenced, hence
|
|
1167
|
+
// prunable.
|
|
1168
|
+
const fromAll = await this.execGitStreaming(
|
|
1169
|
+
["rev-list", "--objects", "--all"],
|
|
1170
|
+
{ timeoutMs: HISTORY_COMPACTION_TIMEOUT_MS },
|
|
1171
|
+
);
|
|
1172
|
+
for (const line of fromAll.stdout.split("\n")) {
|
|
1173
|
+
const spaceIdx = line.indexOf(" ");
|
|
1174
|
+
remaining.delete(spaceIdx === -1 ? line : line.substring(0, spaceIdx));
|
|
1175
|
+
}
|
|
1176
|
+
return remaining.size > 0 ? "prunable" : "none";
|
|
1177
|
+
}
|
|
1178
|
+
|
|
1179
|
+
private async compactHistoryLocked(): Promise<{
|
|
1180
|
+
rewrote: boolean;
|
|
1181
|
+
squashedCommits: number;
|
|
1182
|
+
keptCommits: number;
|
|
1183
|
+
retryAfterMs?: number;
|
|
1184
|
+
}> {
|
|
1185
|
+
const noop = { rewrote: false, squashedCommits: 0, keptCommits: 0 };
|
|
1186
|
+
const limit = this.maxFileSizeBytes();
|
|
1187
|
+
|
|
1188
|
+
// Any oversized blobs at all? Bounds the cost of every boot where there
|
|
1189
|
+
// is nothing to do.
|
|
1190
|
+
const oversizedOids = await this.collectOversizedBlobOidsLocked(limit);
|
|
1191
|
+
if (oversizedOids.size === 0) {
|
|
1192
|
+
return noop;
|
|
1193
|
+
}
|
|
1194
|
+
|
|
1195
|
+
// Only rewrite linear main history from its tip.
|
|
1196
|
+
const head = await this.execGit(["symbolic-ref", "--short", "HEAD"]);
|
|
1197
|
+
if (head.stdout.trim() !== "main") {
|
|
1198
|
+
return noop;
|
|
1199
|
+
}
|
|
1200
|
+
|
|
1201
|
+
// %x1f field / %x1e record separators — %B is the raw multi-line body.
|
|
1202
|
+
const logOut = await this.execGitStreaming(
|
|
1203
|
+
[
|
|
1204
|
+
"log",
|
|
1205
|
+
"--first-parent",
|
|
1206
|
+
"--reverse",
|
|
1207
|
+
"--format=%H%x1f%T%x1f%ct%x1f%an%x1f%ae%x1f%aD%x1f%cn%x1f%ce%x1f%cD%x1f%B%x1e",
|
|
1208
|
+
"main",
|
|
1209
|
+
],
|
|
1210
|
+
{ timeoutMs: HISTORY_COMPACTION_TIMEOUT_MS },
|
|
1211
|
+
);
|
|
1212
|
+
const commits = logOut.stdout
|
|
1213
|
+
.split("\x1e")
|
|
1214
|
+
.map((record) => record.replace(/^\n/, ""))
|
|
1215
|
+
.filter((record) => record.includes("\x1f"))
|
|
1216
|
+
.map((record) => {
|
|
1217
|
+
const f = record.split("\x1f");
|
|
1218
|
+
return {
|
|
1219
|
+
sha: f[0] ?? "",
|
|
1220
|
+
tree: f[1] ?? "",
|
|
1221
|
+
committedAtSec: Number(f[2] ?? "0"),
|
|
1222
|
+
authorName: f[3] ?? "",
|
|
1223
|
+
authorEmail: f[4] ?? "",
|
|
1224
|
+
authorDate: f[5] ?? "",
|
|
1225
|
+
committerName: f[6] ?? "",
|
|
1226
|
+
committerEmail: f[7] ?? "",
|
|
1227
|
+
committerDate: f[8] ?? "",
|
|
1228
|
+
body: f[9] ?? "",
|
|
1229
|
+
};
|
|
1230
|
+
});
|
|
1231
|
+
if (commits.length === 0) {
|
|
1232
|
+
return noop;
|
|
1233
|
+
}
|
|
1234
|
+
|
|
1235
|
+
const verdict = await this.classifyOversizedBlobsLocked(oversizedOids);
|
|
1236
|
+
if (verdict === "none") {
|
|
1237
|
+
// Exempt canonical state or ref-retained only — nothing to reclaim.
|
|
1238
|
+
return { ...noop, keptCommits: commits.length };
|
|
1239
|
+
}
|
|
1240
|
+
if (verdict === "prunable") {
|
|
1241
|
+
// Only unreachable blobs (e.g. an external add that stageAllLocked
|
|
1242
|
+
// reset) — prune reclaims them without rewriting any history.
|
|
1243
|
+
await this.expireReflogsAndPruneLocked();
|
|
1244
|
+
log.info(
|
|
1245
|
+
{ workspaceDir: this.workspaceDir },
|
|
1246
|
+
"Pruned unreachable oversized blobs from workspace git",
|
|
1247
|
+
);
|
|
1248
|
+
return { ...noop, keptCommits: commits.length };
|
|
1249
|
+
}
|
|
1250
|
+
|
|
1251
|
+
// Squash a PREFIX of the chain so replay order stays consistent even if
|
|
1252
|
+
// commit timestamps are not monotonic.
|
|
1253
|
+
const cutoffSec =
|
|
1254
|
+
Math.floor(Date.now() / 1000) - HISTORY_RETENTION_DAYS * 86400;
|
|
1255
|
+
let splitIdx = commits.findIndex((c) => c.committedAtSec >= cutoffSec);
|
|
1256
|
+
if (splitIdx === -1) {
|
|
1257
|
+
splitIdx = commits.length;
|
|
1258
|
+
}
|
|
1259
|
+
if (splitIdx === 0) {
|
|
1260
|
+
// Main holds the blobs, but only in commits still within retention.
|
|
1261
|
+
// A mixed case can also carry unreachable blobs — prune those now,
|
|
1262
|
+
// and re-check in case they were all that remained actionable.
|
|
1263
|
+
await this.expireReflogsAndPruneLocked();
|
|
1264
|
+
const afterPrune = await this.collectOversizedBlobOidsLocked(limit);
|
|
1265
|
+
if ((await this.classifyOversizedBlobsLocked(afterPrune)) === "none") {
|
|
1266
|
+
log.info(
|
|
1267
|
+
{ workspaceDir: this.workspaceDir },
|
|
1268
|
+
"Pruned unreachable oversized blobs from workspace git",
|
|
1269
|
+
);
|
|
1270
|
+
return { ...noop, keptCommits: commits.length };
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1273
|
+
// Report when the oldest commit ages past the cutoff so the caller
|
|
1274
|
+
// can retry then — otherwise a long-running daemon would keep the
|
|
1275
|
+
// bloat until restart.
|
|
1276
|
+
const oldestCommittedAtSec = commits[0]?.committedAtSec ?? cutoffSec;
|
|
1277
|
+
const oldestAgesOutMs =
|
|
1278
|
+
(oldestCommittedAtSec + HISTORY_RETENTION_DAYS * 86400) * 1000 -
|
|
1279
|
+
Date.now() +
|
|
1280
|
+
60_000;
|
|
1281
|
+
const retryAfterMs = Math.max(
|
|
1282
|
+
oldestAgesOutMs,
|
|
1283
|
+
HISTORY_COMPACTION_MIN_RETRY_MS,
|
|
1284
|
+
);
|
|
1285
|
+
log.debug(
|
|
1286
|
+
{ workspaceDir: this.workspaceDir, retryAfterMs },
|
|
1287
|
+
"Oversized blobs present but all history is within retention",
|
|
1288
|
+
);
|
|
1289
|
+
return { ...noop, keptCommits: commits.length, retryAfterMs };
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
const kept = commits.slice(splitIdx);
|
|
1293
|
+
const boundary = commits[splitIdx - 1];
|
|
1294
|
+
if (!boundary) {
|
|
1295
|
+
return noop;
|
|
1296
|
+
}
|
|
1297
|
+
const identityEnv = (c: (typeof commits)[number]) => ({
|
|
1298
|
+
GIT_AUTHOR_NAME: c.authorName || DEFAULT_GIT_NAME,
|
|
1299
|
+
GIT_AUTHOR_EMAIL: c.authorEmail || DEFAULT_GIT_EMAIL,
|
|
1300
|
+
GIT_AUTHOR_DATE: c.authorDate,
|
|
1301
|
+
GIT_COMMITTER_NAME: c.committerName || DEFAULT_GIT_NAME,
|
|
1302
|
+
GIT_COMMITTER_EMAIL: c.committerEmail || DEFAULT_GIT_EMAIL,
|
|
1303
|
+
GIT_COMMITTER_DATE: c.committerDate,
|
|
1304
|
+
});
|
|
1305
|
+
|
|
1306
|
+
const baseTree = await this.scrubTreeLocked(boundary.tree, limit);
|
|
1307
|
+
let newHead = (
|
|
1308
|
+
await this.execGit(
|
|
1309
|
+
[
|
|
1310
|
+
"commit-tree",
|
|
1311
|
+
baseTree,
|
|
1312
|
+
"-m",
|
|
1313
|
+
`Compacted workspace history (${splitIdx} commits squashed)`,
|
|
1314
|
+
],
|
|
1315
|
+
{ env: identityEnv(boundary) },
|
|
1316
|
+
)
|
|
1317
|
+
).stdout.trim();
|
|
1318
|
+
for (const c of kept) {
|
|
1319
|
+
newHead = (
|
|
1320
|
+
await this.execGit(
|
|
1321
|
+
[
|
|
1322
|
+
"commit-tree",
|
|
1323
|
+
c.tree,
|
|
1324
|
+
"-p",
|
|
1325
|
+
newHead,
|
|
1326
|
+
"-m",
|
|
1327
|
+
c.body.trim() || "(no message)",
|
|
1328
|
+
],
|
|
1329
|
+
{ env: identityEnv(c) },
|
|
1330
|
+
)
|
|
1331
|
+
).stdout.trim();
|
|
1332
|
+
}
|
|
1333
|
+
|
|
1334
|
+
// Compare-and-swap against the tip we read, in case an external git
|
|
1335
|
+
// process moved main while we rewrote.
|
|
1336
|
+
const oldHead = commits[commits.length - 1]?.sha ?? "";
|
|
1337
|
+
await this.execGit([
|
|
1338
|
+
"-c",
|
|
1339
|
+
"core.hooksPath=/dev/null",
|
|
1340
|
+
"update-ref",
|
|
1341
|
+
"refs/heads/main",
|
|
1342
|
+
newHead,
|
|
1343
|
+
oldHead,
|
|
1344
|
+
]);
|
|
1345
|
+
await this.expireReflogsAndPruneLocked();
|
|
1346
|
+
|
|
1347
|
+
// Blobs referenced by a replayed kept commit survive the prune (the
|
|
1348
|
+
// common case: a large file untracked only days ago). Request a retry
|
|
1349
|
+
// for when the oldest kept commit ages past retention, so they are
|
|
1350
|
+
// reclaimed without waiting for a daemon restart.
|
|
1351
|
+
let retryAfterMs: number | undefined;
|
|
1352
|
+
const afterGc = await this.collectOversizedBlobOidsLocked(limit);
|
|
1353
|
+
if ((await this.classifyOversizedBlobsLocked(afterGc)) !== "none") {
|
|
1354
|
+
const oldestKeptSec =
|
|
1355
|
+
kept[0]?.committedAtSec ?? Math.floor(Date.now() / 1000);
|
|
1356
|
+
retryAfterMs = Math.max(
|
|
1357
|
+
(oldestKeptSec + HISTORY_RETENTION_DAYS * 86400) * 1000 -
|
|
1358
|
+
Date.now() +
|
|
1359
|
+
60_000,
|
|
1360
|
+
HISTORY_COMPACTION_MIN_RETRY_MS,
|
|
1361
|
+
);
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
log.info(
|
|
1365
|
+
{
|
|
1366
|
+
workspaceDir: this.workspaceDir,
|
|
1367
|
+
squashedCommits: splitIdx,
|
|
1368
|
+
keptCommits: kept.length,
|
|
1369
|
+
maxFileSizeBytes: limit,
|
|
1370
|
+
...(retryAfterMs !== undefined ? { retryAfterMs } : {}),
|
|
1371
|
+
},
|
|
1372
|
+
"Compacted workspace git history",
|
|
1373
|
+
);
|
|
1374
|
+
return {
|
|
1375
|
+
rewrote: true,
|
|
1376
|
+
squashedCommits: splitIdx,
|
|
1377
|
+
keptCommits: kept.length,
|
|
1378
|
+
retryAfterMs,
|
|
1379
|
+
};
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
/**
|
|
1383
|
+
* Return a copy of `tree` with entries whose blob size exceeds the limit
|
|
1384
|
+
* removed, built in a temporary index so the real index is untouched.
|
|
1385
|
+
* Returns the original tree when nothing in it is oversized.
|
|
1386
|
+
*/
|
|
1387
|
+
private async scrubTreeLocked(tree: string, limit: number): Promise<string> {
|
|
1388
|
+
const listing = await this.execGitStreaming(
|
|
1389
|
+
["ls-tree", "-r", "-l", "-z", tree],
|
|
1390
|
+
{
|
|
1391
|
+
timeoutMs: HISTORY_COMPACTION_TIMEOUT_MS,
|
|
1392
|
+
},
|
|
1393
|
+
);
|
|
1394
|
+
const oversizedPaths: string[] = [];
|
|
1395
|
+
for (const entry of listing.stdout.split("\0")) {
|
|
1396
|
+
const tab = entry.indexOf("\t");
|
|
1397
|
+
if (tab < 0) {
|
|
1398
|
+
continue;
|
|
1399
|
+
}
|
|
1400
|
+
// "<mode> <type> <oid> <size>\t<path>" — size is right-aligned.
|
|
1401
|
+
const meta = entry.substring(0, tab).trim().split(/\s+/);
|
|
1402
|
+
const path = entry.substring(tab + 1);
|
|
1403
|
+
if (
|
|
1404
|
+
meta[1] === "blob" &&
|
|
1405
|
+
Number(meta[3]) > limit &&
|
|
1406
|
+
!isSizeGuardExempt(path)
|
|
1407
|
+
) {
|
|
1408
|
+
oversizedPaths.push(path);
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
if (oversizedPaths.length === 0) {
|
|
1412
|
+
return tree;
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
const tmpIndex = join(this.workspaceDir, ".git", "vellum-compact-index");
|
|
1416
|
+
const env = { GIT_INDEX_FILE: tmpIndex };
|
|
1417
|
+
try {
|
|
1418
|
+
await this.execGit(["read-tree", tree], { env });
|
|
1419
|
+
await this.execGitStreaming(
|
|
1420
|
+
[
|
|
1421
|
+
"rm",
|
|
1422
|
+
"--cached",
|
|
1423
|
+
"-q",
|
|
1424
|
+
"--ignore-unmatch",
|
|
1425
|
+
"--pathspec-from-file=-",
|
|
1426
|
+
"--pathspec-file-nul",
|
|
1427
|
+
],
|
|
1428
|
+
{ input: oversizedPaths.map((p) => `:(literal)${p}`).join("\0"), env },
|
|
1429
|
+
);
|
|
1430
|
+
return (await this.execGit(["write-tree"], { env })).stdout.trim();
|
|
1431
|
+
} finally {
|
|
1432
|
+
try {
|
|
1433
|
+
unlinkSync(tmpIndex);
|
|
1434
|
+
} catch {
|
|
1435
|
+
// Never created, or already gone.
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
/**
|
|
1441
|
+
* Stage all workspace changes except files whose working-tree size exceeds
|
|
1442
|
+
* workspaceGit.maxFileSizeBytes. Oversized files stay on disk untouched —
|
|
1443
|
+
* they just never enter workspace history. Deletions always stage (they
|
|
1444
|
+
* shrink the repo). Must be called with the lock held.
|
|
1445
|
+
*
|
|
1446
|
+
* Oversized paths are excluded from the add pathspec up front so git never
|
|
1447
|
+
* hashes their blobs: an `add` of a multi-GB artifact would be slow enough
|
|
1448
|
+
* to trip interactiveGitTimeoutMs and would bloat .git/objects even if the
|
|
1449
|
+
* file were unstaged afterwards. A post-add scan then unstages any
|
|
1450
|
+
* oversized blob that reached the index anyway (e.g. staged by an external
|
|
1451
|
+
* `git add` before this ran).
|
|
1452
|
+
*/
|
|
1453
|
+
private async stageAllLocked(): Promise<void> {
|
|
1454
|
+
// Streamed: output scales with the number of changed files.
|
|
1455
|
+
const changed = await this.execGitStreaming([
|
|
1456
|
+
"status",
|
|
1457
|
+
"--porcelain",
|
|
1458
|
+
"--untracked-files=all",
|
|
1459
|
+
"-z",
|
|
1460
|
+
]);
|
|
1461
|
+
const oversized = new Set<string>();
|
|
1462
|
+
for (const { path } of parsePorcelainZ(changed.stdout)) {
|
|
1463
|
+
if (this.isOversized(path)) {
|
|
1464
|
+
oversized.add(path);
|
|
1465
|
+
}
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
if (oversized.size === 0) {
|
|
1469
|
+
await this.execGit(["add", "-A"]);
|
|
1470
|
+
} else {
|
|
1471
|
+
// Pathspecs via stdin to stay clear of OS argv limits; literal magic
|
|
1472
|
+
// so filenames containing glob characters are not pattern-matched.
|
|
1473
|
+
const pathspecs = [
|
|
1474
|
+
".",
|
|
1475
|
+
...[...oversized].map((p) => `:(exclude,literal)${p}`),
|
|
1476
|
+
];
|
|
1477
|
+
await this.execGitStreaming(
|
|
1478
|
+
["add", "-A", "--pathspec-from-file=-", "--pathspec-file-nul"],
|
|
1479
|
+
{ input: pathspecs.join("\0") },
|
|
1480
|
+
);
|
|
1481
|
+
}
|
|
1482
|
+
|
|
1483
|
+
const base = await this.resolveStagedDiffBaseLocked();
|
|
1484
|
+
// Everything but deletions — T covers a tracked symlink/submodule
|
|
1485
|
+
// replaced by a staged regular file, which ACMR alone would miss.
|
|
1486
|
+
const staged = await this.execGitStreaming([
|
|
1487
|
+
"diff",
|
|
1488
|
+
"--cached",
|
|
1489
|
+
"--name-only",
|
|
1490
|
+
"-z",
|
|
1491
|
+
"--diff-filter=ACMRT",
|
|
1492
|
+
base,
|
|
1493
|
+
]);
|
|
1494
|
+
const stagedOversized = staged.stdout
|
|
1495
|
+
.split("\0")
|
|
1496
|
+
.filter((p) => p.length > 0 && this.isOversized(p));
|
|
1497
|
+
|
|
1498
|
+
if (stagedOversized.length > 0) {
|
|
1499
|
+
// Literal pathspecs via stdin, mirroring the add above: a filename
|
|
1500
|
+
// containing glob characters must not unstage other matching paths.
|
|
1501
|
+
await this.execGitStreaming(
|
|
1502
|
+
["reset", "-q", base, "--pathspec-from-file=-", "--pathspec-file-nul"],
|
|
1503
|
+
{ input: stagedOversized.map((p) => `:(literal)${p}`).join("\0") },
|
|
1504
|
+
);
|
|
1505
|
+
// The external add already hashed these blobs into .git/objects; a
|
|
1506
|
+
// compaction pass prunes them even if the boot-time one already ran.
|
|
1507
|
+
this.scheduleHistoryCompaction();
|
|
1508
|
+
}
|
|
1509
|
+
|
|
1510
|
+
const excluded = [...new Set([...oversized, ...stagedOversized])];
|
|
1511
|
+
const newlyWarned = excluded.filter(
|
|
1512
|
+
(p) => !this.warnedOversizedPaths.has(p),
|
|
1513
|
+
);
|
|
1514
|
+
if (newlyWarned.length > 0) {
|
|
1515
|
+
for (const p of newlyWarned) {
|
|
1516
|
+
this.warnedOversizedPaths.add(p);
|
|
1517
|
+
}
|
|
1518
|
+
log.warn(
|
|
1519
|
+
{
|
|
1520
|
+
workspaceDir: this.workspaceDir,
|
|
1521
|
+
files: newlyWarned,
|
|
1522
|
+
maxFileSizeBytes: this.maxFileSizeBytes(),
|
|
1523
|
+
},
|
|
1524
|
+
"Excluded oversized files from workspace commit",
|
|
1525
|
+
);
|
|
1526
|
+
}
|
|
1527
|
+
}
|
|
1528
|
+
|
|
748
1529
|
/**
|
|
749
1530
|
* Ensure .gitignore contains all required workspace exclusion rules.
|
|
750
1531
|
* Idempotent: checks for missing rules and only appends what's needed.
|
|
@@ -766,18 +1547,38 @@ export class WorkspaceGitService {
|
|
|
766
1547
|
}
|
|
767
1548
|
}
|
|
768
1549
|
|
|
1550
|
+
// Exact line matching: a substring check would let an existing rule like
|
|
1551
|
+
// "plugins/*/node_modules/" mask the broader "node_modules/" rule.
|
|
1552
|
+
const existingLines = new Set(
|
|
1553
|
+
content.split("\n").map((line) => line.trim()),
|
|
1554
|
+
);
|
|
769
1555
|
const missingRules = WORKSPACE_GITIGNORE_RULES.filter(
|
|
770
|
-
(rule) => !
|
|
1556
|
+
(rule) => !existingLines.has(rule),
|
|
771
1557
|
);
|
|
772
1558
|
if (hadLegacyDataRule || missingRules.length > 0) {
|
|
773
1559
|
let updated = content;
|
|
774
1560
|
if (missingRules.length > 0) {
|
|
1561
|
+
// Negation rules must trail every Vellum rule (last matching
|
|
1562
|
+
// pattern wins), so pull existing ones out and re-append them
|
|
1563
|
+
// after the additions instead of leaving them mid-file.
|
|
1564
|
+
const negationRules = WORKSPACE_GITIGNORE_RULES.filter((rule) =>
|
|
1565
|
+
rule.startsWith("!"),
|
|
1566
|
+
);
|
|
1567
|
+
const negationSet = new Set(negationRules);
|
|
1568
|
+
updated = updated
|
|
1569
|
+
.split("\n")
|
|
1570
|
+
.filter((line) => !negationSet.has(line.trim()))
|
|
1571
|
+
.join("\n");
|
|
775
1572
|
if (!updated.endsWith("\n")) {
|
|
776
1573
|
updated += "\n";
|
|
777
1574
|
}
|
|
1575
|
+
const additions = [
|
|
1576
|
+
...missingRules.filter((rule) => !rule.startsWith("!")),
|
|
1577
|
+
...negationRules,
|
|
1578
|
+
];
|
|
778
1579
|
updated +=
|
|
779
1580
|
"# Vellum runtime state (auto-added)\n" +
|
|
780
|
-
|
|
1581
|
+
additions.join("\n") +
|
|
781
1582
|
"\n";
|
|
782
1583
|
}
|
|
783
1584
|
writeFileSync(gitignorePath, updated, "utf-8");
|
|
@@ -791,15 +1592,75 @@ export class WorkspaceGitService {
|
|
|
791
1592
|
}
|
|
792
1593
|
}
|
|
793
1594
|
|
|
1595
|
+
/**
|
|
1596
|
+
* Drop tracked files matched by the Vellum-managed ignore rules from the
|
|
1597
|
+
* index (working tree untouched). Ignore rules only affect untracked
|
|
1598
|
+
* paths, so committed runtime state (e.g. embedding-models/) stays in the
|
|
1599
|
+
* index — and churns every commit — until explicitly removed here. The
|
|
1600
|
+
* staged deletions ride along with the next commit. Best-effort: failures
|
|
1601
|
+
* are logged, never block init. Must be called with the mutex lock held.
|
|
1602
|
+
*
|
|
1603
|
+
* Deliberately matches against the Vellum-managed rules only — not the
|
|
1604
|
+
* workspace .gitignore (which may carry user-authored rules whose matches
|
|
1605
|
+
* are force-added on purpose) and not --exclude-standard (the user's
|
|
1606
|
+
* global/local exclude files). The rules are passed via a temp file under
|
|
1607
|
+
* .git so gitignore semantics, including negation order, are preserved.
|
|
1608
|
+
*/
|
|
1609
|
+
private async untrackIgnoredFilesLocked(): Promise<void> {
|
|
1610
|
+
const rulesPath = join(this.workspaceDir, ".git", "vellum-untrack-rules");
|
|
1611
|
+
try {
|
|
1612
|
+
writeFileSync(
|
|
1613
|
+
rulesPath,
|
|
1614
|
+
WORKSPACE_GITIGNORE_RULES.join("\n") + "\n",
|
|
1615
|
+
"utf-8",
|
|
1616
|
+
);
|
|
1617
|
+
const { stdout } = await this.execGitStreaming([
|
|
1618
|
+
"ls-files",
|
|
1619
|
+
"-z",
|
|
1620
|
+
"--cached",
|
|
1621
|
+
"--ignored",
|
|
1622
|
+
`--exclude-from=${rulesPath}`,
|
|
1623
|
+
]);
|
|
1624
|
+
const files = stdout.split("\0").filter(Boolean);
|
|
1625
|
+
if (files.length === 0) {
|
|
1626
|
+
return;
|
|
1627
|
+
}
|
|
1628
|
+
// Chunked to stay under OS argv limits on bloated workspaces.
|
|
1629
|
+
const chunkSize = 200;
|
|
1630
|
+
for (let i = 0; i < files.length; i += chunkSize) {
|
|
1631
|
+
await this.execGit([
|
|
1632
|
+
"rm",
|
|
1633
|
+
"--cached",
|
|
1634
|
+
"-r",
|
|
1635
|
+
"-q",
|
|
1636
|
+
"--ignore-unmatch",
|
|
1637
|
+
"--",
|
|
1638
|
+
...files.slice(i, i + chunkSize),
|
|
1639
|
+
]);
|
|
1640
|
+
}
|
|
1641
|
+
log.info(
|
|
1642
|
+
{ fileCount: files.length },
|
|
1643
|
+
"Untracked newly ignored files from workspace index",
|
|
1644
|
+
);
|
|
1645
|
+
} catch (err) {
|
|
1646
|
+
log.warn({ err }, "Failed to untrack newly ignored files");
|
|
1647
|
+
} finally {
|
|
1648
|
+
try {
|
|
1649
|
+
unlinkSync(rulesPath);
|
|
1650
|
+
} catch {
|
|
1651
|
+
// Never created, or already gone.
|
|
1652
|
+
}
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
|
|
794
1656
|
/**
|
|
795
1657
|
* Ensure local git identity is configured for automated commits.
|
|
796
1658
|
* Idempotent: git config set is a no-op if the value is already correct.
|
|
797
1659
|
* Must be called with the mutex lock held.
|
|
798
1660
|
*/
|
|
799
1661
|
private async ensureCommitIdentityLocked(): Promise<void> {
|
|
800
|
-
const gitName = process.env.ASSISTANT_GIT_USER_NAME ||
|
|
801
|
-
const gitEmail =
|
|
802
|
-
process.env.ASSISTANT_GIT_USER_EMAIL || "assistant@vellum.ai";
|
|
1662
|
+
const gitName = process.env.ASSISTANT_GIT_USER_NAME || DEFAULT_GIT_NAME;
|
|
1663
|
+
const gitEmail = process.env.ASSISTANT_GIT_USER_EMAIL || DEFAULT_GIT_EMAIL;
|
|
803
1664
|
await this.execGit(["config", "user.name", gitName]);
|
|
804
1665
|
await this.execGit(["config", "user.email", gitEmail]);
|
|
805
1666
|
}
|
|
@@ -891,16 +1752,23 @@ export class WorkspaceGitService {
|
|
|
891
1752
|
*/
|
|
892
1753
|
private async execGit(
|
|
893
1754
|
args: string[],
|
|
894
|
-
options?: {
|
|
1755
|
+
options?: {
|
|
1756
|
+
signal?: AbortSignal;
|
|
1757
|
+
timeoutMs?: number;
|
|
1758
|
+
env?: Record<string, string>;
|
|
1759
|
+
},
|
|
895
1760
|
): Promise<{ stdout: string; stderr: string }> {
|
|
896
1761
|
const config = getConfig();
|
|
897
|
-
const timeoutMs =
|
|
1762
|
+
const timeoutMs =
|
|
1763
|
+
options?.timeoutMs ??
|
|
1764
|
+
config.workspaceGit?.interactiveGitTimeoutMs ??
|
|
1765
|
+
10_000;
|
|
898
1766
|
try {
|
|
899
1767
|
const { stdout, stderr } = await execFileAsync("git", args, {
|
|
900
1768
|
cwd: this.workspaceDir,
|
|
901
1769
|
encoding: "utf-8",
|
|
902
1770
|
timeout: timeoutMs,
|
|
903
|
-
env: cleanGitEnv(this.workspaceDir),
|
|
1771
|
+
env: { ...cleanGitEnv(this.workspaceDir), ...options?.env },
|
|
904
1772
|
signal: options?.signal,
|
|
905
1773
|
});
|
|
906
1774
|
return { stdout, stderr };
|
|
@@ -925,20 +1793,35 @@ export class WorkspaceGitService {
|
|
|
925
1793
|
* workspace) cannot fail with `ERR_CHILD_PROCESS_STDIO_MAXBUFFER`. Used for
|
|
926
1794
|
* read paths where output is unbounded; errors are enhanced identically to
|
|
927
1795
|
* {@link execGit} so callers can still distinguish timeouts and permissions.
|
|
1796
|
+
* `options.input` is written to the child's stdin, which is closed either
|
|
1797
|
+
* way so commands reading stdin to EOF (`--pathspec-from-file=-`) terminate.
|
|
928
1798
|
*/
|
|
929
1799
|
private execGitStreaming(
|
|
930
1800
|
args: string[],
|
|
931
|
-
options?: {
|
|
1801
|
+
options?: {
|
|
1802
|
+
signal?: AbortSignal;
|
|
1803
|
+
input?: string;
|
|
1804
|
+
timeoutMs?: number;
|
|
1805
|
+
env?: Record<string, string>;
|
|
1806
|
+
},
|
|
932
1807
|
): Promise<{ stdout: string; stderr: string }> {
|
|
933
1808
|
const config = getConfig();
|
|
934
|
-
const timeoutMs =
|
|
1809
|
+
const timeoutMs =
|
|
1810
|
+
options?.timeoutMs ??
|
|
1811
|
+
config.workspaceGit?.interactiveGitTimeoutMs ??
|
|
1812
|
+
10_000;
|
|
935
1813
|
return new Promise((resolve, reject) => {
|
|
936
1814
|
const child = spawn("git", args, {
|
|
937
1815
|
cwd: this.workspaceDir,
|
|
938
|
-
env: cleanGitEnv(this.workspaceDir),
|
|
1816
|
+
env: { ...cleanGitEnv(this.workspaceDir), ...options?.env },
|
|
939
1817
|
signal: options?.signal,
|
|
940
1818
|
});
|
|
941
1819
|
|
|
1820
|
+
// Swallow EPIPE from a child that exits without reading stdin; the
|
|
1821
|
+
// failure still surfaces through the close/error handlers below.
|
|
1822
|
+
child.stdin?.on("error", () => {});
|
|
1823
|
+
child.stdin?.end(options?.input ?? "");
|
|
1824
|
+
|
|
942
1825
|
const stdoutChunks: Buffer[] = [];
|
|
943
1826
|
const stderrChunks: Buffer[] = [];
|
|
944
1827
|
let timedOut = false;
|
|
@@ -1233,3 +2116,15 @@ export function _getInitConsecutiveFailures(
|
|
|
1233
2116
|
return (service as unknown as { initConsecutiveFailures: number })
|
|
1234
2117
|
.initConsecutiveFailures;
|
|
1235
2118
|
}
|
|
2119
|
+
|
|
2120
|
+
/**
|
|
2121
|
+
* @internal Test-only: whether a history compaction run is pending
|
|
2122
|
+
*/
|
|
2123
|
+
export function _hasPendingHistoryCompaction(
|
|
2124
|
+
service: WorkspaceGitService,
|
|
2125
|
+
): boolean {
|
|
2126
|
+
return (
|
|
2127
|
+
(service as unknown as { historyCompactionTimer: unknown })
|
|
2128
|
+
.historyCompactionTimer !== null
|
|
2129
|
+
);
|
|
2130
|
+
}
|