@vellumai/assistant 0.11.0 → 0.11.1-staging.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +14 -9
- package/Dockerfile +1 -0
- package/docs/architecture/memory.md +59 -0
- package/docs/stt-provider-onboarding.md +10 -7
- package/eslint.config.mjs +34 -1
- 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__/conversation-handle.test.ts +316 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/redacted-credential.test.ts +1 -1
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/conversation-handle.ts +246 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +2 -2
- 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__/conversation-handle.test.ts +316 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/redacted-credential.test.ts +1 -1
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/conversation-handle.ts +246 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +2 -2
- package/node_modules/@vellumai/ipc-server-utils/src/index.ts +10 -0
- package/{src/ipc → node_modules/@vellumai/ipc-server-utils/src}/ipc-framing.ts +21 -7
- package/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/conversation-handle.test.ts +316 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/redacted-credential.test.ts +1 -1
- package/node_modules/@vellumai/service-contracts/src/conversation-handle.ts +246 -0
- package/node_modules/@vellumai/service-contracts/src/index.ts +1 -0
- package/node_modules/@vellumai/service-contracts/src/remote-web-pairing.ts +2 -2
- package/openapi.yaml +365 -11
- package/package.json +1 -1
- package/scripts/build-plugin-api.ts +11 -4
- package/scripts/capture-x-graphql.ts +54 -20
- package/scripts/generate-openapi.ts +7 -3
- package/scripts/memory-inspect.ts +17 -6
- package/scripts/sync-llm-catalog.ts +44 -19
- package/scripts/sync-web-search-catalog.ts +3 -1
- package/scripts/voice-ttft-spike.ts +6 -3
- package/src/__tests__/add-message-skip-indexing.test.ts +3 -2
- package/src/__tests__/agent-loop-history-repair.test.ts +180 -0
- package/src/__tests__/agent-loop-output-hooks.test.ts +35 -11
- package/src/__tests__/agent-loop-override-profile.test.ts +21 -14
- package/src/__tests__/agent-loop-regrowth-guard.test.ts +3 -1
- package/src/__tests__/agent-loop.test.ts +5 -2
- package/src/__tests__/anthropic-error-formatting.test.ts +3 -1
- package/src/__tests__/app-control-flow.test.ts +3 -1
- package/src/__tests__/app-control-tool-schemas.test.ts +6 -2
- package/src/__tests__/app-dir-path-guard.test.ts +9 -3
- package/src/__tests__/app-routes-csp.test.ts +12 -4
- package/src/__tests__/app-source-watcher.test.ts +3 -1
- package/src/__tests__/approval-primitive.test.ts +66 -22
- package/src/__tests__/assistant-feature-flag-guard.test.ts +6 -2
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +12 -4
- package/src/__tests__/assistant-id-boundary-guard.test.ts +26 -9
- package/src/__tests__/attachments-store.test.ts +12 -4
- package/src/__tests__/avatar-generator.test.ts +3 -1
- package/src/__tests__/background-shell-bash.test.ts +3 -1
- package/src/__tests__/browser-fill-credential.test.ts +6 -2
- package/src/__tests__/browser-runtime-check.test.ts +3 -1
- package/src/__tests__/build-persisted-content.test.ts +3 -1
- package/src/__tests__/bundled-skill-retrieval-guard.test.ts +15 -5
- package/src/__tests__/byok-default-profile-ensure.test.ts +1095 -0
- package/src/__tests__/call-controller.test.ts +9 -3
- package/src/__tests__/call-domain.test.ts +15 -8
- package/src/__tests__/call-setup-flow-midcall-trust.test.ts +3 -1
- package/src/__tests__/call-state-machine.test.ts +3 -1
- package/src/__tests__/channel-approval-routes.test.ts +2 -1
- package/src/__tests__/channel-approval.test.ts +9 -6
- package/src/__tests__/channel-guardian.test.ts +3 -1
- package/src/__tests__/channel-setup-panel-ack.test.ts +1 -3
- package/src/__tests__/clawhub.test.ts +3 -1
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +3 -1
- package/src/__tests__/compact-event-conversation-id-guard.test.ts +3 -2
- package/src/__tests__/compaction-summary-head-persisted-count.test.ts +1 -1
- package/src/__tests__/config-callsite-patch-merge.test.ts +92 -0
- package/src/__tests__/config-get-vision-flag.test.ts +1 -1
- package/src/__tests__/config-loader-backfill.test.ts +199 -134
- package/src/__tests__/config-loader-corrupt.test.ts +3 -1
- package/src/__tests__/config-loader-platform-defaults.test.ts +3 -1
- package/src/__tests__/config-loader-quarantine-notice.test.ts +3 -1
- package/src/__tests__/config-loader-validation-reset-notice.test.ts +3 -1
- package/src/__tests__/config-model-image-provider.test.ts +3 -1
- package/src/__tests__/config-set-platform-guard.test.ts +3 -1
- package/src/__tests__/config-watcher.test.ts +3 -1
- package/src/__tests__/connection-model-compat.test.ts +3 -1
- package/src/__tests__/contact-store-user-file.test.ts +18 -6
- package/src/__tests__/contacts-relay-reads.test.ts +31 -22
- package/src/__tests__/contacts-tools.test.ts +3 -1
- package/src/__tests__/context-overflow-reducer.test.ts +3 -1
- package/src/__tests__/context-search-conversations-source.test.ts +4 -1
- package/src/__tests__/context-search-memory-v2-source.test.ts +3 -1
- package/src/__tests__/conversation-agent-loop-handlers-max-tokens.test.ts +3 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop.test.ts +1 -1
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +3 -3
- package/src/__tests__/conversation-delete-subagent-rows.test.ts +303 -0
- package/src/__tests__/conversation-fork-route.test.ts +3 -1
- package/src/__tests__/conversation-inference-profile-list.test.ts +3 -1
- package/src/__tests__/conversation-list-source.test.ts +3 -1
- package/src/__tests__/conversation-loop-db-lock-resilience.test.ts +9 -8
- package/src/__tests__/conversation-pairing.test.ts +6 -2
- package/src/__tests__/conversation-pre-run-repair.test.ts +1 -1
- package/src/__tests__/conversation-queue.test.ts +65 -1
- package/src/__tests__/conversation-routes-disk-view.test.ts +18 -6
- package/src/__tests__/conversation-slash-commands.test.ts +27 -9
- package/src/__tests__/conversation-slash.test.ts +92 -0
- package/src/__tests__/conversation-starter-routes.test.ts +6 -2
- package/src/__tests__/conversation-surfaces-app-control.test.ts +3 -1
- package/src/__tests__/conversation-surfaces-app-open.test.ts +1 -3
- package/src/__tests__/conversation-surfaces-queued-emit.test.ts +86 -0
- package/src/__tests__/conversation-surfaces-standalone.test.ts +6 -2
- package/src/__tests__/conversation-surfaces-state-update.test.ts +1 -3
- package/src/__tests__/conversation-surfaces-table-action.test.ts +1 -3
- package/src/__tests__/conversation-usage.test.ts +159 -0
- package/src/__tests__/conversations-import-system-filter.test.ts +101 -4
- package/src/__tests__/credential-broker-server-use.test.ts +21 -7
- package/src/__tests__/credential-broker.test.ts +30 -10
- package/src/__tests__/credential-execution-client.test.ts +17 -6
- package/src/__tests__/credential-security-invariants.test.ts +3 -1
- package/src/__tests__/custom-group-listing-visibility.test.ts +93 -0
- package/src/__tests__/db-migration-rollback.test.ts +21 -7
- package/src/__tests__/db-readiness-http-gate.test.ts +3 -1
- package/src/__tests__/db-schedule-syntax-migration.test.ts +1 -0
- package/src/__tests__/default-provider-ensure.test.ts +10 -1
- package/src/__tests__/disk-pressure-guard.test.ts +3 -1
- package/src/__tests__/dm-backfill.test.ts +3 -1
- package/src/__tests__/dm-persistence.test.ts +3 -1
- package/src/__tests__/docker-signing-key-bootstrap.test.ts +2 -1
- package/src/__tests__/drain-requeue-on-contention.test.ts +124 -0
- package/src/__tests__/edit-engine.test.ts +42 -14
- package/src/__tests__/events-dev-bypass-actor.test.ts +3 -1
- package/src/__tests__/file-ops-service.test.ts +60 -20
- package/src/__tests__/filesystem-tools.test.ts +90 -30
- package/src/__tests__/fixtures/mock-chrome-extension.ts +18 -6
- package/src/__tests__/fixtures/mock-signup-server.ts +6 -2
- package/src/__tests__/fuzzy-match-property.test.ts +18 -6
- package/src/__tests__/gateway-flag-listener.test.ts +9 -3
- package/src/__tests__/gateway-only-enforcement.test.ts +2 -1
- package/src/__tests__/gateway-only-guard.test.ts +12 -4
- package/src/__tests__/gemini-image-service.test.ts +3 -1
- package/src/__tests__/gemini-provider.test.ts +81 -2
- package/src/__tests__/get-skill-detail-audit.test.ts +9 -3
- package/src/__tests__/google-calendar-watcher.test.ts +75 -0
- package/src/__tests__/guardian-card-rehydration.test.ts +210 -0
- package/src/__tests__/guardian-card-withdrawal.test.ts +37 -2
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +42 -14
- package/src/__tests__/guardian-expiry-notifier.test.ts +3 -1
- package/src/__tests__/guardian-question-mode.test.ts +12 -4
- package/src/__tests__/headless-browser-interactions.test.ts +6 -2
- package/src/__tests__/headless-browser-mode.test.ts +6 -2
- package/src/__tests__/headless-browser-navigate.test.ts +33 -11
- package/src/__tests__/headless-browser-read-tools.test.ts +24 -8
- package/src/__tests__/headless-browser-snapshot.test.ts +3 -1
- package/src/__tests__/helpers/channel-test-adapter.ts +17 -7
- package/src/__tests__/helpers/create-guardian-binding.ts +3 -1
- package/src/__tests__/helpers/derive-guardian-delivery.ts +3 -1
- package/src/__tests__/helpers/gateway-acl-store.ts +6 -2
- package/src/__tests__/helpers/gateway-classify-mock.ts +3 -1
- package/src/__tests__/helpers/seed-contact-channel.ts +3 -1
- package/src/__tests__/helpers/tar-fixtures.ts +3 -1
- package/src/__tests__/history-repair-observability.test.ts +1 -1
- package/src/__tests__/history-repair.test.ts +2 -2
- package/src/__tests__/host-app-control-routes.test.ts +98 -2
- package/src/__tests__/host-bash-routes.test.ts +66 -0
- package/src/__tests__/host-cu-proxy.test.ts +7 -1
- package/src/__tests__/host-cu-routes-targeted.test.ts +87 -0
- package/src/__tests__/host-file-routes-targeted.test.ts +60 -0
- package/src/__tests__/host-proxy-preactivation.test.ts +1 -5
- package/src/__tests__/host-transfer-proxy.test.ts +4 -4
- package/src/__tests__/host-transfer-routes-targeted.test.ts +3 -1
- package/src/__tests__/image-recovery-hook.test.ts +3 -3
- package/src/__tests__/inbound-slack-persistence.test.ts +3 -1
- package/src/__tests__/injector-config-quarantine-notice.test.ts +3 -1
- package/src/__tests__/injector-config-validation-reset-notice.test.ts +3 -1
- package/src/__tests__/injector-disk-pressure.test.ts +3 -1
- package/src/__tests__/injector-document-comments.test.ts +3 -1
- package/src/__tests__/injector-v3-suppression.test.ts +6 -2
- package/src/__tests__/inline-skill-authoring-guard.test.ts +12 -4
- package/src/__tests__/internal-telemetry-routes.test.ts +3 -1
- package/src/__tests__/lexical-index-dual-write.test.ts +3 -1
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +9 -3
- package/src/__tests__/llm-callsite-catalog.test.ts +3 -1
- package/src/__tests__/llm-catalog-parity.test.ts +21 -7
- package/src/__tests__/managed-profile-guard.test.ts +53 -0
- package/src/__tests__/max-tokens-continue-hook.test.ts +120 -0
- package/src/__tests__/mcp-cli.test.ts +10 -3
- package/src/__tests__/media-stream-output.test.ts +9 -3
- package/src/__tests__/media-stream-parser.test.ts +111 -37
- package/src/__tests__/media-stream-stt-session.test.ts +34 -11
- package/src/__tests__/memory-upsert-concurrency.test.ts +19 -16
- package/src/__tests__/message-delete-segment-purge.test.ts +98 -0
- package/src/__tests__/migration-cross-version-compatibility.test.ts +3 -1
- package/src/__tests__/migration-export-http.test.ts +9 -3
- package/src/__tests__/migration-export-streaming.test.ts +9 -3
- package/src/__tests__/migration-import-commit-http.test.ts +21 -7
- package/src/__tests__/migration-import-preflight-http.test.ts +3 -1
- package/src/__tests__/migration-validate-http.test.ts +3 -1
- package/src/__tests__/mock-fetch.ts +3 -1
- package/src/__tests__/mock-gateway-ipc.ts +20 -7
- package/src/__tests__/mock-signup-server.test.ts +9 -3
- package/src/__tests__/model-intents.test.ts +1 -1
- package/src/__tests__/native-web-search.test.ts +3 -1
- package/src/__tests__/no-is-trusted-guard.test.ts +3 -1
- package/src/__tests__/notification-broadcaster.test.ts +5 -3
- package/src/__tests__/notification-platform-adapter.test.ts +12 -4
- package/src/__tests__/oauth-apps-routes.test.ts +3 -1
- package/src/__tests__/oauth-commands-routes.test.ts +9 -3
- package/src/__tests__/oauth-connect-orchestrator.test.ts +33 -11
- package/src/__tests__/oauth-connect-routes.test.ts +3 -1
- package/src/__tests__/oauth-providers-routes.test.ts +15 -10
- package/src/__tests__/oauth2-refresh-retry.test.ts +3 -1
- package/src/__tests__/onboarding-persona-write.test.ts +12 -10
- package/src/__tests__/openai-image-service.test.ts +6 -2
- package/src/__tests__/openai-provider.test.ts +3 -1
- package/src/__tests__/openai-responses-cutover-guard.test.ts +3 -1
- package/src/__tests__/openai-responses-provider.test.ts +3 -1
- package/src/__tests__/outbound-slack-persistence.test.ts +18 -6
- package/src/__tests__/persist-media-references.test.ts +3 -1
- package/src/__tests__/persist-onboarding-artifacts.test.ts +3 -1
- package/src/__tests__/persist-unsendable-image-downscale.test.ts +3 -3
- package/src/__tests__/persist-unsendable-image.test.ts +3 -3
- package/src/__tests__/persist-user-message-set-processing-failure.test.ts +3 -1
- package/src/__tests__/persistence-secret-redaction.test.ts +9 -3
- package/src/__tests__/persona-resolver.test.ts +3 -1
- package/src/__tests__/plugin-api-tool-definition.test.ts +5 -8
- package/src/__tests__/plugin-bootstrap.test.ts +2 -3
- package/src/__tests__/plugin-import-boundary-guard.test.ts +1 -0
- package/src/__tests__/plugin-import-boundary-reverse-guard.test.ts +1 -4
- package/src/__tests__/post-turn-tool-result-truncation.test.ts +112 -1
- package/src/__tests__/prechat-onboarding-contract.test.ts +6 -2
- package/src/__tests__/pricing.test.ts +2 -2
- package/src/__tests__/process-message-background-slack.test.ts +3 -1
- package/src/__tests__/profiler-routes.test.ts +10 -12
- package/src/__tests__/provider-catalog-visibility.test.ts +12 -4
- package/src/__tests__/provider-error-scenarios.test.ts +27 -9
- package/src/__tests__/provider-streaming.benchmark.test.ts +12 -4
- package/src/__tests__/queued-message-delete-contract.test.ts +339 -0
- package/src/__tests__/recording-handler.test.ts +7 -3
- package/src/__tests__/retry-thinking-preadaptive.test.ts +204 -0
- package/src/__tests__/run-conversation-turn-persistence.test.ts +3 -1
- package/src/__tests__/runtime-events-sse-reconnect.test.ts +3 -1
- package/src/__tests__/schedule-retry.test.ts +3 -1
- package/src/__tests__/schedule-routes-workflow-validation.test.ts +9 -3
- package/src/__tests__/schedule-routes.test.ts +3 -1
- package/src/__tests__/schedule-store.test.ts +113 -9
- package/src/__tests__/schedule-tools.test.ts +106 -0
- package/src/__tests__/scheduler-reuse-conversation.test.ts +3 -1
- package/src/__tests__/scheduler-wake.test.ts +47 -8
- package/src/__tests__/script-proxy-injection-runtime.test.ts +14 -5
- package/src/__tests__/script-proxy-mitm-handler.test.ts +12 -4
- package/src/__tests__/script-proxy-rewrite-specificity.test.ts +12 -4
- package/src/__tests__/search-skills-unified.test.ts +27 -9
- package/src/__tests__/service-contracts-import-guard.test.ts +12 -4
- package/src/__tests__/settings-routes.test.ts +3 -1
- package/src/__tests__/shell-credential-ref.test.ts +6 -2
- package/src/__tests__/shell-observability.test.ts +3 -1
- package/src/__tests__/skill-cache-store.test.ts +3 -1
- package/src/__tests__/skill-feature-flags-integration.test.ts +3 -1
- package/src/__tests__/skill-secret-handling-guard.test.ts +11 -4
- package/src/__tests__/skills-file-content-endpoint.test.ts +93 -31
- package/src/__tests__/skills-files-catalog-fallback.test.ts +33 -11
- package/src/__tests__/skills.test.ts +33 -14
- package/src/__tests__/slack-channel-config.test.ts +6 -2
- package/src/__tests__/slack-messaging-token-resolution.test.ts +6 -2
- package/src/__tests__/sse-actor-principal-guardian-source.test.ts +3 -1
- package/src/__tests__/steer-on-enqueue-question.test.ts +3 -1
- package/src/__tests__/steer-tool-repair.test.ts +6 -2
- package/src/__tests__/stt-language-catalog-parity.test.ts +131 -0
- package/src/__tests__/subagent-allowlist-validation.test.ts +3 -1
- package/src/__tests__/subagent-detail.test.ts +317 -3
- package/src/__tests__/subagent-disposal.test.ts +149 -1
- package/src/__tests__/subagent-fork-prompt-role.test.ts +3 -1
- package/src/__tests__/subagent-notify-parent.test.ts +1 -0
- package/src/__tests__/subagent-persistence.test.ts +444 -7
- package/src/__tests__/subagent-reconcile-route.test.ts +423 -0
- package/src/__tests__/subagent-role-registry.test.ts +3 -1
- package/src/__tests__/subagent-tools.test.ts +304 -0
- package/src/__tests__/system-prompt.test.ts +12 -5
- package/src/__tests__/task-progress-nudge-hook.test.ts +3 -1
- package/src/__tests__/telegram-bot-username-resolution.test.ts +3 -1
- package/src/__tests__/telegram-config.test.ts +3 -1
- package/src/__tests__/telemetry-routes.test.ts +8 -3
- package/src/__tests__/thinking-block-replay.test.ts +1 -2
- package/src/__tests__/thread-backfill.test.ts +24 -8
- package/src/__tests__/token-estimator-accuracy.benchmark.test.ts +6 -2
- package/src/__tests__/token-manager.test.ts +36 -12
- package/src/__tests__/tool-preview-lifecycle.test.ts +3 -6
- package/src/__tests__/tool-result-truncation.test.ts +3 -1
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +6 -2
- package/src/__tests__/tts-catalog-parity.test.ts +6 -2
- package/src/__tests__/twilio-provider.test.ts +6 -2
- package/src/__tests__/unicode.test.ts +1 -3
- package/src/__tests__/usage-cli.test.ts +3 -1
- package/src/__tests__/usage-routes.test.ts +3 -1
- package/src/__tests__/validate-input.test.ts +27 -9
- package/src/__tests__/voice-approval-resolver-relay.test.ts +15 -5
- package/src/__tests__/voice-config-update.test.ts +257 -2
- package/src/__tests__/wake-schedule-escalation.test.ts +477 -0
- package/src/__tests__/wake-schedule-trust.test.ts +255 -0
- package/src/__tests__/web-fetch.test.ts +21 -7
- package/src/__tests__/web-search-catalog-parity.test.ts +11 -4
- package/src/__tests__/web-search-history.test.ts +72 -78
- package/src/__tests__/web-search.test.ts +15 -5
- package/src/__tests__/worker-entrypoint-guards.test.ts +39 -0
- package/src/__tests__/workspace-greetings.test.ts +3 -1
- package/src/__tests__/workspace-migration-026-backfill-install-meta.test.ts +3 -1
- package/src/__tests__/workspace-migration-043-release-notes-latex-rendering.test.ts +3 -1
- package/src/__tests__/workspace-migration-082-backfill-managed-profile-labels.test.ts +1 -4
- package/src/__tests__/workspace-migration-130-speech-mode-to-provider.test.ts +3 -1
- package/src/__tests__/workspace-migration-136-repair-stale-fireworks-kimi-model-id.test.ts +139 -0
- package/src/__tests__/workspace-migration-down-functions.test.ts +5 -2
- package/src/__tests__/workspace-migration-meets.test.ts +4 -6
- package/src/__tests__/workspace-migration-memory-v2-init.test.ts +3 -1
- package/src/__tests__/workspace-migration-seed-device-id.test.ts +3 -1
- package/src/a2a/__tests__/agent-card.test.ts +5 -21
- package/src/a2a/agent-card.ts +11 -17
- package/src/acp/__tests__/helpers/exec-file-stub.ts +3 -1
- package/src/acp/__tests__/prepare-agent-env.test.ts +3 -1
- package/src/acp/agent-process.ts +18 -6
- package/src/acp/auto-install.test.ts +9 -3
- package/src/acp/auto-install.ts +6 -2
- package/src/acp/failure-error.ts +8 -3
- package/src/acp/prepare-agent-env.ts +3 -1
- package/src/acp/resolve-agent.test.ts +81 -27
- package/src/acp/resolve-agent.ts +9 -3
- package/src/{plugins/defaults/history-repair/terminal.ts → agent/history-repair/history-repair.ts} +42 -11
- package/src/agent/image-optimize.ts +18 -6
- package/src/agent/loop.ts +45 -10
- package/src/api/events/contact-request.ts +1 -0
- package/src/api/events/message-dequeued.ts +4 -0
- package/src/api/events/message-queued-deleted.ts +4 -0
- package/src/api/events/message-queued.ts +4 -0
- package/src/api/events/message-requeued.ts +35 -0
- package/src/api/events/tool-result.ts +1 -0
- package/src/api/index.ts +6 -0
- package/src/api/responses/subagent-detail.ts +13 -6
- package/src/approvals/guardian-card-withdrawal.ts +30 -11
- package/src/apps/app-store.ts +65 -22
- package/src/apps/shared-app-links-store.ts +9 -3
- package/src/avatar/__tests__/avatar-store.test.ts +6 -2
- package/src/avatar/avatar-manifest.ts +18 -6
- package/src/avatar/resvg-lazy.test.ts +6 -2
- package/src/background-wake/background-wake-routes.test.ts +9 -3
- package/src/background-wake/next-wake.ts +15 -5
- package/src/background-wake/platform-client.ts +18 -6
- package/src/background-wake/publisher.ts +3 -1
- package/src/backup/__tests__/paths.test.ts +0 -1
- package/src/backup/__tests__/restore.test.ts +1 -6
- package/src/backup/__tests__/snapshot-lock.test.ts +3 -2
- package/src/backup/list-snapshots.ts +15 -5
- package/src/backup/local-writer.ts +9 -3
- package/src/backup/paths.ts +6 -3
- package/src/backup/snapshot-lock.ts +18 -6
- package/src/browser-session/__tests__/manager.test.ts +6 -2
- package/src/browser-session/manager.ts +6 -2
- package/src/bundler/app-compiler.ts +44 -15
- package/src/bundler/bundle-scanner.ts +29 -10
- package/src/bundler/bundle-signer.ts +3 -1
- package/src/bundler/compiler-tools.ts +15 -5
- package/src/bundler/package-resolver.ts +3 -1
- package/src/bundler/signature-verifier.ts +3 -1
- package/src/calls/__tests__/inbound-trust-reader.test.ts +1 -4
- package/src/calls/__tests__/tts-text-sanitizer.test.ts +11 -11
- package/src/calls/access-request-wait.ts +9 -3
- package/src/calls/audio-store.ts +9 -3
- package/src/calls/call-constants.ts +6 -2
- package/src/calls/call-controller.ts +72 -25
- package/src/calls/call-pointer-message-composer.ts +11 -4
- package/src/calls/call-pointer-messages.ts +24 -8
- package/src/calls/call-store.ts +12 -4
- package/src/calls/guardian-action-sweep.ts +3 -1
- package/src/calls/inbound-trust-reader.ts +5 -1
- package/src/calls/media-stream-audio-transcode.ts +9 -3
- package/src/calls/media-stream-output.ts +41 -15
- package/src/calls/media-stream-stt-session.ts +21 -7
- package/src/calls/media-turn-detector.ts +9 -3
- package/src/calls/speaker-identification.ts +21 -7
- package/src/calls/telephony-credential-preflight.ts +1 -3
- package/src/calls/tts-text-sanitizer.ts +2 -8
- package/src/calls/twilio-config.ts +3 -1
- package/src/calls/twilio-provider.ts +3 -1
- package/src/calls/twilio-rest.ts +3 -1
- package/src/calls/voice-control-protocol.ts +12 -4
- package/src/channels/__tests__/gateway-verification-sessions.test.ts +2 -3
- package/src/channels/permission-profiles.ts +9 -3
- package/src/channels/slack-callback-url.ts +9 -3
- package/src/channels/types.ts +17 -6
- package/src/cli/__tests__/run-assistant-command.ts +3 -1
- package/src/cli/__tests__/unknown-command.test.ts +3 -1
- package/src/cli/commands/__tests__/attachment.test.ts +3 -1
- package/src/cli/commands/__tests__/avatar.test.ts +18 -10
- package/src/cli/commands/__tests__/backup.test.ts +30 -10
- package/src/cli/commands/__tests__/browser.test.ts +3 -1
- package/src/cli/commands/__tests__/cache.test.ts +3 -1
- package/src/cli/commands/__tests__/changelog.test.ts +3 -1
- package/src/cli/commands/__tests__/channel-verification-sessions.test.ts +11 -6
- package/src/cli/commands/__tests__/conversations-import.test.ts +3 -1
- package/src/cli/commands/__tests__/conversations-new.test.ts +9 -3
- package/src/cli/commands/__tests__/conversations-slack.test.ts +15 -5
- package/src/cli/commands/__tests__/conversations-wake.test.ts +13 -3
- package/src/cli/commands/__tests__/domain-register.test.ts +1 -3
- package/src/cli/commands/__tests__/domain-status.test.ts +13 -5
- package/src/cli/commands/__tests__/email-attachment.test.ts +61 -19
- package/src/cli/commands/__tests__/email-core.test.ts +126 -49
- package/src/cli/commands/__tests__/gateway.test.ts +6 -2
- package/src/cli/commands/__tests__/image-generation.test.ts +5 -2
- package/src/cli/commands/__tests__/inference-send.test.ts +3 -1
- package/src/cli/commands/__tests__/skills.test.ts +3 -1
- package/src/cli/commands/__tests__/status.test.ts +16 -3
- package/src/cli/commands/__tests__/stt.test.ts +23 -5
- package/src/cli/commands/__tests__/trust.test.ts +3 -1
- package/src/cli/commands/__tests__/tts.test.ts +6 -2
- package/src/cli/commands/__tests__/ui-confirm.test.ts +3 -1
- package/src/cli/commands/__tests__/ui.test.ts +3 -1
- package/src/cli/commands/__tests__/watchers.test.ts +3 -1
- package/src/cli/commands/__tests__/webhooks.test.ts +23 -5
- package/src/cli/commands/audit.ts +7 -3
- package/src/cli/commands/avatar.ts +14 -7
- package/src/cli/commands/backup.ts +42 -17
- package/src/cli/commands/cache.ts +9 -3
- package/src/cli/commands/changelog.ts +50 -18
- package/src/cli/commands/channel-verification-sessions.ts +25 -10
- package/src/cli/commands/channels/__tests__/channels.test.ts +8 -13
- package/src/cli/commands/channels/index.ts +12 -4
- package/src/cli/commands/clients.ts +12 -4
- package/src/cli/commands/contacts.help.ts +5 -0
- package/src/cli/commands/contacts.ts +30 -12
- package/src/cli/commands/conversations-import.ts +2 -1
- package/src/cli/commands/conversations.ts +12 -4
- package/src/cli/commands/db/__tests__/repair.test.ts +6 -2
- package/src/cli/commands/db/format.ts +18 -6
- package/src/cli/commands/db/repair-steps.ts +3 -1
- package/src/cli/commands/db/status.ts +6 -2
- package/src/cli/commands/gateway.ts +25 -9
- package/src/cli/commands/image-generation.ts +5 -2
- package/src/cli/commands/inference-session.ts +6 -2
- package/src/cli/commands/inference.ts +44 -6
- package/src/cli/commands/memory/__tests__/memory-ingest.test.ts +591 -0
- package/src/cli/commands/memory/__tests__/memory-v2.test.ts +3 -1
- package/src/cli/commands/memory/__tests__/memory-v3.test.ts +3 -1
- package/src/cli/commands/memory/__tests__/worker.test.ts +3 -1
- package/src/cli/commands/memory/index.help.ts +55 -1
- package/src/cli/commands/memory/index.ts +2 -0
- package/src/cli/commands/memory/memory-ingest.ts +273 -0
- package/src/cli/commands/memory/memory-v2-compare-render.ts +3 -1
- package/src/cli/commands/memory/memory-v2.ts +12 -4
- package/src/cli/commands/memory/memory-v3.ts +3 -1
- package/src/cli/commands/notifications.ts +56 -19
- package/src/cli/commands/oauth/apps.ts +15 -5
- package/src/cli/commands/oauth/disconnect.ts +9 -3
- package/src/cli/commands/oauth/mode.ts +6 -2
- package/src/cli/commands/oauth/ping.ts +9 -3
- package/src/cli/commands/oauth/providers.ts +223 -92
- package/src/cli/commands/oauth/request.ts +26 -9
- package/src/cli/commands/oauth/token.ts +9 -3
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +7 -8
- package/src/cli/commands/platform/__tests__/plans.test.ts +129 -0
- package/src/cli/commands/platform/__tests__/subscription.test.ts +121 -0
- package/src/cli/commands/platform/connect.ts +2 -1
- package/src/cli/commands/platform/disconnect.ts +2 -1
- package/src/cli/commands/platform/index.help.ts +55 -0
- package/src/cli/commands/platform/index.ts +118 -4
- package/src/cli/commands/ps.ts +3 -1
- package/src/cli/commands/sequence.ts +43 -15
- package/src/cli/commands/skills.ts +103 -45
- package/src/cli/commands/status.ts +3 -1
- package/src/cli/commands/telemetry.ts +2 -1
- package/src/cli/commands/ui.ts +6 -2
- package/src/cli/commands/watchers.ts +31 -11
- package/src/cli/commands/webhooks.ts +4 -2
- package/src/cli/lib/__tests__/inspect-plugin.test.ts +3 -1
- package/src/cli/lib/__tests__/list-installed-plugins.test.ts +4 -2
- package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +5 -2
- package/src/cli/lib/__tests__/plugin-catalog-resolve.test.ts +20 -11
- package/src/cli/lib/__tests__/plugin-details.test.ts +13 -7
- package/src/cli/lib/__tests__/plugin-pin-history.test.ts +3 -1
- package/src/cli/lib/__tests__/plugins-install-offline.test.ts +17 -5
- package/src/cli/lib/__tests__/publish-plugin.test.ts +51 -22
- package/src/cli/lib/__tests__/search-plugins.test.ts +13 -6
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +9 -3
- package/src/cli/lib/bundled-marketplace.json +13 -0
- package/src/cli/lib/cli-colors.ts +24 -8
- package/src/cli/lib/confirm-prompt.ts +3 -1
- package/src/cli/lib/install-from-github.ts +6 -2
- package/src/cli/lib/ipc-params.ts +6 -2
- package/src/cli/lib/list-installed-plugins.ts +21 -7
- package/src/cli/lib/parse-github-plugin-spec.ts +15 -5
- package/src/cli/lib/plugin-artifact.ts +9 -3
- package/src/cli/lib/plugin-catalog-platform.ts +7 -2
- package/src/cli/lib/plugin-catalog-resolve.ts +7 -5
- package/src/cli/lib/plugin-marketplace.ts +12 -4
- package/src/cli/lib/plugin-surfaces.ts +15 -5
- package/src/cli/lib/publish-plugin.ts +24 -8
- package/src/cli/lib/search-plugins.ts +3 -1
- package/src/cli/lib/time-ago.ts +18 -6
- package/src/cli/lib/unknown-command.ts +12 -4
- package/src/cli/output.ts +3 -1
- package/src/cli/program.ts +3 -1
- package/src/cli/utils/__tests__/conversation-id.test.ts +3 -3
- package/src/cli/utils/conversation-id.ts +9 -3
- package/src/cli/utils/parse-duration.ts +6 -2
- package/src/config/__tests__/default-plugin-skill-discovery.test.ts +158 -0
- package/src/config/__tests__/default-profile-catalog.test.ts +60 -1
- package/src/config/__tests__/deployment-context-defaults.test.ts +9 -3
- package/src/config/__tests__/feature-flag-registry-guard.test.ts +7 -2
- package/src/config/__tests__/loader-callsite-strip-fallback.test.ts +9 -3
- package/src/config/__tests__/plugin-resident-skill-discovery.test.ts +5 -2
- package/src/config/__tests__/seed-default-provider.test.ts +16 -0
- package/src/config/__tests__/sync-gated-profiles.test.ts +6 -2
- package/src/config/assistant-feature-flags.ts +32 -11
- package/src/config/bundled-skills/app-builder/SKILL.md +3 -3
- package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +24 -34
- package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +1 -1
- package/src/config/bundled-skills/app-builder/references/SLIDES.md +1 -0
- package/src/config/bundled-skills/app-builder/references/WIDGETS.md +1 -1
- package/src/config/bundled-skills/app-builder/tools/app-generate-icon.ts +3 -1
- package/src/config/bundled-skills/app-builder/tools/app-refresh.ts +3 -1
- package/src/config/bundled-skills/app-builder/tools/app-update.ts +3 -1
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +11 -4
- package/src/config/bundled-skills/contacts/tools/google-contacts.ts +6 -2
- package/src/config/bundled-skills/media-processing/__tests__/extract-keyframes.test.ts +3 -1
- package/src/config/bundled-skills/media-processing/services/preprocess.ts +9 -3
- package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +9 -3
- package/src/config/bundled-skills/media-processing/services/reduce.ts +3 -1
- package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +3 -1
- package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +12 -4
- package/src/config/bundled-skills/messaging/SKILL.md +2 -2
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +6 -2
- package/src/config/bundled-skills/messaging/tools/messaging-draft.ts +23 -8
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +5 -2
- package/src/config/bundled-skills/messaging/tools/shared.ts +21 -7
- package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +7 -7
- package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +11 -4
- package/src/config/bundled-skills/schedule/SKILL.md +4 -0
- package/src/config/bundled-skills/schedule/TOOLS.json +8 -0
- package/src/config/bundled-skills/sequences/tools/sequence-create.ts +8 -3
- package/src/config/bundled-skills/sequences/tools/sequence-delete.ts +6 -2
- package/src/config/bundled-skills/sequences/tools/sequence-enroll.ts +12 -4
- package/src/config/bundled-skills/sequences/tools/sequence-enrollment-list.ts +3 -1
- package/src/config/bundled-skills/sequences/tools/sequence-get.ts +6 -2
- package/src/config/bundled-skills/sequences/tools/sequence-import.ts +13 -5
- package/src/config/bundled-skills/sequences/tools/sequence-list.ts +3 -1
- package/src/config/bundled-skills/sequences/tools/sequence-update.ts +17 -7
- package/src/config/bundled-skills/settings/TOOLS.json +4 -3
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +226 -2
- package/src/config/bundled-skills/skill-management/SKILL.md +1 -1
- package/src/config/bundled-skills/skill-management/TOOLS.json +1 -1
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.test.ts +3 -1
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +15 -5
- package/src/config/default-profile-catalog.ts +103 -42
- package/src/config/default-profile-names.ts +16 -2
- package/src/config/env-registry.ts +3 -1
- package/src/config/env.ts +6 -2
- package/src/config/feature-flag-registry.json +8 -8
- package/src/config/llm-resolver.ts +4 -4
- package/src/config/loader.ts +42 -14
- package/src/config/prune-seeded-callsite-defaults.ts +30 -10
- package/src/config/schema-utils.ts +9 -3
- package/src/config/schemas/__tests__/stt.test.ts +27 -0
- package/src/config/schemas/llm.ts +48 -4
- package/src/config/schemas/memory-v3.ts +7 -7
- package/src/config/schemas/stt.ts +20 -1
- package/src/config/seed-inference-profiles.ts +84 -160
- package/src/config/skills.ts +195 -45
- package/src/config/sync-gated-profiles.ts +21 -7
- package/src/contacts/__tests__/guardian-contact-reader.test.ts +3 -1
- package/src/contacts/contact-store.ts +106 -37
- package/src/contacts/guardian-contact-reader.ts +3 -1
- package/src/contacts/guardian-delivery-reader.ts +15 -5
- package/src/context/compactor.ts +96 -32
- package/src/context/estimator-calibration.ts +9 -3
- package/src/context/image-dimensions.ts +75 -25
- package/src/context/post-turn-tool-result-truncation.ts +158 -23
- package/src/context/strip-injections.ts +15 -5
- package/src/context/token-estimator.ts +3 -1
- package/src/context/tool-result-spool.ts +3 -1
- package/src/context/tool-result-truncation.ts +6 -2
- package/src/conversations/job-handlers/summarization.ts +18 -6
- package/src/credential-execution/ces-runtime.ts +10 -10
- package/src/credential-execution/process-manager.test.ts +3 -1
- package/src/credential-execution/process-manager.ts +6 -2
- package/src/credential-health/credential-health-service.ts +30 -10
- package/src/daemon/__tests__/embedding-reconcile.test.ts +3 -1
- package/src/daemon/app-source-watcher.ts +21 -7
- package/src/daemon/assistant-attachments.ts +44 -15
- package/src/daemon/classifier.ts +9 -3
- package/src/daemon/connection-policy.ts +6 -2
- package/src/daemon/conversation-agent-loop.ts +10 -1
- package/src/daemon/conversation-error.ts +12 -4
- package/src/daemon/conversation-evictor.ts +12 -4
- package/src/daemon/conversation-media-retry.ts +18 -6
- package/src/daemon/conversation-messaging.ts +58 -15
- package/src/daemon/conversation-notices.ts +6 -2
- package/src/daemon/conversation-plugin-scope.ts +3 -1
- package/src/daemon/conversation-process.ts +77 -10
- package/src/daemon/conversation-queue-manager.ts +35 -8
- package/src/daemon/conversation-registry.ts +9 -3
- package/src/daemon/conversation-resting-trust.ts +64 -0
- package/src/daemon/conversation-runtime-assembly.ts +6 -2
- package/src/daemon/conversation-slash.ts +50 -17
- package/src/daemon/conversation-store.ts +16 -5
- package/src/daemon/conversation-surfaces.ts +2 -7
- package/src/daemon/conversation-usage.ts +109 -15
- package/src/daemon/conversation-workspace.ts +5 -2
- package/src/daemon/conversation.ts +1 -1
- package/src/daemon/daemon-control.ts +42 -14
- package/src/daemon/date-context.ts +15 -5
- package/src/daemon/dictation-profile-store.ts +26 -10
- package/src/daemon/dictation-text-processing.ts +9 -3
- package/src/daemon/disk-pressure-guard.ts +12 -4
- package/src/daemon/disk-pressure-policy.ts +15 -5
- package/src/daemon/first-greeting.ts +9 -3
- package/src/daemon/handlers/__tests__/config-channels.test.ts +9 -3
- package/src/daemon/handlers/config-channels.ts +3 -1
- package/src/daemon/handlers/conversations.ts +83 -11
- package/src/daemon/handlers/identity.ts +6 -2
- package/src/daemon/handlers/skills.ts +138 -48
- package/src/daemon/host-app-control-proxy.ts +3 -1
- package/src/daemon/host-bash-proxy.ts +11 -4
- package/src/daemon/host-cu-proxy.ts +20 -7
- package/src/daemon/host-transfer-proxy.ts +24 -8
- package/src/daemon/identity-helpers.ts +3 -1
- package/src/daemon/install-symlink.ts +18 -6
- package/src/daemon/interrupted-turn-reconciler.ts +7 -33
- package/src/daemon/lifecycle.ts +20 -5
- package/src/daemon/message-types/web-activity.ts +1 -0
- package/src/daemon/now-scratchpad.ts +3 -1
- package/src/daemon/orphan-reaper.test.ts +17 -6
- package/src/daemon/orphan-reaper.ts +24 -8
- package/src/daemon/parse-actual-tokens-from-error.ts +27 -9
- package/src/daemon/persist-media-references.ts +6 -2
- package/src/daemon/pkb-context-tracker.test.ts +37 -9
- package/src/daemon/pkb-context-tracker.ts +12 -4
- package/src/daemon/pointer-conversation-trust.ts +3 -1
- package/src/daemon/process-message.ts +3 -1
- package/src/daemon/profiler-run-store.ts +21 -7
- package/src/daemon/shutdown-handlers.ts +20 -7
- package/src/daemon/sqlite-corruption-watchdog.ts +6 -2
- package/src/daemon/summarize-boundary.ts +3 -1
- package/src/daemon/turn-latency-tracker.ts +33 -11
- package/src/daemon/verification-session-intent.ts +3 -1
- package/src/daemon/wake-conversation-ops.ts +3 -1
- package/src/daemon/web-search-history.ts +12 -4
- package/src/documents/document-store.ts +15 -5
- package/src/followups/followup-store.ts +9 -3
- package/src/heartbeat/heartbeat-run-store.ts +3 -1
- package/src/home/conversation-starter-checkpoints.ts +3 -1
- package/src/home/feed-source-enrichment.test.ts +7 -0
- package/src/home/feed-source-enrichment.ts +11 -2
- package/src/home/feed-writer.ts +27 -9
- package/src/home/home-greeting-cache.ts +3 -1
- package/src/home/job-handlers/conversation-starters.ts +15 -5
- package/src/home/post-connect-feed.ts +3 -1
- package/src/home/progress-formula.ts +6 -2
- package/src/home/relationship-state-writer.ts +78 -25
- package/src/ipc/__tests__/exit-helper.test.ts +12 -8
- package/src/ipc/__tests__/streaming-client.test.ts +54 -16
- package/src/ipc/__tests__/streaming-framing.test.ts +31 -8
- package/src/ipc/__tests__/ui-request-route.test.ts +3 -1
- package/src/ipc/__tests__/watcher-ipc.test.ts +6 -2
- package/src/ipc/assistant-server.ts +21 -13
- package/src/ipc/cli-client.ts +38 -13
- package/src/ipc/gateway-client.ts +6 -2
- package/src/ipc/gateway-flag-listener.ts +9 -3
- package/src/ipc/routes/__tests__/contacts-mirror-apply-atomicity.test.ts +7 -4
- package/src/ipc/routes/__tests__/contacts-mirror-apply.test.ts +22 -10
- package/src/ipc/routes/__tests__/contacts-mirror-ipc-routes.test.ts +26 -13
- package/src/ipc/routes/__tests__/contacts-mirror-merge-contact.test.ts +35 -9
- package/src/ipc/routes/__tests__/contacts-mirror-upsert-full.test.ts +37 -20
- package/src/ipc/routes/__tests__/guardian-label-ipc-routes.test.ts +4 -6
- package/src/ipc/routes/contacts-info-ipc-routes.ts +9 -6
- package/src/ipc/routes/trust-rules.test.ts +6 -2
- package/src/ipc/socket-cleanup.ts +6 -2
- package/src/live-voice/__tests__/live-activity-reporter.test.ts +194 -0
- package/src/live-voice/__tests__/live-voice-archive.test.ts +24 -8
- package/src/live-voice/__tests__/live-voice-stt.test.ts +330 -3
- package/src/live-voice/__tests__/live-voice-vad.test.ts +11 -1
- package/src/live-voice/__tests__/protocol.test.ts +45 -15
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +6 -2
- package/src/live-voice/live-activity-reporter.ts +180 -0
- package/src/live-voice/live-voice-archive.ts +18 -6
- package/src/live-voice/live-voice-metrics.ts +24 -8
- package/src/live-voice/live-voice-session.ts +154 -15
- package/src/live-voice/protocol.ts +6 -2
- package/src/mcp/client.ts +9 -3
- package/src/mcp/manager.ts +3 -1
- package/src/mcp/mcp-auth-orchestrator.ts +3 -1
- package/src/mcp/mcp-header-store.ts +3 -1
- package/src/mcp/mcp-oauth-provider.ts +12 -4
- package/src/media/gemini-image-service.ts +15 -5
- package/src/media/openai-image-service.ts +9 -3
- package/src/messaging/draft-store.ts +3 -1
- package/src/messaging/providers/__tests__/transport-dispatch.test.ts +3 -1
- package/src/messaging/providers/a2a/__tests__/deliver.test.ts +3 -1
- package/src/messaging/providers/a2a/deliver.ts +3 -1
- package/src/messaging/providers/callback-routing.ts +3 -1
- package/src/messaging/providers/gmail/adapter.ts +36 -12
- package/src/messaging/providers/gmail/client.ts +71 -24
- package/src/messaging/providers/gmail/mime-builder.ts +6 -2
- package/src/messaging/providers/gmail/people-client.ts +3 -1
- package/src/messaging/providers/outlook/client.ts +30 -10
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +15 -6
- package/src/messaging/providers/slack/adapter.ts +51 -17
- package/src/messaging/providers/slack/api.ts +39 -13
- package/src/messaging/providers/slack/client.ts +9 -3
- package/src/messaging/providers/slack/deep-link.ts +15 -5
- package/src/messaging/providers/slack/message-metadata.ts +21 -7
- package/src/messaging/providers/slack/render-transcript.ts +54 -18
- package/src/messaging/providers/slack/render.ts +50 -17
- package/src/messaging/providers/slack/transport.ts +9 -3
- package/src/messaging/providers/telegram-bot/adapter.ts +6 -2
- package/src/messaging/providers/telegram-bot/api.ts +3 -1
- package/src/messaging/providers/telegram-bot/render.ts +33 -11
- package/src/messaging/providers/telegram-bot/send.ts +3 -1
- package/src/messaging/providers/whatsapp/adapter.ts +3 -1
- package/src/messaging/providers/whatsapp/api.ts +9 -3
- package/src/messaging/registry.ts +3 -1
- package/src/messaging/style-analyzer.ts +3 -1
- package/src/monitoring/__tests__/db-integrity-sample.test.ts +96 -0
- package/src/monitoring/__tests__/sample-ring-buffer.test.ts +12 -4
- package/src/monitoring/db-integrity-check.ts +163 -0
- package/src/monitoring/db-integrity-sample.ts +171 -0
- package/src/monitoring/process-memory.ts +2 -1
- package/src/monitoring/sample-ring-buffer.ts +15 -5
- package/src/monitoring/worker.ts +12 -0
- package/src/notifications/adapters/platform.ts +6 -7
- package/src/notifications/adapters/shared.ts +9 -3
- package/src/notifications/conversation-candidates.ts +21 -7
- package/src/notifications/conversation-seed-composer.ts +21 -7
- package/src/notifications/copy-composer.ts +12 -4
- package/src/notifications/decisions-store.ts +6 -2
- package/src/notifications/deferred-emit.ts +18 -6
- package/src/notifications/deliveries-store.ts +3 -1
- package/src/notifications/destination-resolver.ts +12 -6
- package/src/notifications/deterministic-checks.ts +6 -2
- package/src/notifications/edit-notification.ts +3 -1
- package/src/notifications/events-store.ts +3 -1
- package/src/notifications/guardian-question-mode.ts +15 -5
- package/src/notifications/home-feed-side-effect.ts +12 -4
- package/src/notifications/notification-utils.ts +8 -3
- package/src/notifications/preference-extractor.ts +5 -2
- package/src/notifications/preference-summary.ts +3 -1
- package/src/oauth/__tests__/oauth-connect-state.test.ts +4 -1
- package/src/oauth/byo-connection.test.ts +15 -5
- package/src/oauth/byo-connection.ts +6 -2
- package/src/oauth/connect-orchestrator.ts +3 -1
- package/src/oauth/connection-resolver.test.ts +6 -2
- package/src/oauth/connection-resolver.ts +12 -4
- package/src/oauth/identity-verifier.ts +30 -10
- package/src/oauth/manual-token-connection.ts +12 -4
- package/src/oauth/oauth-connect-state.ts +15 -3
- package/src/oauth/oauth-store.ts +132 -52
- package/src/oauth/provider-serializer.ts +9 -3
- package/src/oauth/provider-visibility.ts +3 -1
- package/src/oauth/scope-utils.ts +3 -1
- package/src/onboarding/checkin-event.ts +33 -11
- package/src/outbound-proxy/certs.ts +6 -2
- package/src/outbound-proxy/connect-tunnel.ts +15 -5
- package/src/outbound-proxy/host-pattern-match.ts +3 -1
- package/src/outbound-proxy/http-forwarder.ts +9 -3
- package/src/outbound-proxy/logging.ts +6 -2
- package/src/outbound-proxy/mitm-handler.ts +9 -3
- package/src/outbound-proxy/policy.ts +12 -4
- package/src/outbound-proxy/router.ts +3 -1
- package/src/outbound-proxy/server.ts +15 -5
- package/src/permissions/approval-provenance.test.ts +13 -4
- package/src/permissions/question-prompter.test.ts +12 -4
- package/src/permissions/question-prompter.ts +6 -2
- package/src/persistence/__tests__/raw-query-telemetry.test.ts +3 -1
- package/src/persistence/a2a-invite-store.ts +1 -4
- package/src/persistence/attachments-store.ts +60 -20
- package/src/persistence/bookmark-crud.ts +6 -2
- package/src/persistence/compaction-ledger-store.ts +6 -2
- package/src/persistence/compaction-log-store-clickhouse.ts +29 -10
- package/src/persistence/conversation-attention-store.ts +3 -1
- package/src/persistence/conversation-crud.ts +241 -93
- package/src/persistence/conversation-directories.ts +9 -3
- package/src/persistence/conversation-group-migration.ts +17 -1
- package/src/persistence/conversation-key-store.ts +3 -1
- package/src/persistence/conversation-queries.ts +146 -47
- package/src/persistence/conversation-search-lexical.ts +3 -1
- package/src/persistence/db-async-query.ts +9 -3
- package/src/persistence/delivery-channels.ts +3 -1
- package/src/persistence/embeddings/__tests__/embedding-identity.test.ts +9 -3
- package/src/persistence/embeddings/__tests__/embedding-local-lifecycle.test.ts +755 -0
- package/src/persistence/embeddings/__tests__/plugin-facade-index.test.ts +73 -0
- package/src/persistence/embeddings/__tests__/plugin-index.test.ts +323 -0
- package/src/persistence/embeddings/embed.ts +21 -7
- package/src/persistence/embeddings/embedding-backend.test.ts +12 -4
- package/src/persistence/embeddings/embedding-backend.ts +181 -24
- package/src/persistence/embeddings/embedding-billing-breaker.ts +21 -7
- package/src/persistence/embeddings/embedding-cache.ts +6 -2
- package/src/persistence/embeddings/embedding-gemini.ts +6 -2
- package/src/persistence/embeddings/embedding-identity.ts +12 -4
- package/src/persistence/embeddings/embedding-local.ts +719 -142
- package/src/persistence/embeddings/embedding-ollama.ts +6 -2
- package/src/persistence/embeddings/embedding-openai.ts +3 -1
- package/src/persistence/embeddings/embedding-runtime-manager.ts +25 -9
- package/src/persistence/embeddings/embedding-types.ts +22 -1
- package/src/persistence/embeddings/messages-lexical-index.ts +12 -4
- package/src/persistence/embeddings/plugin-facade.ts +102 -3
- package/src/persistence/embeddings/plugin-index.ts +341 -0
- package/src/persistence/embeddings/qdrant-circuit-breaker.ts +6 -2
- package/src/persistence/embeddings/qdrant-client.test.ts +10 -4
- package/src/persistence/embeddings/qdrant-client.ts +173 -9
- package/src/persistence/embeddings/qdrant-manager.ts +21 -7
- package/src/persistence/external-conversation-store.ts +6 -2
- package/src/persistence/group-crud.test.ts +59 -0
- package/src/persistence/group-crud.ts +36 -11
- package/src/persistence/job-handlers/cleanup.ts +30 -12
- package/src/persistence/job-utils.ts +46 -26
- package/src/persistence/llm-request-log-sink-clickhouse.ts +12 -4
- package/src/persistence/llm-request-log-source-clickhouse.ts +18 -6
- package/src/persistence/llm-request-log-store.ts +26 -9
- package/src/persistence/migrations/001-job-deferrals.ts +3 -1
- package/src/persistence/migrations/002-tool-invocations-fk.ts +6 -2
- package/src/persistence/migrations/003-memory-fts-backfill.ts +3 -1
- package/src/persistence/migrations/004-entity-relation-dedup.ts +3 -1
- package/src/persistence/migrations/005-fingerprint-scope-unique.ts +3 -1
- package/src/persistence/migrations/006-scope-salted-fingerprints.ts +6 -2
- package/src/persistence/migrations/007-assistant-id-to-self.ts +3 -1
- package/src/persistence/migrations/008-remove-assistant-id-columns.ts +6 -2
- package/src/persistence/migrations/009-llm-usage-events-drop-assistant-id.ts +6 -2
- package/src/persistence/migrations/011-call-sessions-provider-sid-dedup.ts +9 -3
- package/src/persistence/migrations/014-backfill-inbox-thread-state.ts +3 -1
- package/src/persistence/migrations/015-drop-active-search-index.ts +3 -1
- package/src/persistence/migrations/019-notification-tables-schema-migration.ts +3 -1
- package/src/persistence/migrations/020-rename-macos-ios-channel-to-vellum.ts +3 -1
- package/src/persistence/migrations/024-embedding-vector-blob.ts +6 -2
- package/src/persistence/migrations/025-messages-fts-backfill.ts +3 -1
- package/src/persistence/migrations/026a-embeddings-nullable-vector-json.ts +9 -3
- package/src/persistence/migrations/036-normalize-phone-identities.ts +36 -12
- package/src/persistence/migrations/120-fk-cascade-rebuilds.ts +12 -4
- package/src/persistence/migrations/126-backfill-guardian-principal-id.ts +6 -2
- package/src/persistence/migrations/127-guardian-principal-id-not-null.ts +15 -5
- package/src/persistence/migrations/134-contacts-notes-column.ts +10 -4
- package/src/persistence/migrations/135-backfill-contact-interaction-stats.ts +6 -2
- package/src/persistence/migrations/136-drop-assistant-id-columns.ts +12 -4
- package/src/persistence/migrations/140-backfill-usage-cache-accounting.ts +24 -8
- package/src/persistence/migrations/141-rename-verification-table.ts +12 -4
- package/src/persistence/migrations/142-rename-verification-session-id-column.ts +6 -2
- package/src/persistence/migrations/147-migrate-reminders-to-schedules.ts +6 -2
- package/src/persistence/migrations/150-oauth-apps-client-secret-path.ts +12 -4
- package/src/persistence/migrations/157-invite-contact-id.ts +3 -1
- package/src/persistence/migrations/162-guardian-timestamps-epoch-ms.ts +21 -8
- package/src/persistence/migrations/174-rename-thread-starters-table.ts +12 -4
- package/src/persistence/migrations/180-backfill-inline-attachments-to-disk.ts +3 -1
- package/src/persistence/migrations/196-strip-integration-prefix-from-provider-keys.ts +6 -2
- package/src/persistence/migrations/206-scrub-corrupted-image-attachments.ts +3 -1
- package/src/persistence/migrations/209-strip-thinking-from-consolidated.ts +3 -1
- package/src/persistence/migrations/220-normalize-user-file-by-principal.ts +24 -8
- package/src/persistence/migrations/222-strip-placeholder-sentinels-from-messages.ts +3 -1
- package/src/persistence/migrations/231-repair-memory-graph-event-dates.ts +18 -6
- package/src/persistence/migrations/241-activation-state-fk-cascade.ts +6 -2
- package/src/persistence/migrations/246-backfill-provider-connection-label.ts +3 -1
- package/src/persistence/migrations/247-external-conversation-binding-thread-id.ts +3 -1
- package/src/persistence/migrations/249-normalize-slack-external-content.ts +30 -10
- package/src/persistence/migrations/256-memory-v2-injection-events.ts +24 -8
- package/src/persistence/migrations/296-rewrite-balanced-economy-profile-pins.test.ts +3 -1
- package/src/persistence/migrations/296-rewrite-balanced-economy-profile-pins.ts +6 -2
- package/src/persistence/migrations/297-move-llm-request-logs-to-logs-db.ts +3 -1
- package/src/persistence/migrations/302-create-compaction-events.ts +3 -1
- package/src/persistence/migrations/306-rewrite-frontier-profile-pins.test.ts +3 -1
- package/src/persistence/migrations/306-rewrite-frontier-profile-pins.ts +6 -2
- package/src/persistence/migrations/311-create-subagents-table.ts +5 -3
- package/src/persistence/migrations/318-drop-contact-channel-telemetry.ts +3 -1
- package/src/persistence/migrations/319-remove-legacy-managed-connections.ts +3 -1
- package/src/persistence/migrations/329-move-onboarding-events-to-telemetry-db.ts +3 -1
- package/src/persistence/migrations/340-sweep-orphaned-graph-node-vectors.test.ts +9 -0
- package/src/persistence/migrations/342-add-conversation-parent-id.test.ts +1 -3
- package/src/persistence/migrations/352-drop-schedule-skill-script-handoff.ts +3 -1
- package/src/persistence/migrations/355-add-schedule-group-id.ts +22 -0
- package/src/persistence/migrations/356-add-subagent-parent-tool-use-id.test.ts +87 -0
- package/src/persistence/migrations/356-add-subagent-parent-tool-use-id.ts +31 -0
- package/src/persistence/migrations/357-move-memory-segments-to-memory-db.ts +95 -0
- package/src/persistence/migrations/358-move-memory-embeddings-to-memory-db.ts +83 -0
- package/src/persistence/migrations/359-move-memory-summaries-to-memory-db.ts +86 -0
- package/src/persistence/migrations/__tests__/350-conversations-total-input-tokens-nullable.test.ts +3 -1
- package/src/persistence/migrations/run-migrations.ts +12 -4
- package/src/persistence/migrations/validate-migration-state.ts +12 -4
- package/src/persistence/raw-query.ts +9 -3
- package/src/persistence/schema/conversation-groups.ts +2 -0
- package/src/persistence/schema/infrastructure.ts +1 -0
- package/src/persistence/slow-query-log.ts +27 -9
- package/src/persistence/slow-sync-log.ts +3 -1
- package/src/persistence/steps.ts +60 -0
- package/src/persistence/subagent-store.ts +187 -8
- package/src/persistence/usage-buckets.ts +9 -3
- package/src/persistence/usage-grouped-buckets.ts +6 -2
- package/src/platform/feature-gate.ts +3 -1
- package/src/platform/sync-identity.ts +9 -3
- package/src/playbooks/playbook-compiler.ts +3 -1
- package/src/plugin-api/index.ts +34 -1
- package/src/plugin-api/model-profiles.test.ts +30 -0
- package/src/plugin-api/model-profiles.ts +11 -4
- package/src/plugin-api/vision-support.test.ts +65 -2
- package/src/plugin-api/vision-support.ts +15 -3
- package/src/plugins/defaults/channel/injectors.ts +12 -4
- package/src/plugins/defaults/compaction/window-manager.ts +30 -10
- package/src/plugins/defaults/documents/injectors.ts +18 -6
- package/src/plugins/defaults/empty-response/hooks/post-model-call.ts +9 -3
- package/src/plugins/defaults/exploration-drift/hooks/post-tool-use.ts +26 -8
- package/src/plugins/defaults/image-fallback/hooks/post-compact.ts +3 -1
- package/src/plugins/defaults/image-fallback/hooks/post-tool-use.ts +6 -2
- package/src/plugins/defaults/image-fallback/hooks/user-prompt-submit.ts +3 -1
- package/src/plugins/defaults/image-fallback/src/caption-blocks.ts +6 -2
- package/src/plugins/defaults/image-fallback/src/image-persist.ts +3 -1
- package/src/plugins/defaults/image-fallback/src/vision-caption.ts +6 -2
- package/src/plugins/defaults/index.ts +0 -28
- package/src/plugins/defaults/injection-presence.ts +3 -1
- package/src/plugins/defaults/main.ts +31 -0
- package/src/plugins/defaults/max-tokens-continue/hooks/post-model-call.ts +62 -6
- package/src/plugins/defaults/memory/AGENTS.md +10 -7
- package/src/plugins/defaults/memory/__tests__/capability-seed-embed-gate.test.ts +4 -4
- package/src/plugins/defaults/memory/__tests__/compaction-log-store-clickhouse.test.ts +6 -2
- package/src/plugins/defaults/memory/__tests__/conversation-memory-purge.test.ts +1 -0
- package/src/plugins/defaults/memory/__tests__/conversation-queries.test.ts +224 -0
- package/src/plugins/defaults/memory/__tests__/conversation-row-batch-delete.test.ts +18 -34
- package/src/plugins/defaults/memory/__tests__/db-async-query.test.ts +3 -1
- package/src/plugins/defaults/memory/__tests__/db-memory-attach.test.ts +3 -0
- package/src/plugins/defaults/memory/__tests__/embedding-cache.test.ts +10 -7
- package/src/plugins/defaults/memory/__tests__/indexer-tier-dispatch.test.ts +62 -2
- package/src/plugins/defaults/memory/__tests__/relocated-memory-test-rows.ts +16 -0
- package/src/plugins/defaults/memory/__tests__/table-relocation.test.ts +183 -0
- package/src/plugins/defaults/memory/__tests__/worker-control.test.ts +6 -2
- package/src/plugins/defaults/memory/anisotropy.test.ts +18 -6
- package/src/plugins/defaults/memory/anisotropy.ts +45 -15
- package/src/plugins/defaults/memory/context-search/agent-protocol.ts +3 -1
- package/src/plugins/defaults/memory/context-search/agent-runner.ts +6 -2
- package/src/plugins/defaults/memory/context-search/limits.ts +6 -2
- package/src/plugins/defaults/memory/context-search/search.ts +30 -10
- package/src/plugins/defaults/memory/context-search/sources/memory.ts +9 -3
- package/src/plugins/defaults/memory/context-search/sources/workspace.ts +33 -11
- package/src/plugins/defaults/memory/conversation-memory-purge.ts +5 -0
- package/src/plugins/defaults/memory/find-most-recent-retrospective-for.ts +3 -1
- package/src/plugins/defaults/memory/frontmatter.ts +3 -1
- package/src/plugins/defaults/memory/graph/__tests__/conversation-graph-memory-recent-summaries.test.ts +142 -0
- package/src/plugins/defaults/memory/graph/conversation-graph-memory.ts +117 -45
- package/src/plugins/defaults/memory/graph/graph-memory-state-store.ts +9 -3
- package/src/plugins/defaults/memory/graph/graph-search.ts +3 -1
- package/src/plugins/defaults/memory/graph/store.ts +113 -45
- package/src/plugins/defaults/memory/graph/types.ts +20 -7
- package/src/plugins/defaults/memory/graph-topology/__tests__/build-memory-graph.test.ts +1 -0
- package/src/plugins/defaults/memory/indexer.ts +40 -3
- package/src/plugins/defaults/memory/jobs/__tests__/embed-concept-page.test.ts +2 -2
- package/src/plugins/defaults/memory/jobs/embed-concept-page.ts +20 -21
- package/src/plugins/defaults/memory/memory-db.ts +3 -1
- package/src/plugins/defaults/memory/memory-retrospective-accounting.ts +18 -6
- package/src/plugins/defaults/memory/memory-retrospective-state.ts +30 -10
- package/src/plugins/defaults/memory/memory-retrospective-trigger-check.ts +18 -6
- package/src/plugins/defaults/memory/prompt-override.ts +6 -2
- package/src/plugins/defaults/memory/segmenter.ts +6 -2
- package/src/plugins/defaults/memory/src/__tests__/memory-ingest-routes.test.ts +176 -0
- package/src/plugins/defaults/memory/src/__tests__/memory-worker-routes.test.ts +3 -1
- package/src/plugins/defaults/memory/src/memory-ingest-routes.ts +125 -0
- package/src/plugins/defaults/memory/src/memory-v2-routes.ts +5 -2
- package/src/plugins/defaults/memory/substrate/__tests__/consolidation-lock.test.ts +136 -0
- package/src/plugins/defaults/memory/substrate/__tests__/ingest.test.ts +440 -0
- package/src/plugins/defaults/memory/substrate/__tests__/page-index.test.ts +129 -2
- package/src/plugins/defaults/memory/substrate/__tests__/page-store.test.ts +31 -0
- package/src/plugins/defaults/memory/substrate/consolidation-job.ts +10 -218
- package/src/plugins/defaults/memory/substrate/consolidation-lock.ts +250 -0
- package/src/plugins/defaults/memory/substrate/ingest.ts +360 -0
- package/src/plugins/defaults/memory/substrate/page-index.ts +110 -1
- package/src/plugins/defaults/memory/substrate/page-store.ts +20 -24
- package/src/plugins/defaults/memory/substrate/types.ts +12 -0
- package/src/plugins/defaults/memory/task-memory-cleanup.ts +18 -6
- package/src/plugins/defaults/memory/v1/graph/bootstrap.ts +27 -10
- package/src/plugins/defaults/memory/v1/graph/consolidation.ts +57 -21
- package/src/plugins/defaults/memory/v1/graph/decay.ts +6 -2
- package/src/plugins/defaults/memory/v1/graph/extraction-job.ts +3 -1
- package/src/plugins/defaults/memory/v1/graph/injection.ts +24 -8
- package/src/plugins/defaults/memory/v1/graph/narrative.ts +3 -1
- package/src/plugins/defaults/memory/v1/graph/pattern-scan.ts +3 -1
- package/src/plugins/defaults/memory/v1/graph/scoring.ts +18 -6
- package/src/plugins/defaults/memory/v1/graph/serendipity.ts +9 -3
- package/src/plugins/defaults/memory/v1/graph/triggers.ts +30 -10
- package/src/plugins/defaults/memory/v1/job-handlers/embedding.ts +10 -3
- package/src/plugins/defaults/memory/v1/job-handlers/index-maintenance.ts +12 -12
- package/src/plugins/defaults/memory/v1/jobs/embed-pkb-file.ts +9 -3
- package/src/plugins/defaults/memory/v1/pkb/autoinject.ts +3 -1
- package/src/plugins/defaults/memory/v1/pkb/context.ts +12 -4
- package/src/plugins/defaults/memory/v1/pkb/pkb-reconcile.test.ts +3 -1
- package/src/plugins/defaults/memory/v1/pkb/pkb-reconcile.ts +3 -1
- package/src/plugins/defaults/memory/v1/pkb/pkb-search.test.ts +6 -2
- package/src/plugins/defaults/memory/v1/pkb/pkb-search.ts +15 -5
- package/src/plugins/defaults/memory/v1/pkb-schedule.ts +3 -1
- package/src/plugins/defaults/memory/v1/semantic-search.ts +30 -15
- package/src/plugins/defaults/memory/v2/harness/metrics.ts +9 -3
- package/src/plugins/defaults/memory/v2/harness/runner.ts +9 -3
- package/src/plugins/defaults/memory/v2/injection-events.ts +21 -7
- package/src/plugins/defaults/memory/v3/__tests__/card.test.ts +2 -2
- package/src/plugins/defaults/memory/v3/__tests__/carry-integration.test.ts +1 -0
- package/src/plugins/defaults/memory/v3/__tests__/dense.test.ts +9 -3
- package/src/plugins/defaults/memory/v3/__tests__/edge.test.ts +9 -1
- package/src/plugins/defaults/memory/v3/__tests__/fresh-set.test.ts +39 -5
- package/src/plugins/defaults/memory/v3/__tests__/injection.test.ts +6 -2
- package/src/plugins/defaults/memory/v3/__tests__/live-integration.test.ts +1 -0
- package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +2 -0
- package/src/plugins/defaults/memory/v3/__tests__/section-dense-store.test.ts +13 -3
- package/src/plugins/defaults/memory/v3/__tests__/shadow-integration.test.ts +1 -0
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +4 -0
- package/src/plugins/defaults/memory/v3/card.ts +1 -1
- package/src/plugins/defaults/memory/v3/core-set.ts +6 -2
- package/src/plugins/defaults/memory/v3/dense.ts +15 -5
- package/src/plugins/defaults/memory/v3/entity-lane.ts +9 -3
- package/src/plugins/defaults/memory/v3/ever-injected-store.ts +39 -13
- package/src/plugins/defaults/memory/v3/fresh-set.ts +27 -15
- package/src/plugins/defaults/memory/v3/hot-set.ts +6 -2
- package/src/plugins/defaults/memory/v3/injector.ts +51 -17
- package/src/plugins/defaults/memory/v3/learned-edges.ts +21 -7
- package/src/plugins/defaults/memory/v3/llm-retry.ts +3 -1
- package/src/plugins/defaults/memory/v3/orchestrate.ts +15 -5
- package/src/plugins/defaults/memory/v3/pool-select.test.ts +3 -1
- package/src/plugins/defaults/memory/v3/pool-select.ts +15 -5
- package/src/plugins/defaults/memory/v3/render-injection.ts +6 -2
- package/src/plugins/defaults/memory/v3/section-dense-store.ts +51 -25
- package/src/plugins/defaults/memory/v3/section-needle.ts +27 -9
- package/src/plugins/defaults/memory/v3/sections.ts +6 -2
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +24 -17
- package/src/plugins/defaults/memory/v3-eval/__tests__/eval-tally.test.ts +9 -3
- package/src/plugins/defaults/memory/v3-eval/eval-packets.ts +6 -0
- package/src/plugins/defaults/memory/v3-eval/eval-tally.ts +22 -9
- package/src/plugins/defaults/memory/worker.ts +54 -10
- package/src/plugins/defaults/session/injectors.ts +15 -5
- package/src/plugins/defaults/surface-completion-nudge/hooks/post-model-call.ts +49 -17
- package/src/plugins/defaults/task-progress-nudge/hooks/post-tool-use.ts +33 -11
- package/src/plugins/defaults/title-generate/hooks/stop.ts +15 -5
- package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +6 -2
- package/src/plugins/defaults/tool-error/hooks/post-tool-use.ts +21 -7
- package/src/plugins/defaults/tool-result-truncate/terminal.ts +3 -1
- package/src/plugins/defaults/turn-context/injectors.ts +3 -1
- package/src/plugins/defaults/workspace/injectors.ts +52 -18
- package/src/plugins/external-plugin-loader.ts +21 -7
- package/src/plugins/injector-registry.ts +6 -2
- package/src/prompts/__tests__/system-prompt.test.ts +5 -2
- package/src/prompts/bootstrap-cleanup.ts +3 -1
- package/src/prompts/normalize-onboarding.ts +9 -3
- package/src/prompts/persona-resolver.ts +33 -11
- package/src/prompts/sections.ts +42 -14
- package/src/prompts/system-prompt.ts +30 -10
- package/src/prompts/template-detection.ts +6 -2
- package/src/prompts/templates/system-sections.ts +55 -20
- package/src/prompts/user-reference.ts +6 -2
- package/src/providers/__tests__/connection-model-compat.test.ts +6 -1
- package/src/providers/__tests__/inference.test.ts +24 -8
- package/src/providers/__tests__/preflight-resolved-config.test.ts +25 -0
- package/src/providers/__tests__/request-diagnostics.test.ts +131 -0
- package/src/providers/__tests__/retry-callsite.test.ts +30 -0
- package/src/providers/__tests__/search-provider-catalog.test.ts +4 -1
- package/src/providers/__tests__/vellum-mismatch-routing.test.ts +108 -1
- package/src/providers/anthropic/client.ts +119 -41
- package/src/providers/call-site-routing.ts +7 -0
- package/src/providers/connection-model-compat.ts +12 -4
- package/src/providers/connection-resolution.ts +61 -1
- package/src/providers/fetch-provider-catalog.ts +3 -2
- package/src/providers/gemini/client.ts +86 -12
- package/src/providers/inference/codex-token-refresh.ts +6 -2
- package/src/providers/inference/connection-availability.ts +13 -1
- package/src/providers/inference/connections.ts +78 -15
- package/src/providers/media-resolve.ts +21 -7
- package/src/providers/model-catalog.ts +104 -63
- package/src/providers/model-intents.ts +2 -2
- package/src/providers/ollama/client.ts +3 -1
- package/src/providers/openai/__tests__/chat-completions-input-audio.test.ts +3 -1
- package/src/providers/openai/__tests__/chat-completions-provider-endpoint.test.ts +3 -1
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +3 -1
- package/src/providers/openai/api-error-normalization.ts +75 -25
- package/src/providers/openai/chat-completions-provider.ts +49 -16
- package/src/providers/openai/codex-models.ts +9 -5
- package/src/providers/openai/coerce-object-args.ts +12 -4
- package/src/providers/openai/responses-provider.ts +31 -11
- package/src/providers/openrouter/client.ts +9 -3
- package/src/providers/platform-proxy/context.ts +9 -3
- package/src/providers/provider-catalog-visibility.ts +4 -4
- package/src/providers/provider-send-message.ts +6 -0
- package/src/providers/ratelimit.ts +6 -2
- package/src/providers/request-diagnostics.ts +225 -0
- package/src/providers/retry.ts +68 -17
- package/src/providers/routing-identity.ts +2 -1
- package/src/providers/search-provider-catalog.ts +18 -0
- package/src/providers/speech-to-text/__tests__/deepgram.test.ts +27 -0
- package/src/providers/speech-to-text/__tests__/provider-catalog.test.ts +25 -0
- package/src/providers/speech-to-text/__tests__/resolve.test.ts +195 -1
- package/src/providers/speech-to-text/deepgram-realtime.test.ts +18 -6
- package/src/providers/speech-to-text/deepgram-realtime.ts +9 -1
- package/src/providers/speech-to-text/deepgram.ts +117 -1
- package/src/providers/speech-to-text/google-gemini-live-stream.test.ts +116 -132
- package/src/providers/speech-to-text/google-gemini-live-stream.ts +87 -31
- package/src/providers/speech-to-text/provider-catalog.ts +17 -0
- package/src/providers/speech-to-text/resolve.ts +64 -5
- package/src/providers/speech-to-text/xai-realtime.test.ts +18 -6
- package/src/providers/speech-to-text/xai-realtime.ts +60 -20
- package/src/providers/speech-to-text/xai.test.ts +43 -0
- package/src/providers/speech-to-text/xai.ts +48 -7
- package/src/providers/stop-reasons.ts +3 -1
- package/src/providers/thinking-config.ts +7 -1
- package/src/providers/tool-progress-events.ts +15 -5
- package/src/providers/usage-tracking.ts +6 -2
- package/src/routes/route-host-client.ts +3 -2
- package/src/routes/route-host-protocol.ts +1 -1
- package/src/routes/worker.ts +3 -2
- package/src/runtime/__tests__/agent-wake.test.ts +3 -1
- package/src/runtime/__tests__/interactive-ui.test.ts +3 -1
- package/src/runtime/__tests__/local-principal-trust.test.ts +10 -8
- package/src/runtime/anchored-guardian.test.ts +45 -8
- package/src/runtime/anchored-guardian.ts +4 -1
- package/src/runtime/approval-conversation-turn.ts +17 -7
- package/src/runtime/approval-message-composer.ts +6 -2
- package/src/runtime/auth/__tests__/guard-tests.test.ts +24 -8
- package/src/runtime/auth/middleware.ts +0 -2
- package/src/runtime/auth/owner-caller.ts +95 -0
- package/src/runtime/auth/require-bound-guardian.ts +7 -22
- package/src/runtime/auth/same-actor.ts +12 -4
- package/src/runtime/background-job-runner.ts +12 -4
- package/src/runtime/channel-invite-transports/slack.ts +6 -2
- package/src/runtime/channel-invite-transports/telegram.ts +6 -2
- package/src/runtime/channel-verification-service.ts +9 -3
- package/src/runtime/decision-token.ts +3 -1
- package/src/runtime/guardian-action-message-composer.ts +6 -2
- package/src/runtime/guardian-vellum-migration.ts +18 -6
- package/src/runtime/http-router.ts +18 -6
- package/src/runtime/invite-service.ts +6 -2
- package/src/runtime/local-principal-trust.ts +6 -2
- package/src/runtime/member-verdict-cache.ts +18 -6
- package/src/runtime/middleware/__tests__/request-logger.test.ts +1 -3
- package/src/runtime/middleware/auth.ts +37 -13
- package/src/runtime/middleware/error-handler.ts +1 -4
- package/src/runtime/middleware/rate-limiter.ts +12 -4
- package/src/runtime/middleware/request-logger.ts +12 -4
- package/src/runtime/migrations/__tests__/rebind-secrets-credentials.test.ts +18 -6
- package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +3 -1
- package/src/runtime/migrations/__tests__/vbundle-import-parity.test.ts +9 -3
- package/src/runtime/migrations/__tests__/vbundle-import-version-compat.test.ts +11 -4
- package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +84 -28
- package/src/runtime/migrations/__tests__/vbundle-symlink-importer.test.ts +18 -6
- package/src/runtime/migrations/__tests__/vbundle-symlink-streaming-importer.test.ts +0 -0
- package/src/runtime/migrations/__tests__/vbundle-symlink-tar.test.ts +24 -8
- package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +3 -1
- package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +6 -2
- package/src/runtime/migrations/gcs-signed-url.ts +21 -7
- package/src/runtime/migrations/job-registry.ts +24 -8
- package/src/runtime/migrations/migration-wizard.ts +9 -3
- package/src/runtime/migrations/transfer-progress-screen.ts +3 -1
- package/src/runtime/migrations/validation-results-screen.ts +3 -1
- package/src/runtime/migrations/vbundle-builder.ts +33 -11
- package/src/runtime/migrations/vbundle-import-analyzer.ts +3 -1
- package/src/runtime/migrations/vbundle-import-policy.ts +21 -7
- package/src/runtime/migrations/vbundle-importer.ts +9 -3
- package/src/runtime/migrations/vbundle-metadata-merge.ts +12 -4
- package/src/runtime/migrations/vbundle-streaming-importer.ts +57 -19
- package/src/runtime/migrations/vbundle-tar-stream.ts +15 -5
- package/src/runtime/migrations/vbundle-validator.ts +6 -2
- package/src/runtime/nl-approval-parser.ts +6 -3
- package/src/runtime/no-response.ts +12 -4
- package/src/runtime/pending-interactions.ts +9 -3
- package/src/runtime/pre-first-message-gate.ts +3 -1
- package/src/runtime/routes/__tests__/acp-routes.test.ts +24 -8
- package/src/runtime/routes/__tests__/avatar-state-routes.test.ts +9 -3
- package/src/runtime/routes/__tests__/backup-routes.test.ts +3 -1
- package/src/runtime/routes/__tests__/channel-verification-revoke.test.ts +9 -3
- package/src/runtime/routes/__tests__/client-routes.test.ts +3 -1
- package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +12 -4
- package/src/runtime/routes/__tests__/consolidation-routes.test.ts +3 -1
- package/src/runtime/routes/__tests__/contact-routes-update-channel-relay.test.ts +3 -1
- package/src/runtime/routes/__tests__/contact-routes.test.ts +3 -1
- package/src/runtime/routes/__tests__/content-source-routes.test.ts +3 -1
- package/src/runtime/routes/__tests__/conversation-compaction-routes.test.ts +3 -1
- package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +3 -1
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +3 -1
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +116 -1
- package/src/runtime/routes/__tests__/conversation-surface-routes.test.ts +3 -1
- package/src/runtime/routes/__tests__/default-plugin-routes.test.ts +4 -14
- package/src/runtime/routes/__tests__/default-provider-routes.test.ts +4 -4
- package/src/runtime/routes/__tests__/deprecated-route-context.test.ts +112 -0
- package/src/runtime/routes/__tests__/gateway-log-routes.test.ts +3 -1
- package/src/runtime/routes/__tests__/gateway-status-routes.test.ts +3 -1
- package/src/runtime/routes/__tests__/global-search-routes.test.ts +12 -0
- package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +3 -1
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +6 -3
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +57 -4
- package/src/runtime/routes/__tests__/inference-send-routes.test.ts +79 -2
- package/src/runtime/routes/__tests__/invite-relay-routes.test.ts +3 -1
- package/src/runtime/routes/__tests__/ps-routes.test.ts +12 -4
- package/src/runtime/routes/__tests__/question-routes.test.ts +6 -2
- package/src/runtime/routes/__tests__/retrospective-routes.test.ts +3 -1
- package/src/runtime/routes/__tests__/sanity-routes.test.ts +6 -2
- package/src/runtime/routes/__tests__/schedule-routes-create.test.ts +3 -1
- package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +3 -1
- package/src/runtime/routes/__tests__/stt-routes.test.ts +22 -3
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +9 -3
- package/src/runtime/routes/__tests__/surface-content-routes.test.ts +3 -1
- package/src/runtime/routes/__tests__/tts-routes.test.ts +9 -3
- package/src/runtime/routes/__tests__/user-route-dispatcher-host.test.ts +3 -12
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +26 -115
- package/src/runtime/routes/__tests__/wake-conversation-routes.test.ts +3 -1
- package/src/runtime/routes/acp-routes-list.test.ts +9 -3
- package/src/runtime/routes/acp-routes.test.ts +18 -6
- package/src/runtime/routes/app-management-routes.ts +13 -5
- package/src/runtime/routes/app-routes.ts +3 -1
- package/src/runtime/routes/archive-utils.ts +3 -1
- package/src/runtime/routes/attachment-routes.ts +6 -2
- package/src/runtime/routes/background-wake-routes.ts +12 -4
- package/src/runtime/routes/backup-routes.ts +6 -2
- package/src/runtime/routes/browser-routes.ts +3 -1
- package/src/runtime/routes/call-routes.ts +3 -1
- package/src/runtime/routes/contact-prompt-routes.ts +8 -1
- package/src/runtime/routes/contact-routes.ts +9 -3
- package/src/runtime/routes/conversation-list-routes.ts +3 -1
- package/src/runtime/routes/conversation-management-routes.ts +6 -2
- package/src/runtime/routes/conversation-query-routes.ts +101 -12
- package/src/runtime/routes/conversation-routes.ts +6 -2
- package/src/runtime/routes/conversation-starter-routes.ts +12 -4
- package/src/runtime/routes/conversations-import-routes.ts +28 -2
- package/src/runtime/routes/debug-bash-routes.ts +3 -1
- package/src/runtime/routes/default-provider-routes.ts +8 -4
- package/src/runtime/routes/defer-routes.ts +17 -14
- package/src/runtime/routes/deprecated-route-context.ts +125 -0
- package/src/runtime/routes/diagnostics-routes.ts +3 -1
- package/src/runtime/routes/disk-pressure-routes.ts +12 -4
- package/src/runtime/routes/email-routes.ts +18 -6
- package/src/runtime/routes/errors.ts +13 -0
- package/src/runtime/routes/events-routes.ts +9 -3
- package/src/runtime/routes/global-search-routes.ts +28 -8
- package/src/runtime/routes/group-routes.ts +47 -5
- package/src/runtime/routes/guardian-action-routes.ts +2 -1
- package/src/runtime/routes/heartbeat-routes.ts +12 -6
- package/src/runtime/routes/home-feed-routes.ts +51 -18
- package/src/runtime/routes/host-app-control-routes.ts +40 -45
- package/src/runtime/routes/host-bash-routes.ts +31 -22
- package/src/runtime/routes/host-browser-routes.ts +6 -3
- package/src/runtime/routes/host-cu-routes.ts +26 -36
- package/src/runtime/routes/host-file-routes.ts +29 -40
- package/src/runtime/routes/host-transfer-routes.ts +21 -9
- package/src/runtime/routes/http-adapter.ts +15 -5
- package/src/runtime/routes/identity-routes.ts +15 -5
- package/src/runtime/routes/inbound-stages/admission-policy.test.ts +9 -3
- package/src/runtime/routes/inbound-stages/channel-turn-admission.ts +2 -2
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +12 -4
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/inference-profile-session-handler.ts +6 -2
- package/src/runtime/routes/inference-profile-session-reaper.ts +6 -2
- package/src/runtime/routes/inference-profiles-routes.ts +10 -5
- package/src/runtime/routes/inference-provider-connection-routes.ts +36 -6
- package/src/runtime/routes/inference-send-routes.ts +88 -22
- package/src/runtime/routes/integrations/twilio.ts +3 -1
- package/src/runtime/routes/internal-oauth-routes.ts +6 -2
- package/src/runtime/routes/llm-call-sites-routes.ts +5 -2
- package/src/runtime/routes/llm-context-normalization.ts +36 -12
- package/src/runtime/routes/log-export/__tests__/workspace-allowlist.test.ts +12 -4
- package/src/runtime/routes/log-export/workspace-allowlist.ts +33 -11
- package/src/runtime/routes/log-export-routes.ts +51 -17
- package/src/runtime/routes/mcp-auth-routes.ts +23 -8
- package/src/runtime/routes/migration-rollback-routes.ts +4 -2
- package/src/runtime/routes/migration-routes.ts +24 -8
- package/src/runtime/routes/oauth-apps.ts +3 -1
- package/src/runtime/routes/oauth-commands-routes.ts +66 -22
- package/src/runtime/routes/oauth-connect-routes.ts +14 -5
- package/src/runtime/routes/oauth-providers.ts +89 -34
- package/src/runtime/routes/onboarding-checkin-routes.ts +3 -1
- package/src/runtime/routes/platform-routes.ts +162 -50
- package/src/runtime/routes/playground/__tests__/force-compact.test.ts +6 -2
- package/src/runtime/routes/playground/__tests__/inject-failures.test.ts +9 -3
- package/src/runtime/routes/playground/__tests__/reset-circuit.test.ts +3 -1
- package/src/runtime/routes/playground/__tests__/seed-conversation.test.ts +3 -1
- package/src/runtime/routes/playground/__tests__/seeded-conversations.test.ts +3 -1
- package/src/runtime/routes/playground/__tests__/state.test.ts +3 -1
- package/src/runtime/routes/playground/helpers.ts +9 -3
- package/src/runtime/routes/playground/seeded-conversations.ts +3 -1
- package/src/runtime/routes/profiler-routes.ts +12 -4
- package/src/runtime/routes/question-routes.ts +3 -1
- package/src/runtime/routes/redact-staged-export.ts +15 -5
- package/src/runtime/routes/schedule-routes.ts +135 -38
- package/src/runtime/routes/sequence-routes.ts +23 -10
- package/src/runtime/routes/skills-routes.ts +45 -15
- package/src/runtime/routes/slack-channel-routes.ts +6 -2
- package/src/runtime/routes/sounds-config-routes.ts +15 -5
- package/src/runtime/routes/stt-routes.ts +12 -3
- package/src/runtime/routes/subagents-routes.ts +182 -47
- package/src/runtime/routes/tool-call-question-enrichment.ts +6 -2
- package/src/runtime/routes/user-route-dispatcher.ts +23 -64
- package/src/runtime/routes/user-routes-cli.ts +3 -1
- package/src/runtime/routes/user-routes.ts +1 -10
- package/src/runtime/routes/watcher-routes.ts +15 -5
- package/src/runtime/routes/workflow-routes.test.ts +9 -3
- package/src/runtime/routes/workflow-routes.ts +12 -4
- package/src/runtime/routes/workspace-greetings.ts +12 -4
- package/src/runtime/routes/workspace-routes.ts +12 -4
- package/src/runtime/routes/workspace-utils.ts +6 -2
- package/src/runtime/services/conversation-serializer.ts +9 -3
- package/src/runtime/slack-reply-session.test.ts +3 -1
- package/src/runtime/slack-reply-session.ts +42 -14
- package/src/runtime/trust-verdict-consumer.ts +9 -3
- package/src/runtime/verification-outbound-actions.ts +3 -1
- package/src/runtime/verification-rate-limiter.ts +6 -2
- package/src/schedule/__tests__/run-script.test.ts +62 -0
- package/src/schedule/defer-provenance.ts +51 -0
- package/src/schedule/integration-status.ts +6 -2
- package/src/schedule/recurrence-engine.ts +35 -13
- package/src/schedule/recurrence-types.ts +6 -2
- package/src/schedule/run-script.ts +111 -21
- package/src/schedule/schedule-recovery.ts +6 -2
- package/src/schedule/schedule-store.ts +308 -57
- package/src/schedule/scheduler.ts +9 -11
- package/src/schedule/wake-schedule-options.ts +94 -0
- package/src/security/AGENTS.md +14 -0
- package/src/security/__tests__/oauth2-exchange-body.test.ts +1 -4
- package/src/security/__tests__/provider-key-env-fallback.test.ts +6 -2
- package/src/security/__tests__/untrusted-content.test.ts +21 -2
- package/src/security/ces-credential-client.ts +15 -5
- package/src/security/ces-rpc-credential-backend.ts +6 -2
- package/src/security/credential-key.ts +6 -2
- package/src/security/encrypted-store.ts +47 -18
- package/src/security/oauth-callback-registry.ts +6 -2
- package/src/security/oauth2-device-code.ts +7 -2
- package/src/security/oauth2.ts +36 -7
- package/src/security/redact-json.ts +3 -1
- package/src/security/redaction.ts +3 -1
- package/src/security/secret-allowlist.ts +21 -7
- package/src/security/secret-ingress.ts +3 -1
- package/src/security/secret-scanner.ts +23 -8
- package/src/security/token-manager.ts +4 -2
- package/src/security/tool-approval-digest.ts +3 -1
- package/src/security/untrusted-content.ts +11 -3
- package/src/sequence/analytics.ts +6 -2
- package/src/sequence/guardrails.ts +6 -2
- package/src/sequence/importer.ts +18 -6
- package/src/sequence/reply-matcher.ts +18 -6
- package/src/sequence/store.ts +40 -15
- package/src/services/published-app-updater.ts +9 -3
- package/src/signals/cancel.ts +3 -1
- package/src/signals/conversation-undo.ts +3 -1
- package/src/skills/active-skill-tools.ts +9 -3
- package/src/skills/catalog-cache.ts +4 -1
- package/src/skills/catalog-files.ts +93 -31
- package/src/skills/catalog-install.ts +30 -10
- package/src/skills/categories-cache.ts +9 -3
- package/src/skills/clawhub-files.ts +21 -7
- package/src/skills/clawhub.ts +18 -6
- package/src/skills/frontmatter.ts +3 -1
- package/src/skills/include-graph.ts +33 -11
- package/src/skills/inline-command-expansions.ts +9 -3
- package/src/skills/inline-command-runner.ts +6 -2
- package/src/skills/install-meta.ts +17 -6
- package/src/skills/managed-store.ts +3 -1
- package/src/skills/remote-skill-policy.ts +6 -2
- package/src/skills/skill-cache-store.ts +6 -2
- package/src/skills/skillssh-files.ts +42 -14
- package/src/skills/skillssh-registry.ts +18 -6
- package/src/skills/validate-input.ts +60 -20
- package/src/skills/version-hash.ts +6 -2
- package/src/stt/__tests__/daemon-batch-transcriber.test.ts +136 -2
- package/src/stt/daemon-batch-transcriber.ts +39 -22
- package/src/subagent/consult-prompt.ts +3 -1
- package/src/subagent/consult-transcript.ts +6 -2
- package/src/subagent/index.ts +11 -2
- package/src/subagent/manager.ts +162 -47
- package/src/subagent/types.ts +67 -0
- package/src/subagent/validate-allowlists.ts +6 -2
- package/src/telemetry/tool-usage-store.ts +6 -2
- package/src/telemetry/watchdog-direct-emit.ts +6 -2
- package/src/telemetry/watchdog-events-store.ts +6 -3
- package/src/tools/background-tool-registry.ts +6 -2
- package/src/tools/browser/__tests__/auth-detector.test.ts +20 -0
- package/src/tools/browser/__tests__/browser-untrusted-content.test.ts +512 -0
- package/src/tools/browser/auth-cache.ts +6 -2
- package/src/tools/browser/auth-detector.ts +24 -6
- package/src/tools/browser/browser-execution.ts +245 -47
- package/src/tools/browser/browser-manager.ts +66 -24
- package/src/tools/browser/browser-screencast.ts +6 -2
- package/src/tools/browser/cdp-client/__tests__/accessibility-snapshot.test.ts +27 -0
- package/src/tools/browser/cdp-client/__tests__/browser-tabs-factory.test.ts +75 -27
- package/src/tools/browser/cdp-client/__tests__/cdp-dom-helpers.test.ts +39 -14
- package/src/tools/browser/cdp-client/__tests__/cdp-inspect-client.test.ts +9 -3
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +4 -1
- package/src/tools/browser/cdp-client/accessibility-snapshot.ts +67 -19
- package/src/tools/browser/cdp-client/cdp-dom-helpers.ts +15 -5
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +9 -3
- package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +33 -11
- package/src/tools/browser/cdp-client/cdp-inspect/ws-transport.ts +42 -14
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +36 -11
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +9 -3
- package/src/tools/browser/cdp-client/factory.ts +45 -27
- package/src/tools/browser/cdp-client/local-cdp-client.ts +21 -6
- package/src/tools/browser/cdp-client/types.ts +5 -1
- package/src/tools/browser/network-recorder.ts +45 -15
- package/src/tools/browser/pinned-tabs.ts +28 -9
- package/src/tools/browser/runtime-check.ts +21 -7
- package/src/tools/credentials/broker.ts +3 -1
- package/src/tools/credentials/domain-policy.ts +12 -4
- package/src/tools/credentials/host-pattern-match.ts +3 -1
- package/src/tools/credentials/post-connect-hooks.ts +6 -2
- package/src/tools/credentials/resolve.ts +21 -7
- package/src/tools/credentials/selection.ts +15 -5
- package/src/tools/credentials/tool-policy.ts +6 -2
- package/src/tools/execution-target.ts +3 -1
- package/src/tools/filesystem/fuzzy-match.ts +54 -18
- package/src/tools/filesystem/search.ts +34 -12
- package/src/tools/filesystem/write.ts +12 -4
- package/src/tools/network/__tests__/web-search-metadata.test.ts +9 -3
- package/src/tools/network/__tests__/web-search.test.ts +111 -4
- package/src/tools/network/domain-normalize.ts +12 -4
- package/src/tools/network/managed-search-proxy.ts +24 -8
- package/src/tools/network/script-proxy/session-manager.ts +39 -13
- package/src/tools/network/url-safety.ts +63 -21
- package/src/tools/network/web-fetch.ts +62 -21
- package/src/tools/network/web-search-error.ts +30 -13
- package/src/tools/network/web-search.ts +237 -10
- package/src/tools/schedule/create.ts +18 -0
- package/src/tools/schedule/update.ts +19 -2
- package/src/tools/sensitive-output-placeholders.ts +15 -5
- package/src/tools/shared/filesystem/file-ops-service.ts +6 -2
- package/src/tools/shared/filesystem/image-read.ts +3 -1
- package/src/tools/shared/filesystem/size-guard.ts +6 -2
- package/src/tools/skills/execute.ts +24 -8
- package/src/tools/skills/find-similar-skills.ts +6 -2
- package/src/tools/skills/load.ts +25 -9
- package/src/tools/skills/sandbox-runner.ts +6 -2
- package/src/tools/subagent/read.ts +7 -4
- package/src/tools/subagent/resolve.ts +73 -3
- package/src/tools/subagent/status.ts +66 -5
- package/src/tools/tool-input-summary.ts +3 -1
- package/src/tools/tool-name-aliases.ts +3 -1
- package/src/tools/verification-control-plane-policy.ts +12 -4
- package/src/tools/workflows/manage-workflows.ts +5 -2
- package/src/tts/__tests__/provider-adapters.test.ts +9 -3
- package/src/tts/__tests__/speakable-segments.test.ts +4 -4
- package/src/tts/providers/__tests__/xai-tts-socket.test.ts +26 -12
- package/src/tts/providers/deepgram-provider.ts +3 -1
- package/src/tts/providers/elevenlabs-provider.ts +9 -3
- package/src/tts/providers/fish-audio-provider.ts +3 -1
- package/src/tts/providers/xai-provider.ts +3 -1
- package/src/tts/providers/xai-tts-socket.ts +36 -11
- package/src/tts/synthesize-text.ts +3 -1
- package/src/usage/pricing.ts +27 -9
- package/src/util/abort-reasons.ts +3 -1
- package/src/util/bun-runtime.ts +9 -3
- package/src/util/bundled-asset.ts +6 -2
- package/src/util/canonicalize-identity.ts +3 -1
- package/src/util/cgroup-memory.ts +12 -4
- package/src/util/debounce.ts +11 -4
- package/src/util/diff.ts +18 -6
- package/src/util/disk-usage.ts +15 -5
- package/src/util/errors.ts +1 -0
- package/src/util/favicon.ts +9 -3
- package/src/util/fs.ts +3 -1
- package/src/util/image-conversion.ts +15 -5
- package/src/util/log-redact.ts +6 -2
- package/src/util/logger.ts +15 -5
- package/src/util/phone.ts +6 -2
- package/src/util/platform.ts +18 -6
- package/src/util/pricing.ts +30 -10
- package/src/util/process-liveness.ts +6 -2
- package/src/util/promise-guard.ts +3 -1
- package/src/util/retry.ts +21 -7
- package/src/util/row-mapper.ts +6 -2
- package/src/util/spinner.ts +6 -2
- package/src/util/strip-comment-lines.ts +3 -1
- package/src/util/time.ts +18 -6
- package/src/util/truncate.ts +6 -2
- package/src/util/unicode.ts +9 -3
- package/src/util/xml.ts +1 -4
- package/src/version.ts +9 -3
- package/src/watcher/__tests__/engine.test.ts +331 -4
- package/src/watcher/__tests__/payload-bounds.test.ts +414 -0
- package/src/watcher/constants.ts +69 -0
- package/src/watcher/engine.ts +135 -25
- package/src/watcher/payload-bounds.ts +443 -0
- package/src/watcher/provider-types.ts +13 -0
- package/src/watcher/providers/github.ts +18 -6
- package/src/watcher/providers/gmail.ts +1 -0
- package/src/watcher/providers/google-calendar.ts +36 -16
- package/src/watcher/providers/linear.ts +16 -5
- package/src/watcher/providers/outlook-calendar.ts +4 -1
- package/src/watcher/providers/outlook.ts +1 -0
- package/src/watcher/telemetry.ts +3 -1
- package/src/watcher/watcher-store.ts +32 -12
- package/src/workflows/deterministic-stringify.ts +6 -2
- package/src/workflows/engine-integration.test.ts +3 -1
- package/src/workflows/engine.test.ts +17 -6
- package/src/workflows/engine.ts +88 -32
- package/src/workflows/journal-store.ts +3 -1
- package/src/workflows/leaf-runner.ts +9 -2
- package/src/workflows/library.test.ts +5 -2
- package/src/workflows/library.ts +15 -5
- package/src/workflows/run-manager.test.ts +9 -3
- package/src/workflows/run-manager.ts +18 -6
- package/src/workflows/sandbox.ts +6 -2
- package/src/workspace/adaptive-thinking-repair.ts +33 -11
- package/src/workspace/byok-default-profile-ensure.ts +627 -0
- package/src/workspace/commit-message-enrichment-service.ts +15 -5
- package/src/workspace/custom-profile-ensure.ts +26 -15
- package/src/workspace/default-provider-ensure.ts +11 -10
- package/src/workspace/git-service.ts +12 -4
- package/src/workspace/hatched-date.ts +12 -4
- package/src/workspace/heartbeat-service.ts +3 -1
- package/src/workspace/migrations/003-seed-device-id.ts +12 -4
- package/src/workspace/migrations/004-extract-collect-usage-data.ts +27 -9
- package/src/workspace/migrations/006-services-config.ts +17 -6
- package/src/workspace/migrations/007-web-search-provider-rename.ts +34 -10
- package/src/workspace/migrations/010-app-dir-rename.ts +21 -7
- package/src/workspace/migrations/012-rename-conversation-disk-view-dirs.ts +30 -10
- package/src/workspace/migrations/016-extract-feature-flags-to-protected.ts +12 -4
- package/src/workspace/migrations/017-seed-persona-dirs.ts +15 -5
- package/src/workspace/migrations/018-rekey-compound-credential-keys.ts +30 -10
- package/src/workspace/migrations/019-scope-journal-to-guardian.ts +18 -6
- package/src/workspace/migrations/020-rename-oauth-skill-dirs.ts +6 -2
- package/src/workspace/migrations/021-move-signals-to-workspace.ts +6 -2
- package/src/workspace/migrations/022-move-hooks-to-workspace.ts +6 -2
- package/src/workspace/migrations/023-move-config-files-to-workspace.ts +6 -2
- package/src/workspace/migrations/024-move-runtime-files-to-workspace.ts +6 -2
- package/src/workspace/migrations/025-remove-oauth-app-setup-skills.ts +3 -1
- package/src/workspace/migrations/026-backfill-install-meta.ts +27 -9
- package/src/workspace/migrations/028-recover-conversations-from-disk-view.ts +9 -3
- package/src/workspace/migrations/029-seed-pkb.ts +3 -1
- package/src/workspace/migrations/030-seed-pkb-autoinject.ts +6 -2
- package/src/workspace/migrations/031-drop-user-md.ts +25 -10
- package/src/workspace/migrations/031-llm-log-retention-zero-to-null.ts +28 -10
- package/src/workspace/migrations/032-tts-provider-unification.ts +33 -11
- package/src/workspace/migrations/033-stt-service-explicit-config.ts +12 -4
- package/src/workspace/migrations/034-remove-calls-voice-transcription-provider.ts +24 -8
- package/src/workspace/migrations/036-update-pkb-index-bar.ts +6 -2
- package/src/workspace/migrations/037-create-meets-dir.ts +3 -1
- package/src/workspace/migrations/038-unify-llm-callsite-configs.ts +27 -9
- package/src/workspace/migrations/039-drop-legacy-llm-keys.ts +9 -3
- package/src/workspace/migrations/040-seed-latency-callsite-defaults.ts +15 -5
- package/src/workspace/migrations/041-backfill-google-gmail-settings-scope.ts +9 -3
- package/src/workspace/migrations/042-fix-backfill-google-gmail-settings-scope.ts +9 -3
- package/src/workspace/migrations/044-bump-stale-provider-stream-timeout.ts +11 -4
- package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +12 -4
- package/src/workspace/migrations/047-remove-watch-callsites.ts +18 -5
- package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +9 -3
- package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +12 -4
- package/src/workspace/migrations/052-seed-default-inference-profiles.ts +12 -4
- package/src/workspace/migrations/054-seed-recall-callsite.ts +12 -4
- package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +39 -13
- package/src/workspace/migrations/059-move-pid-to-workspace.ts +6 -2
- package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +6 -2
- package/src/workspace/migrations/064-unwind-main-agent-opus-seed.ts +21 -7
- package/src/workspace/migrations/065-bump-stale-heartbeat-interval.ts +12 -3
- package/src/workspace/migrations/066-seed-heartbeat-callsite-cost-default.ts +18 -6
- package/src/workspace/migrations/069-seed-onboarding-threads.ts +9 -3
- package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +12 -4
- package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +21 -7
- package/src/workspace/migrations/074-drop-deprecated-secret-detection-keys.ts +12 -4
- package/src/workspace/migrations/075-memory-v2-bm25-b-default-reembed.ts +9 -3
- package/src/workspace/migrations/076-drop-services-inference-mode.ts +13 -5
- package/src/workspace/migrations/077-seed-memory-router-callsite.ts +9 -3
- package/src/workspace/migrations/079-home-feed-notification-only.ts +21 -7
- package/src/workspace/migrations/080-restrict-vercel-api-token-metadata.ts +3 -1
- package/src/workspace/migrations/081-backfill-bash-allowed-tools-for-injection-credentials.ts +9 -3
- package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +15 -5
- package/src/workspace/migrations/083-system-prompt-prefix-to-file.ts +8 -3
- package/src/workspace/migrations/084-remove-legacy-skills-index.ts +42 -14
- package/src/workspace/migrations/085-memory-v2-bm25-b-reembed-disabled-v2-pages.ts +12 -4
- package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +33 -11
- package/src/workspace/migrations/087-memory-router-balanced-profile.ts +15 -5
- package/src/workspace/migrations/088-deprecate-background-conversation-override.ts +9 -3
- package/src/workspace/migrations/089-move-memory-tree-out-of-v3.ts +6 -2
- package/src/workspace/migrations/090-memory-router-cost-optimized-profile.ts +21 -7
- package/src/workspace/migrations/091-retighten-migration-onboarding-thread.ts +9 -3
- package/src/workspace/migrations/092-backfill-v3-leaves.ts +30 -10
- package/src/workspace/migrations/093-backfill-leaf-ids.ts +15 -5
- package/src/workspace/migrations/094-seed-avatar-manifest.ts +9 -3
- package/src/workspace/migrations/095-bump-heartbeat-interval-30m-to-60m.ts +12 -3
- package/src/workspace/migrations/096-reduce-quality-profile-effort.ts +18 -6
- package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +27 -9
- package/src/workspace/migrations/099-disable-cache-one-shot-callsites.ts +24 -8
- package/src/workspace/migrations/100-upgrade-quality-profile-to-fable-5.ts +21 -7
- package/src/workspace/migrations/101-upgrade-balanced-economy-to-minimax-m3.ts +15 -5
- package/src/workspace/migrations/102-preserve-heartbeat-enabled-for-existing-workspaces.ts +9 -3
- package/src/workspace/migrations/103-upgrade-quality-profile-to-opus-4-8.ts +21 -7
- package/src/workspace/migrations/104-recheck-adaptive-thinking-model-implied-anthropic.ts +27 -9
- package/src/workspace/migrations/105-enable-memory-v3-live-for-new-workspaces.ts +21 -7
- package/src/workspace/migrations/106-drop-collect-usage-data.ts +9 -3
- package/src/workspace/migrations/107-drop-send-diagnostics.ts +9 -3
- package/src/workspace/migrations/108-drop-balanced-economy-profile.ts +18 -6
- package/src/workspace/migrations/109-swap-quality-profile-to-glm-5p2.ts +9 -3
- package/src/workspace/migrations/110-flip-balanced-profile-to-together.ts +12 -4
- package/src/workspace/migrations/111-prune-seeded-callsite-defaults.ts +36 -12
- package/src/workspace/migrations/112-remove-advisor-callsite-override.ts +18 -5
- package/src/workspace/migrations/113-swap-balanced-profile-to-glm-5p2.ts +18 -6
- package/src/workspace/migrations/114-swap-quality-profile-to-opus.ts +12 -4
- package/src/workspace/migrations/115-drop-frontier-profile.ts +18 -6
- package/src/workspace/migrations/117-normalize-stale-lean-memory-v3-defaults.ts +15 -5
- package/src/workspace/migrations/118-seed-now-md.ts +3 -1
- package/src/workspace/migrations/119-strip-persisted-memory-v3-tuning-defaults.ts +18 -6
- package/src/workspace/migrations/120-revise-onboarding-threads.ts +9 -3
- package/src/workspace/migrations/121-seed-default-user-guardrails.ts +3 -1
- package/src/workspace/migrations/123-swap-quality-profile-to-fable.ts +24 -8
- package/src/workspace/migrations/125-repoint-managed-connections-to-vellum.ts +21 -7
- package/src/workspace/migrations/126-strip-managed-profile-bodies.ts +21 -7
- package/src/workspace/migrations/129-remove-analyze-conversation-config.ts +9 -3
- package/src/workspace/migrations/130-speech-mode-to-provider.ts +24 -8
- package/src/workspace/migrations/131-drop-web-fetch-mode.ts +13 -5
- package/src/workspace/migrations/133-collapse-provider-connections.ts +30 -10
- package/src/workspace/migrations/136-repair-stale-fireworks-kimi-model-id.ts +127 -0
- package/src/workspace/migrations/__tests__/backfill-leaf-ids.test.ts +3 -1
- package/src/workspace/migrations/migrate-to-workspace-volume.ts +9 -3
- package/src/workspace/migrations/rebuild-conversation-disk-view.ts +23 -8
- package/src/workspace/migrations/registry.ts +2 -0
- package/src/workspace/migrations/utils.ts +3 -1
- package/src/workspace/top-level-renderer.ts +3 -1
- package/src/__tests__/history-repair-hook.test.ts +0 -392
- package/src/daemon/__tests__/route-conversation-post.test.ts +0 -158
- package/src/daemon/route-conversation-post.ts +0 -158
- package/src/plugins/defaults/history-repair/hooks/post-model-call.ts +0 -50
- package/src/plugins/defaults/history-repair/hooks/stop.ts +0 -22
- package/src/plugins/defaults/history-repair/hooks/user-prompt-submit.ts +0 -35
- package/src/plugins/defaults/history-repair/package.json +0 -14
- package/src/plugins/defaults/history-repair/repair-state-store.ts +0 -51
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
existsSync,
|
|
3
|
+
readdirSync,
|
|
3
4
|
readFileSync,
|
|
4
5
|
rmSync,
|
|
5
6
|
unlinkSync,
|
|
@@ -37,7 +38,9 @@ interface WorkerResponse {
|
|
|
37
38
|
* that can be resolved by clearing the model cache and re-downloading.
|
|
38
39
|
*/
|
|
39
40
|
function isModelCorruptionError(err: unknown): boolean {
|
|
40
|
-
if (!(err instanceof Error))
|
|
41
|
+
if (!(err instanceof Error)) {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
41
44
|
const msg = err.message.toLowerCase();
|
|
42
45
|
return (
|
|
43
46
|
msg.includes("protobuf parsing") ||
|
|
@@ -61,6 +64,207 @@ function clearModelCache(): void {
|
|
|
61
64
|
}
|
|
62
65
|
}
|
|
63
66
|
|
|
67
|
+
/** How long a worker gets to exit after each signal before we escalate. */
|
|
68
|
+
const WORKER_TERMINATE_GRACE_MS = 2_000;
|
|
69
|
+
|
|
70
|
+
/** Poll interval while waiting for a worker we hold no handle for to exit. */
|
|
71
|
+
const WORKER_EXIT_POLL_MS = 50;
|
|
72
|
+
|
|
73
|
+
/** Whether `promise` settles within `timeoutMs`. */
|
|
74
|
+
async function didSettle(
|
|
75
|
+
promise: Promise<unknown>,
|
|
76
|
+
timeoutMs: number,
|
|
77
|
+
): Promise<boolean> {
|
|
78
|
+
const timeout = Symbol("timeout");
|
|
79
|
+
const result = await Promise.race([
|
|
80
|
+
promise.then(() => undefined),
|
|
81
|
+
Bun.sleep(timeoutMs).then(() => timeout),
|
|
82
|
+
]);
|
|
83
|
+
return result !== timeout;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/** Whether a PID names a live process. */
|
|
87
|
+
function isProcessAlive(pid: number): boolean {
|
|
88
|
+
try {
|
|
89
|
+
// Signal 0 probes for liveness without delivering a signal.
|
|
90
|
+
process.kill(pid, 0);
|
|
91
|
+
return true;
|
|
92
|
+
} catch {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
interface WorkerProcess {
|
|
98
|
+
pid: number;
|
|
99
|
+
ppid: number;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* What this process may do with an embed worker it found in the process table.
|
|
104
|
+
*
|
|
105
|
+
* - `reclaim`: parented to us, a worker we started and lost track of. Reaping
|
|
106
|
+
* it is what enforces one live worker per owning process.
|
|
107
|
+
* - `orphan`: reparented to init, or its owner is gone. Nobody else will ever
|
|
108
|
+
* clean it up.
|
|
109
|
+
* - `foreign`: owned by another live process. The memory-worker process runs
|
|
110
|
+
* its own backend against this same workspace and is entitled to its own
|
|
111
|
+
* worker; signalling it is what made the two replace each other in a loop.
|
|
112
|
+
*
|
|
113
|
+
* A parent of PID 1 is ambiguous, and resolving it wrongly in either direction
|
|
114
|
+
* costs something real. `docker-entrypoint.sh` execs the daemon, so PID 1 can
|
|
115
|
+
* BE the daemon and its child a healthy sibling's worker. Under `docker run
|
|
116
|
+
* --init`, and on any host, PID 1 is an init process instead, so the same
|
|
117
|
+
* parentage means the owner died and the worker needs reclaiming. Callers
|
|
118
|
+
* therefore pass what PID 1 actually is rather than inferring it from whether
|
|
119
|
+
* the deployment is containerized, which is true in both container shapes.
|
|
120
|
+
*/
|
|
121
|
+
export type WorkerOwnership = "reclaim" | "orphan" | "foreign";
|
|
122
|
+
|
|
123
|
+
export function classifyWorkerOwnership(
|
|
124
|
+
worker: WorkerProcess,
|
|
125
|
+
selfPid: number,
|
|
126
|
+
isOwnerAlive: (pid: number) => boolean,
|
|
127
|
+
pid1OwnsWorkers: boolean,
|
|
128
|
+
): WorkerOwnership {
|
|
129
|
+
if (worker.ppid === selfPid) {
|
|
130
|
+
return "reclaim";
|
|
131
|
+
}
|
|
132
|
+
if (worker.ppid <= 1) {
|
|
133
|
+
return pid1OwnsWorkers ? "foreign" : "orphan";
|
|
134
|
+
}
|
|
135
|
+
if (!isOwnerAlive(worker.ppid)) {
|
|
136
|
+
return "orphan";
|
|
137
|
+
}
|
|
138
|
+
return "foreign";
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** Entrypoint the daemon is exec'd with, including inside a container. */
|
|
142
|
+
const DAEMON_ENTRYPOINT_MARKER = "daemon/main";
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Whether PID 1 is an assistant daemon rather than an init process.
|
|
146
|
+
*
|
|
147
|
+
* True only where the daemon was exec'd as PID 1 (`docker-entrypoint.sh`),
|
|
148
|
+
* which is what makes a worker parented to 1 a live sibling's rather than an
|
|
149
|
+
* orphan. Under `docker run --init` PID 1 is docker-init and under launchd or
|
|
150
|
+
* systemd it is the system init, so both answer false and PID-1 orphans stay
|
|
151
|
+
* reclaimable. Unreadable means false, which keeps the reclaiming behaviour.
|
|
152
|
+
*/
|
|
153
|
+
function pid1OwnsEmbedWorkers(): boolean {
|
|
154
|
+
if (process.pid === 1) {
|
|
155
|
+
return true;
|
|
156
|
+
}
|
|
157
|
+
let cmd: string;
|
|
158
|
+
try {
|
|
159
|
+
cmd = readFileSync("/proc/1/cmdline", "utf8").split("\0").join(" ");
|
|
160
|
+
} catch {
|
|
161
|
+
const result = Bun.spawnSync({
|
|
162
|
+
cmd: ["ps", "-ww", "-p", "1", "-o", "command="],
|
|
163
|
+
stdout: "pipe",
|
|
164
|
+
stderr: "ignore",
|
|
165
|
+
});
|
|
166
|
+
if (result.exitCode !== 0) {
|
|
167
|
+
return false;
|
|
168
|
+
}
|
|
169
|
+
cmd = new TextDecoder().decode(result.stdout);
|
|
170
|
+
}
|
|
171
|
+
return cmd.includes(DAEMON_ENTRYPOINT_MARKER);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/** Enumerate `(pid, ppid, rawCommand)` rows from Linux `/proc`. */
|
|
175
|
+
function listProcessRowsFromProc(): {
|
|
176
|
+
pid: number;
|
|
177
|
+
ppid: number;
|
|
178
|
+
cmd: string;
|
|
179
|
+
}[] {
|
|
180
|
+
const rows: { pid: number; ppid: number; cmd: string }[] = [];
|
|
181
|
+
for (const entry of readdirSync("/proc")) {
|
|
182
|
+
const pid = Number(entry);
|
|
183
|
+
if (!Number.isInteger(pid) || pid <= 0) {
|
|
184
|
+
continue;
|
|
185
|
+
}
|
|
186
|
+
try {
|
|
187
|
+
// `stat` field 4 is ppid, but `comm` (field 2) may contain spaces or
|
|
188
|
+
// parens, so parse from the last ')' and a weird comm cannot shift fields.
|
|
189
|
+
const stat = readFileSync(`/proc/${pid}/stat`, "utf8");
|
|
190
|
+
const after = stat.slice(stat.lastIndexOf(")") + 2).split(" ");
|
|
191
|
+
const ppid = Number(after[1]);
|
|
192
|
+
const cmd = readFileSync(`/proc/${pid}/cmdline`, "utf8")
|
|
193
|
+
.split("\0")
|
|
194
|
+
.filter(Boolean)
|
|
195
|
+
.join(" ");
|
|
196
|
+
if (Number.isInteger(ppid)) {
|
|
197
|
+
rows.push({ pid, ppid, cmd });
|
|
198
|
+
}
|
|
199
|
+
} catch {
|
|
200
|
+
// Process exited between readdir and read, so skip it.
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return rows;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/** Enumerate `(pid, ppid, rawCommand)` rows via `ps` (macOS / no `/proc`). */
|
|
207
|
+
function listProcessRowsFromPs(): { pid: number; ppid: number; cmd: string }[] {
|
|
208
|
+
// `-ww` disables column-width truncation. Without it, macOS `ps` clips the
|
|
209
|
+
// command field to the terminal width, which can cut off the workerPath
|
|
210
|
+
// argument and hide a genuine match. Same flag is used by
|
|
211
|
+
// daemon-control.ts:123 for exactly this reason.
|
|
212
|
+
const result = Bun.spawnSync({
|
|
213
|
+
cmd: ["ps", "-A", "-ww", "-o", "pid=,ppid=,command="],
|
|
214
|
+
stdout: "pipe",
|
|
215
|
+
stderr: "ignore",
|
|
216
|
+
});
|
|
217
|
+
if (result.exitCode !== 0) {
|
|
218
|
+
return [];
|
|
219
|
+
}
|
|
220
|
+
const rows: { pid: number; ppid: number; cmd: string }[] = [];
|
|
221
|
+
for (const line of new TextDecoder().decode(result.stdout).split("\n")) {
|
|
222
|
+
const m = line.match(/^\s*(\d+)\s+(\d+)\s+(.*)$/);
|
|
223
|
+
if (m) {
|
|
224
|
+
rows.push({ pid: Number(m[1]), ppid: Number(m[2]), cmd: m[3].trim() });
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return rows;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Live embed-worker processes for this workspace, as `(pid, ppid)` pairs.
|
|
232
|
+
*
|
|
233
|
+
* Ownership of an embed worker is recorded by the OS process tree, not by the
|
|
234
|
+
* PID file: a worker's parent IS its owner. The process table is therefore the
|
|
235
|
+
* authoritative answer to "whose worker is this", and unlike the PID file it
|
|
236
|
+
* survives a crash and cannot be overwritten by a second owner. That matters
|
|
237
|
+
* because the daemon and the memory-worker process legitimately run one worker
|
|
238
|
+
* each against the same workspace.
|
|
239
|
+
*
|
|
240
|
+
* Matches on the absolute worker script path, which lives under THIS
|
|
241
|
+
* workspace's embedding-models directory and is therefore unique per assistant
|
|
242
|
+
* instance, so a sibling instance's workers never match. Raw command lines are
|
|
243
|
+
* read for matching only, never stored or logged: process arguments can carry
|
|
244
|
+
* secrets (see the redaction note in `util/process-tree.ts`).
|
|
245
|
+
*/
|
|
246
|
+
export function listWorkerProcesses(
|
|
247
|
+
workerPath: string,
|
|
248
|
+
model?: string,
|
|
249
|
+
): WorkerProcess[] {
|
|
250
|
+
let rows: { pid: number; ppid: number; cmd: string }[];
|
|
251
|
+
try {
|
|
252
|
+
rows = listProcessRowsFromProc();
|
|
253
|
+
} catch {
|
|
254
|
+
rows = listProcessRowsFromPs();
|
|
255
|
+
}
|
|
256
|
+
return rows
|
|
257
|
+
.filter(
|
|
258
|
+
(r) =>
|
|
259
|
+
r.cmd.includes(workerPath) &&
|
|
260
|
+
// An argv token, not a substring: `foo/bar-small` must not match a
|
|
261
|
+
// `foo/bar-small-v2` worker, or a backend for the shorter name would
|
|
262
|
+
// reclaim the longer one's live worker. Model names carry no spaces.
|
|
263
|
+
(!model || r.cmd.split(/\s+/).includes(model)),
|
|
264
|
+
)
|
|
265
|
+
.map((r) => ({ pid: r.pid, ppid: r.ppid }));
|
|
266
|
+
}
|
|
267
|
+
|
|
64
268
|
/**
|
|
65
269
|
* Local embedding backend using @huggingface/transformers (ONNX Runtime).
|
|
66
270
|
* Runs BAAI/bge-small-en-v1.5 locally — no API calls, no network required.
|
|
@@ -94,6 +298,13 @@ export class LocalEmbeddingBackend implements EmbeddingBackend {
|
|
|
94
298
|
private disposeRequested = false;
|
|
95
299
|
|
|
96
300
|
private readonly initGuard = new PromiseGuard<void>();
|
|
301
|
+
private initInFlight: Promise<void> | null = null;
|
|
302
|
+
/** A worker signalled but never confirmed dead. Blocks any replacement. */
|
|
303
|
+
private unconfirmedWorker: number | null = null;
|
|
304
|
+
/** Path of the worker script, retained so liveness can be re-probed. */
|
|
305
|
+
private workerPath: string | null = null;
|
|
306
|
+
/** Overridable so tests can exercise the escalation path without the wait. */
|
|
307
|
+
private terminateGraceMs = WORKER_TERMINATE_GRACE_MS;
|
|
97
308
|
|
|
98
309
|
constructor(model: string) {
|
|
99
310
|
this.model = model;
|
|
@@ -106,7 +317,9 @@ export class LocalEmbeddingBackend implements EmbeddingBackend {
|
|
|
106
317
|
if (this.disposeRequested) {
|
|
107
318
|
throw new Error("Local embedding backend is shutting down");
|
|
108
319
|
}
|
|
109
|
-
if (inputs.length === 0)
|
|
320
|
+
if (inputs.length === 0) {
|
|
321
|
+
return [];
|
|
322
|
+
}
|
|
110
323
|
|
|
111
324
|
const texts = inputs.map((i) => {
|
|
112
325
|
const n = normalizeEmbeddingInput(i);
|
|
@@ -115,8 +328,9 @@ export class LocalEmbeddingBackend implements EmbeddingBackend {
|
|
|
115
328
|
}
|
|
116
329
|
return n.text;
|
|
117
330
|
});
|
|
118
|
-
if (options?.signal?.aborted)
|
|
331
|
+
if (options?.signal?.aborted) {
|
|
119
332
|
throw new DOMException("Aborted", "AbortError");
|
|
333
|
+
}
|
|
120
334
|
|
|
121
335
|
this.activeEmbeds++;
|
|
122
336
|
try {
|
|
@@ -125,8 +339,9 @@ export class LocalEmbeddingBackend implements EmbeddingBackend {
|
|
|
125
339
|
const results: number[][] = [];
|
|
126
340
|
const batchSize = 32;
|
|
127
341
|
for (let i = 0; i < texts.length; i += batchSize) {
|
|
128
|
-
if (options?.signal?.aborted)
|
|
342
|
+
if (options?.signal?.aborted) {
|
|
129
343
|
throw new DOMException("Aborted", "AbortError");
|
|
344
|
+
}
|
|
130
345
|
const batch = texts.slice(i, i + batchSize);
|
|
131
346
|
const response = await this.sendRequest(batch);
|
|
132
347
|
if (response.error) {
|
|
@@ -147,23 +362,75 @@ export class LocalEmbeddingBackend implements EmbeddingBackend {
|
|
|
147
362
|
private sendRequest(texts: string[]): Promise<WorkerResponse> {
|
|
148
363
|
const id = ++this.requestCounter;
|
|
149
364
|
return new Promise((resolve) => {
|
|
150
|
-
|
|
365
|
+
const proc = this.workerProc;
|
|
366
|
+
if (!proc) {
|
|
151
367
|
resolve({ id, error: "Worker not initialized" });
|
|
152
368
|
return;
|
|
153
369
|
}
|
|
154
370
|
this.pendingRequests.set(id, { resolve });
|
|
155
|
-
|
|
371
|
+
|
|
372
|
+
// Writing to a worker that has already exited raises EPIPE. That must
|
|
373
|
+
// surface as an ordinary embed failure the caller can fall back from:
|
|
374
|
+
// an escaping EPIPE reaches the daemon's `unhandledRejection` handler,
|
|
375
|
+
// which tears down the whole process (JARVIS-1125).
|
|
376
|
+
//
|
|
377
|
+
// The guard covers `write` as well as `flush`: both are synchronous on
|
|
378
|
+
// Bun's FileSink, and `write` is the call that raises the broken pipe.
|
|
156
379
|
try {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
380
|
+
proc.stdin.write(JSON.stringify({ id, texts }) + "\n");
|
|
381
|
+
proc.stdin.flush();
|
|
382
|
+
} catch (err) {
|
|
383
|
+
this.failPendingRequest(id, err);
|
|
160
384
|
}
|
|
161
385
|
});
|
|
162
386
|
}
|
|
163
387
|
|
|
388
|
+
/**
|
|
389
|
+
* Resolve one in-flight request with an error. Resolving (rather than
|
|
390
|
+
* rejecting) keeps the failure on the normal `embed()` path, where it becomes
|
|
391
|
+
* a thrown `Error` the backend chain can fall back from.
|
|
392
|
+
*/
|
|
393
|
+
private failPendingRequest(id: number, err: unknown): void {
|
|
394
|
+
const pending = this.pendingRequests.get(id);
|
|
395
|
+
if (!pending) {
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
this.pendingRequests.delete(id);
|
|
399
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
400
|
+
log.warn({ err, model: this.model }, "Embedding worker pipe write failed");
|
|
401
|
+
pending.resolve({ id, error: `worker pipe write failed: ${message}` });
|
|
402
|
+
this.disposeIfIdle();
|
|
403
|
+
}
|
|
404
|
+
|
|
164
405
|
private async ensureInitialized(): Promise<void> {
|
|
165
|
-
if (this.workerProc)
|
|
166
|
-
|
|
406
|
+
if (this.workerProc) {
|
|
407
|
+
return;
|
|
408
|
+
}
|
|
409
|
+
// Fail closed: a child we could not confirm dead may still be running, so
|
|
410
|
+
// starting a replacement here would recreate the duplicate-worker bug.
|
|
411
|
+
if (this.unconfirmedWorkerStillAlive()) {
|
|
412
|
+
// Deliberately NOT phrased "Local embedding backend unavailable": that
|
|
413
|
+
// wording is the sentinel `embedding-backend.ts` matches to mark the
|
|
414
|
+
// local backend PERMANENTLY broken (a compiled binary missing
|
|
415
|
+
// onnxruntime-node). This condition is transient and self-healing, so
|
|
416
|
+
// tripping that latch would disable local embeddings for the rest of the
|
|
417
|
+
// process over a worker that is about to disappear.
|
|
418
|
+
throw new Error(
|
|
419
|
+
`Local embedding worker ${this.unconfirmedWorker} could not be confirmed terminated; refusing to spawn a replacement`,
|
|
420
|
+
);
|
|
421
|
+
}
|
|
422
|
+
// Tracked so `shutdown()` can wait for an initialization that has not yet
|
|
423
|
+
// assigned `workerProc`. Without it, shutting down mid-download returns
|
|
424
|
+
// with nothing to reap and the initializer spawns an orphan afterwards.
|
|
425
|
+
const inFlight = this.initGuard.run(() => this.initialize());
|
|
426
|
+
this.initInFlight = inFlight;
|
|
427
|
+
try {
|
|
428
|
+
await inFlight;
|
|
429
|
+
} finally {
|
|
430
|
+
if (this.initInFlight === inFlight) {
|
|
431
|
+
this.initInFlight = null;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
167
434
|
}
|
|
168
435
|
|
|
169
436
|
dispose(): void {
|
|
@@ -222,11 +489,18 @@ export class LocalEmbeddingBackend implements EmbeddingBackend {
|
|
|
222
489
|
const embeddingModelsDir = getEmbeddingModelsDir();
|
|
223
490
|
const modelCacheDir = `${embeddingModelsDir}/model-cache`;
|
|
224
491
|
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
//
|
|
228
|
-
//
|
|
229
|
-
|
|
492
|
+
this.workerPath = workerPath;
|
|
493
|
+
|
|
494
|
+
// Singleton guard: a worker this process already owns (or one orphaned by
|
|
495
|
+
// a crashed owner) may still be running. Reclaim it, and wait for it to be
|
|
496
|
+
// gone, before spawning so two same-owner workers never overlap.
|
|
497
|
+
await this.reclaimOwnedWorkers(workerPath);
|
|
498
|
+
|
|
499
|
+
// Shutdown may have been requested while the reclaim above was running.
|
|
500
|
+
// Spawning now would hand a fresh child to a backend nobody will tear down.
|
|
501
|
+
if (this.disposeRequested) {
|
|
502
|
+
throw new Error("Local embedding backend is shutting down");
|
|
503
|
+
}
|
|
230
504
|
|
|
231
505
|
log.info(
|
|
232
506
|
{ bunPath, workerPath, model: this.model },
|
|
@@ -252,16 +526,22 @@ export class LocalEmbeddingBackend implements EmbeddingBackend {
|
|
|
252
526
|
// Wait for the worker to signal it's ready (model loaded)
|
|
253
527
|
await this.waitForReady();
|
|
254
528
|
} catch (err) {
|
|
255
|
-
//
|
|
529
|
+
// Startup failed. Release ownership through the same bounded path every
|
|
530
|
+
// other teardown uses: a worker wedged in native ONNX ignores SIGTERM, so
|
|
531
|
+
// an unbounded wait here would leave the init guard holding a promise
|
|
532
|
+
// that never settles and every later embed queued behind it.
|
|
256
533
|
this.workerProc = null;
|
|
257
534
|
this.stdoutReaderActive = false;
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
const stderr = await
|
|
535
|
+
// A partial line from the dead worker would otherwise be prepended to the
|
|
536
|
+
// next worker's first line, corrupting its `ready` signal.
|
|
537
|
+
this.stdoutBuffer = "";
|
|
538
|
+
const confirmed = await this.terminateWorker(proc);
|
|
539
|
+
const exitCode = confirmed ? proc.exitCode : undefined;
|
|
540
|
+
// Bounded for the same reason: a live child never closes stderr.
|
|
541
|
+
const stderr = await Promise.race([
|
|
542
|
+
new Response(proc.stderr).text().catch(() => ""),
|
|
543
|
+
Bun.sleep(this.terminateGraceMs).then(() => ""),
|
|
544
|
+
]);
|
|
265
545
|
if (stderr.trim()) {
|
|
266
546
|
log.warn(
|
|
267
547
|
{ stderr: stderr.trim(), exitCode, bunPath },
|
|
@@ -296,10 +576,13 @@ export class LocalEmbeddingBackend implements EmbeddingBackend {
|
|
|
296
576
|
try {
|
|
297
577
|
while (true) {
|
|
298
578
|
const { done, value } = await reader.read();
|
|
299
|
-
if (done)
|
|
579
|
+
if (done) {
|
|
580
|
+
break;
|
|
581
|
+
}
|
|
300
582
|
const text = decoder.decode(value, { stream: true }).trim();
|
|
301
|
-
if (text)
|
|
583
|
+
if (text) {
|
|
302
584
|
log.debug({ workerStderr: text }, "Embedding worker stderr");
|
|
585
|
+
}
|
|
303
586
|
}
|
|
304
587
|
} catch {
|
|
305
588
|
// Reader cancelled or stream errored — expected on shutdown
|
|
@@ -308,7 +591,9 @@ export class LocalEmbeddingBackend implements EmbeddingBackend {
|
|
|
308
591
|
}
|
|
309
592
|
|
|
310
593
|
private startStdoutReader(): void {
|
|
311
|
-
if (this.stdoutReaderActive || !this.workerProc)
|
|
594
|
+
if (this.stdoutReaderActive || !this.workerProc) {
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
312
597
|
this.stdoutReaderActive = true;
|
|
313
598
|
|
|
314
599
|
// Capture reference to detect if a new worker was spawned during cleanup
|
|
@@ -320,7 +605,9 @@ export class LocalEmbeddingBackend implements EmbeddingBackend {
|
|
|
320
605
|
try {
|
|
321
606
|
while (true) {
|
|
322
607
|
const { done, value } = await reader.read();
|
|
323
|
-
if (done)
|
|
608
|
+
if (done) {
|
|
609
|
+
break;
|
|
610
|
+
}
|
|
324
611
|
this.stdoutBuffer += decoder.decode(value, { stream: true });
|
|
325
612
|
this.processStdoutBuffer();
|
|
326
613
|
}
|
|
@@ -330,24 +617,162 @@ export class LocalEmbeddingBackend implements EmbeddingBackend {
|
|
|
330
617
|
|
|
331
618
|
// Only clean up if this reader's proc is still the active one.
|
|
332
619
|
// A new worker may have been spawned during the async cleanup window.
|
|
333
|
-
if (this.workerProc
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
620
|
+
if (this.workerProc !== proc) {
|
|
621
|
+
return;
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
// The stream ending does NOT prove the child exited: a read error ends
|
|
625
|
+
// this loop just the same. Releasing ownership of a still-running child
|
|
626
|
+
// strands it: nothing holds its handle any more and, once its PID file
|
|
627
|
+
// entry is gone, no later reclaim can find it, so it lives until reboot
|
|
628
|
+
// holding ~570 MB (JARVIS-1125). Terminate and wait for the OS to confirm
|
|
629
|
+
// before forgetting it.
|
|
630
|
+
const confirmed = await this.terminateWorker(proc);
|
|
631
|
+
|
|
632
|
+
// Re-check: a new worker may have been spawned while we awaited exit.
|
|
633
|
+
if (this.workerProc !== proc) {
|
|
634
|
+
return;
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
for (const [, pending] of this.pendingRequests) {
|
|
638
|
+
pending.resolve({
|
|
639
|
+
error: "Embedding worker process exited unexpectedly",
|
|
640
|
+
});
|
|
641
|
+
}
|
|
642
|
+
this.pendingRequests.clear();
|
|
643
|
+
this.workerProc = null;
|
|
644
|
+
this.stdoutReaderActive = false;
|
|
645
|
+
this.stdoutBuffer = "";
|
|
646
|
+
// Allow re-initialization on next embed() call. When the child was not
|
|
647
|
+
// confirmed dead, ownership and publication are retained instead, and
|
|
648
|
+
// ensureInitialized refuses to spawn beside it.
|
|
649
|
+
this.initGuard.reset();
|
|
650
|
+
if (confirmed) {
|
|
651
|
+
this.releasePidFile(proc.pid);
|
|
652
|
+
} else {
|
|
653
|
+
this.retainUnconfirmedWorker(proc.pid);
|
|
347
654
|
}
|
|
348
655
|
})();
|
|
349
656
|
}
|
|
350
657
|
|
|
658
|
+
/**
|
|
659
|
+
* Terminate a worker and wait for the OS to confirm it is gone, escalating to
|
|
660
|
+
* SIGKILL if it does not go quietly.
|
|
661
|
+
*
|
|
662
|
+
* Every path that gives up ownership of a worker goes through here, so the
|
|
663
|
+
* invariant "we never forget a child we have not confirmed dead" holds even
|
|
664
|
+
* when the trigger was a stream error rather than an exit.
|
|
665
|
+
*
|
|
666
|
+
* The wait is bounded. A worker wedged in native ONNX code can ignore SIGTERM,
|
|
667
|
+
* and an unbounded wait here would hang every in-flight embed and block
|
|
668
|
+
* re-initialization forever, since the caller only resolves pending requests
|
|
669
|
+
* afterwards.
|
|
670
|
+
*
|
|
671
|
+
* Returns whether the child was CONFIRMED gone. A successful `kill` proves
|
|
672
|
+
* signal delivery, not exit, so callers must not treat `false` as disposal:
|
|
673
|
+
* see {@link retainUnconfirmedWorker} for the fail-closed handling.
|
|
674
|
+
*/
|
|
675
|
+
private async terminateWorker(proc: {
|
|
676
|
+
kill: (signal?: number | NodeJS.Signals) => void;
|
|
677
|
+
exited: Promise<unknown>;
|
|
678
|
+
}): Promise<boolean> {
|
|
679
|
+
const settled = proc.exited.catch(() => undefined);
|
|
680
|
+
|
|
681
|
+
try {
|
|
682
|
+
proc.kill();
|
|
683
|
+
} catch {
|
|
684
|
+
// Already exiting or already reaped.
|
|
685
|
+
}
|
|
686
|
+
if (await didSettle(settled, this.terminateGraceMs)) {
|
|
687
|
+
return true;
|
|
688
|
+
}
|
|
689
|
+
|
|
690
|
+
log.warn(
|
|
691
|
+
{ model: this.model },
|
|
692
|
+
"Embedding worker ignored SIGTERM, escalating to SIGKILL",
|
|
693
|
+
);
|
|
694
|
+
try {
|
|
695
|
+
proc.kill("SIGKILL");
|
|
696
|
+
} catch {
|
|
697
|
+
// Already gone.
|
|
698
|
+
}
|
|
699
|
+
return didSettle(settled, this.terminateGraceMs);
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
/**
|
|
703
|
+
* Record a worker that was signalled but never confirmed dead.
|
|
704
|
+
*
|
|
705
|
+
* This is the fail-closed half of the "never forget an unconfirmed child"
|
|
706
|
+
* invariant. The transport is gone either way, so `workerProc` is cleared,
|
|
707
|
+
* but ownership is not: the PID publication is kept and this state blocks
|
|
708
|
+
* {@link ensureInitialized} from spawning a replacement. Otherwise a child
|
|
709
|
+
* that survived SIGKILL (uninterruptible I/O) would run unowned and
|
|
710
|
+
* unpublished beside its replacement, which is the invisible-duplicate class
|
|
711
|
+
* this whole change exists to remove.
|
|
712
|
+
*
|
|
713
|
+
* Self-healing: the block lifts as soon as the process actually disappears,
|
|
714
|
+
* checked on the next initialization attempt.
|
|
715
|
+
*/
|
|
716
|
+
private retainUnconfirmedWorker(pid: number): void {
|
|
717
|
+
this.unconfirmedWorker = pid;
|
|
718
|
+
log.error(
|
|
719
|
+
{ pid, model: this.model },
|
|
720
|
+
"Embedding worker could not be confirmed terminated; retaining ownership and refusing to spawn a replacement",
|
|
721
|
+
);
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
/**
|
|
725
|
+
* Whether a retained worker is still present. Clears the retention when it
|
|
726
|
+
* has finally gone, so the backend recovers without a restart.
|
|
727
|
+
*/
|
|
728
|
+
private unconfirmedWorkerStillAlive(): boolean {
|
|
729
|
+
const pid = this.unconfirmedWorker;
|
|
730
|
+
if (pid == null) {
|
|
731
|
+
return false;
|
|
732
|
+
}
|
|
733
|
+
const stillListed = this.workerPath
|
|
734
|
+
? listWorkerProcesses(this.workerPath, this.model).some(
|
|
735
|
+
(w) => w.pid === pid,
|
|
736
|
+
)
|
|
737
|
+
: isProcessAlive(pid);
|
|
738
|
+
if (!stillListed) {
|
|
739
|
+
log.info(
|
|
740
|
+
{ pid, model: this.model },
|
|
741
|
+
"Previously unconfirmed embedding worker is gone; allowing a replacement",
|
|
742
|
+
);
|
|
743
|
+
this.unconfirmedWorker = null;
|
|
744
|
+
this.releasePidFile(pid);
|
|
745
|
+
}
|
|
746
|
+
return stillListed;
|
|
747
|
+
}
|
|
748
|
+
|
|
749
|
+
/**
|
|
750
|
+
* Wait for a PID that this process does not hold a handle for to disappear.
|
|
751
|
+
*
|
|
752
|
+
* Liveness is probed by re-enumerating workers rather than with `kill(pid, 0)`,
|
|
753
|
+
* which succeeds for a zombie and would stall this wait for the full timeout
|
|
754
|
+
* on every reclaim. A zombie has no command line, so it stops matching
|
|
755
|
+
* `workerPath` as soon as it dies.
|
|
756
|
+
*/
|
|
757
|
+
private async waitForWorkerExit(
|
|
758
|
+
pid: number,
|
|
759
|
+
workerPath: string,
|
|
760
|
+
timeoutMs: number,
|
|
761
|
+
): Promise<boolean> {
|
|
762
|
+
const deadline = Date.now() + timeoutMs;
|
|
763
|
+
while (Date.now() < deadline) {
|
|
764
|
+
if (
|
|
765
|
+
!listWorkerProcesses(workerPath, this.model).some((w) => w.pid === pid)
|
|
766
|
+
) {
|
|
767
|
+
return true;
|
|
768
|
+
}
|
|
769
|
+
await Bun.sleep(WORKER_EXIT_POLL_MS);
|
|
770
|
+
}
|
|
771
|
+
return !listWorkerProcesses(workerPath, this.model).some(
|
|
772
|
+
(w) => w.pid === pid,
|
|
773
|
+
);
|
|
774
|
+
}
|
|
775
|
+
|
|
351
776
|
private readyResolve: (() => void) | null = null;
|
|
352
777
|
private readyReject: ((err: Error) => void) | null = null;
|
|
353
778
|
|
|
@@ -356,7 +781,9 @@ export class LocalEmbeddingBackend implements EmbeddingBackend {
|
|
|
356
781
|
while ((idx = this.stdoutBuffer.indexOf("\n")) !== -1) {
|
|
357
782
|
const line = this.stdoutBuffer.slice(0, idx);
|
|
358
783
|
this.stdoutBuffer = this.stdoutBuffer.slice(idx + 1);
|
|
359
|
-
if (!line.trim())
|
|
784
|
+
if (!line.trim()) {
|
|
785
|
+
continue;
|
|
786
|
+
}
|
|
360
787
|
|
|
361
788
|
let msg: WorkerResponse;
|
|
362
789
|
try {
|
|
@@ -419,17 +846,26 @@ export class LocalEmbeddingBackend implements EmbeddingBackend {
|
|
|
419
846
|
originalReject(err);
|
|
420
847
|
};
|
|
421
848
|
|
|
422
|
-
// Also handle early worker exit
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
849
|
+
// Also handle early worker exit. The `catch` matters: an unhandled
|
|
850
|
+
// rejection here reaches the daemon's fatal-error handler and takes the
|
|
851
|
+
// process down, which is the same failure shape as the EPIPE in
|
|
852
|
+
// `sendRequest` (JARVIS-1125).
|
|
853
|
+
this.workerProc?.exited
|
|
854
|
+
.then(() => {
|
|
855
|
+
if (this.readyResolve) {
|
|
856
|
+
clearTimeout(timeout);
|
|
857
|
+
this.readyResolve = null;
|
|
858
|
+
this.readyReject = null;
|
|
859
|
+
reject(
|
|
860
|
+
new Error(
|
|
861
|
+
"Embedding worker process exited before becoming ready",
|
|
862
|
+
),
|
|
863
|
+
);
|
|
864
|
+
}
|
|
865
|
+
})
|
|
866
|
+
.catch(() => {
|
|
867
|
+
// Exit status unavailable, so the ready timeout is the backstop.
|
|
868
|
+
});
|
|
433
869
|
});
|
|
434
870
|
}
|
|
435
871
|
|
|
@@ -451,7 +887,19 @@ export class LocalEmbeddingBackend implements EmbeddingBackend {
|
|
|
451
887
|
}
|
|
452
888
|
}
|
|
453
889
|
|
|
454
|
-
|
|
890
|
+
/**
|
|
891
|
+
* Drop the PID file, but only while it still names `ownedPid`.
|
|
892
|
+
*
|
|
893
|
+
* The file is a single workspace-scoped slot shared by every backend instance
|
|
894
|
+
* and by the memory-worker process, so an unconditional unlink here deletes
|
|
895
|
+
* whichever worker happens to be published, including a live one belonging
|
|
896
|
+
* to somebody else. Compare-and-delete keeps a teardown from unpublishing a
|
|
897
|
+
* worker it does not own (JARVIS-1125).
|
|
898
|
+
*/
|
|
899
|
+
private releasePidFile(ownedPid: number): void {
|
|
900
|
+
if (this.readPidFile() !== ownedPid) {
|
|
901
|
+
return;
|
|
902
|
+
}
|
|
455
903
|
try {
|
|
456
904
|
unlinkSync(this.getPidFilePath());
|
|
457
905
|
} catch {
|
|
@@ -462,7 +910,9 @@ export class LocalEmbeddingBackend implements EmbeddingBackend {
|
|
|
462
910
|
/** Read the PID from the on-disk PID file, or null if missing/invalid. */
|
|
463
911
|
private readPidFile(): number | null {
|
|
464
912
|
const path = this.getPidFilePath();
|
|
465
|
-
if (!existsSync(path))
|
|
913
|
+
if (!existsSync(path)) {
|
|
914
|
+
return null;
|
|
915
|
+
}
|
|
466
916
|
try {
|
|
467
917
|
const pid = parseInt(readFileSync(path, "utf-8").trim(), 10);
|
|
468
918
|
return Number.isFinite(pid) && pid > 0 ? pid : null;
|
|
@@ -472,118 +922,245 @@ export class LocalEmbeddingBackend implements EmbeddingBackend {
|
|
|
472
922
|
}
|
|
473
923
|
|
|
474
924
|
/**
|
|
475
|
-
*
|
|
476
|
-
*
|
|
477
|
-
* original worker exited and the OS recycled the PID.
|
|
925
|
+
* Terminate every embed worker this process is responsible for, so spawning
|
|
926
|
+
* a replacement cannot leave a duplicate behind.
|
|
478
927
|
*
|
|
479
|
-
*
|
|
480
|
-
*
|
|
481
|
-
* the
|
|
482
|
-
*
|
|
928
|
+
* Responsibility is read off the process tree rather than the PID file. A
|
|
929
|
+
* worker's parent is its owner, which makes ownership survive a crash and
|
|
930
|
+
* immune to a second owner overwriting the shared PID file. Those are the two failure
|
|
931
|
+
* modes behind JARVIS-1125. See {@link classifyWorkerOwnership} for the
|
|
932
|
+
* per-worker decision; this also recovers workers stranded by earlier daemon
|
|
933
|
+
* generations, not just the single entry a PID file can hold.
|
|
483
934
|
*/
|
|
484
|
-
private
|
|
485
|
-
|
|
486
|
-
//
|
|
487
|
-
//
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
if (
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
935
|
+
private async reclaimOwnedWorkers(workerPath: string): Promise<void> {
|
|
936
|
+
for (const worker of listWorkerProcesses(workerPath, this.model)) {
|
|
937
|
+
// Never signal ourselves. This should not happen, since the worker is a
|
|
938
|
+
// child process, but guard against logic bugs that would deadlock us.
|
|
939
|
+
if (worker.pid === process.pid) {
|
|
940
|
+
continue;
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
const ownership = classifyWorkerOwnership(
|
|
944
|
+
worker,
|
|
945
|
+
process.pid,
|
|
946
|
+
isProcessAlive,
|
|
947
|
+
pid1OwnsEmbedWorkers(),
|
|
948
|
+
);
|
|
949
|
+
if (ownership === "foreign") {
|
|
950
|
+
continue;
|
|
951
|
+
}
|
|
952
|
+
|
|
953
|
+
log.warn(
|
|
954
|
+
{ pid: worker.pid, ownerPid: worker.ppid, model: this.model },
|
|
955
|
+
ownership === "reclaim"
|
|
956
|
+
? "Reclaiming an embed worker this process had lost track of"
|
|
957
|
+
: "Terminating an orphaned embed worker from a previous owner",
|
|
958
|
+
);
|
|
959
|
+
try {
|
|
960
|
+
process.kill(worker.pid, "SIGTERM");
|
|
961
|
+
} catch {
|
|
962
|
+
// Race: it exited between enumeration and the kill, which is fine.
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
// Wait for the exit before publishing a replacement. Returning early
|
|
966
|
+
// would leave two same-owner workers briefly alive and would unpublish a
|
|
967
|
+
// child not yet confirmed dead, which are the exact invariants this is
|
|
968
|
+
// meant to hold.
|
|
969
|
+
if (
|
|
970
|
+
!(await this.waitForWorkerExit(
|
|
971
|
+
worker.pid,
|
|
972
|
+
workerPath,
|
|
973
|
+
this.terminateGraceMs,
|
|
974
|
+
))
|
|
975
|
+
) {
|
|
976
|
+
try {
|
|
977
|
+
process.kill(worker.pid, "SIGKILL");
|
|
978
|
+
} catch {
|
|
979
|
+
// Already gone.
|
|
980
|
+
}
|
|
981
|
+
if (
|
|
982
|
+
!(await this.waitForWorkerExit(
|
|
983
|
+
worker.pid,
|
|
984
|
+
workerPath,
|
|
985
|
+
this.terminateGraceMs,
|
|
986
|
+
))
|
|
987
|
+
) {
|
|
988
|
+
// Fail closed. Publishing a replacement now would leave this child
|
|
989
|
+
// running unowned beside it, which is the duplicate-worker class
|
|
990
|
+
// being fixed. Abort the spawn instead and keep the publication.
|
|
991
|
+
this.retainUnconfirmedWorker(worker.pid);
|
|
992
|
+
// Transient, so it must not carry the permanent-failure sentinel
|
|
993
|
+
// (see the note in `ensureInitialized`).
|
|
994
|
+
throw new Error(
|
|
995
|
+
`Local embedding worker ${worker.pid} survived SIGKILL and could not be confirmed terminated`,
|
|
996
|
+
);
|
|
997
|
+
}
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
this.releasePidFile(worker.pid);
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
// A PID file naming a process that is gone (or was never ours) is stale;
|
|
1004
|
+
// drop it so the worker we are about to spawn can publish cleanly.
|
|
1005
|
+
const published = this.readPidFile();
|
|
1006
|
+
if (published != null && !isProcessAlive(published)) {
|
|
1007
|
+
this.releasePidFile(published);
|
|
502
1008
|
}
|
|
503
1009
|
}
|
|
504
1010
|
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
* by a crashed daemon, for example), terminate it before spawning a new one
|
|
508
|
-
* so we never end up with duplicate workers competing for the same workspace.
|
|
509
|
-
*
|
|
510
|
-
* Stale PID files (process no longer exists) are silently cleaned up.
|
|
511
|
-
* PIDs that have been recycled to unrelated processes — including embed
|
|
512
|
-
* workers belonging to *other* assistant instances — are left untouched.
|
|
513
|
-
*/
|
|
514
|
-
private reclaimStaleWorker(workerPath: string): void {
|
|
515
|
-
const pid = this.readPidFile();
|
|
516
|
-
if (pid == null) return;
|
|
517
|
-
|
|
518
|
-
// Never signal ourselves — should not happen since the worker is a child
|
|
519
|
-
// process, but guard against logic bugs that would deadlock the daemon.
|
|
520
|
-
if (pid === process.pid) {
|
|
521
|
-
this.removePidFile();
|
|
1011
|
+
private disposeIfIdle(): void {
|
|
1012
|
+
if (!this.disposeRequested) {
|
|
522
1013
|
return;
|
|
523
1014
|
}
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
try {
|
|
527
|
-
// Signal 0 just probes for liveness without delivering a signal.
|
|
528
|
-
process.kill(pid, 0);
|
|
529
|
-
isAlive = true;
|
|
530
|
-
} catch {
|
|
531
|
-
// ESRCH — no such process. PID file is stale.
|
|
1015
|
+
if (this.activeEmbeds > 0) {
|
|
1016
|
+
return;
|
|
532
1017
|
}
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
"Removing stale embed worker PID file (process no longer exists)",
|
|
538
|
-
);
|
|
539
|
-
this.removePidFile();
|
|
1018
|
+
if (this.pendingRequests.size > 0) {
|
|
1019
|
+
return;
|
|
1020
|
+
}
|
|
1021
|
+
if (this.readyResolve || this.readyReject) {
|
|
540
1022
|
return;
|
|
541
1023
|
}
|
|
542
1024
|
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
1025
|
+
const proc = this.workerProc;
|
|
1026
|
+
this.workerProc = null;
|
|
1027
|
+
this.stdoutReaderActive = false;
|
|
1028
|
+
this.stdoutBuffer = "";
|
|
1029
|
+
this.initGuard.reset();
|
|
1030
|
+
|
|
1031
|
+
// An instance whose worker already exited owns nothing. Unlinking the PID
|
|
1032
|
+
// file here would unpublish whichever worker is currently registered,
|
|
1033
|
+
// typically a live one belonging to another instance, which then becomes
|
|
1034
|
+
// invisible to every later reclaim. Only release what we actually hold.
|
|
1035
|
+
if (!proc) {
|
|
553
1036
|
return;
|
|
554
1037
|
}
|
|
555
1038
|
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
1039
|
+
void this.terminateWorker(proc)
|
|
1040
|
+
.then((confirmed) => {
|
|
1041
|
+
if (confirmed) {
|
|
1042
|
+
this.releasePidFile(proc.pid);
|
|
1043
|
+
} else {
|
|
1044
|
+
this.retainUnconfirmedWorker(proc.pid);
|
|
1045
|
+
}
|
|
1046
|
+
})
|
|
1047
|
+
.catch((err: unknown) => {
|
|
1048
|
+
log.warn({ err, model: this.model }, "Deferred worker teardown failed");
|
|
1049
|
+
});
|
|
1050
|
+
}
|
|
1051
|
+
|
|
1052
|
+
/**
|
|
1053
|
+
* SIGKILL this backend's worker without waiting, for a process that must exit
|
|
1054
|
+
* this tick and cannot afford the graceful path.
|
|
1055
|
+
*
|
|
1056
|
+
* The fail-closed retention that {@link shutdown} uses is meaningless here:
|
|
1057
|
+
* we are about to exit, so there is nobody left to hold ownership for. What
|
|
1058
|
+
* matters is that the child does not outlive us as an orphan the next owner's
|
|
1059
|
+
* single reclaim sweep has already passed by. SIGKILL cannot be caught, so
|
|
1060
|
+
* delivery is disposal.
|
|
1061
|
+
*/
|
|
1062
|
+
terminateNow(): void {
|
|
1063
|
+
const proc = this.workerProc;
|
|
1064
|
+
this.workerProc = null;
|
|
1065
|
+
this.stdoutReaderActive = false;
|
|
1066
|
+
this.stdoutBuffer = "";
|
|
1067
|
+
this.initGuard.reset();
|
|
1068
|
+
|
|
1069
|
+
if (proc) {
|
|
1070
|
+
try {
|
|
1071
|
+
proc.kill("SIGKILL");
|
|
1072
|
+
} catch {
|
|
1073
|
+
// Already gone.
|
|
1074
|
+
}
|
|
1075
|
+
this.releasePidFile(proc.pid);
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
// A worker spawned but not yet adopted (startup still in flight) is not in
|
|
1079
|
+
// `workerProc`, so the handle alone would miss it and it would outlive this
|
|
1080
|
+
// process as an orphan. Parentage finds it; both calls are synchronous, so
|
|
1081
|
+
// this still costs the caller nothing it cannot afford before exiting.
|
|
1082
|
+
if (!this.workerPath) {
|
|
1083
|
+
return;
|
|
1084
|
+
}
|
|
1085
|
+
for (const worker of listWorkerProcesses(this.workerPath, this.model)) {
|
|
1086
|
+
if (worker.ppid !== process.pid || worker.pid === proc?.pid) {
|
|
1087
|
+
continue;
|
|
1088
|
+
}
|
|
1089
|
+
try {
|
|
1090
|
+
process.kill(worker.pid, "SIGKILL");
|
|
1091
|
+
} catch {
|
|
1092
|
+
// Already gone.
|
|
1093
|
+
}
|
|
1094
|
+
this.releasePidFile(worker.pid);
|
|
564
1095
|
}
|
|
565
|
-
this.removePidFile();
|
|
566
1096
|
}
|
|
567
1097
|
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
1098
|
+
/**
|
|
1099
|
+
* Terminate this backend's worker and wait for the child to exit.
|
|
1100
|
+
*
|
|
1101
|
+
* The deterministic counterpart to {@link dispose} for daemon shutdown: it
|
|
1102
|
+
* ignores the idle checks (the process is going away, so deferring until
|
|
1103
|
+
* in-flight embeds settle would just orphan the child) and resolves only once
|
|
1104
|
+
* the OS confirms the worker is gone.
|
|
1105
|
+
*/
|
|
1106
|
+
async shutdown(): Promise<void> {
|
|
1107
|
+
this.disposeRequested = true;
|
|
1108
|
+
|
|
1109
|
+
// An initialization already in flight has not necessarily assigned
|
|
1110
|
+
// `workerProc` yet: it may still be downloading the runtime or waiting for
|
|
1111
|
+
// the model to load. Returning now would sweep the cache and let that
|
|
1112
|
+
// initializer spawn a worker afterwards, with nobody left to reap it. Wait
|
|
1113
|
+
// for it to settle so there is a handle to tear down.
|
|
1114
|
+
// Bounded. `waitForReady` allows two minutes for a cold model load, far
|
|
1115
|
+
// longer than any caller's shutdown budget, so an unbounded wait here would
|
|
1116
|
+
// let the parent's own deadline fire first and orphan the child.
|
|
1117
|
+
const inFlight = this.initInFlight;
|
|
1118
|
+
if (inFlight) {
|
|
1119
|
+
await Promise.race([
|
|
1120
|
+
inFlight.catch(() => undefined),
|
|
1121
|
+
Bun.sleep(this.terminateGraceMs),
|
|
1122
|
+
]);
|
|
1123
|
+
}
|
|
573
1124
|
|
|
574
1125
|
const proc = this.workerProc;
|
|
575
1126
|
this.workerProc = null;
|
|
576
1127
|
this.stdoutReaderActive = false;
|
|
577
1128
|
this.stdoutBuffer = "";
|
|
578
1129
|
this.initGuard.reset();
|
|
579
|
-
this.removePidFile();
|
|
580
1130
|
|
|
581
|
-
|
|
1131
|
+
for (const [, pending] of this.pendingRequests) {
|
|
1132
|
+
pending.resolve({ error: "Local embedding backend is shutting down" });
|
|
1133
|
+
}
|
|
1134
|
+
this.pendingRequests.clear();
|
|
582
1135
|
|
|
1136
|
+
if (!proc) {
|
|
1137
|
+
return;
|
|
1138
|
+
}
|
|
1139
|
+
|
|
1140
|
+
if (await this.terminateWorker(proc)) {
|
|
1141
|
+
this.releasePidFile(proc.pid);
|
|
1142
|
+
return;
|
|
1143
|
+
}
|
|
1144
|
+
// Leave the publication in place: the child may outlive us, and the entry
|
|
1145
|
+
// is what lets the next owner's reclaim sweep find and reap it.
|
|
1146
|
+
this.retainUnconfirmedWorker(proc.pid);
|
|
1147
|
+
}
|
|
1148
|
+
|
|
1149
|
+
/**
|
|
1150
|
+
* Reap any worker still parented to this process.
|
|
1151
|
+
*
|
|
1152
|
+
* Backstop for {@link shutdown}: an initializer that did not settle inside the
|
|
1153
|
+
* bounded wait can still spawn a child afterwards, and that child has no
|
|
1154
|
+
* handle anyone is holding. Ownership by parentage finds it regardless.
|
|
1155
|
+
*/
|
|
1156
|
+
async sweepOwnedWorkers(): Promise<void> {
|
|
1157
|
+
if (!this.workerPath) {
|
|
1158
|
+
return;
|
|
1159
|
+
}
|
|
583
1160
|
try {
|
|
584
|
-
|
|
585
|
-
} catch {
|
|
586
|
-
|
|
1161
|
+
await this.reclaimOwnedWorkers(this.workerPath);
|
|
1162
|
+
} catch (err) {
|
|
1163
|
+
log.warn({ err, model: this.model }, "Owned-worker sweep incomplete");
|
|
587
1164
|
}
|
|
588
1165
|
}
|
|
589
1166
|
}
|