@vellumai/assistant 0.8.0 → 0.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +11 -0
- package/ARCHITECTURE.md +2 -7
- package/Dockerfile +80 -5
- package/README.md +2 -2
- package/bun.lock +11 -1
- package/docker-entrypoint.sh +21 -0
- package/docker-init-apt-root.sh +94 -0
- package/docker-kata-apt-env.sh +39 -0
- package/docs/plugins.md +88 -47
- package/docs/skills.md +9 -7
- package/eslint-rules/__tests__/cli-no-daemon-internals.test.ts +420 -0
- package/eslint-rules/cli-no-daemon-internals.js +283 -0
- package/eslint.config.mjs +12 -0
- package/examples/plugins/echo/README.md +27 -27
- package/examples/plugins/echo/package.json +3 -0
- package/examples/plugins/echo/register.ts +31 -31
- package/knip.json +2 -1
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -1
- package/node_modules/@vellumai/slack-text/src/index.test.ts +114 -14
- package/node_modules/@vellumai/slack-text/src/index.ts +82 -18
- package/openapi.yaml +4462 -991
- package/package.json +5 -1
- package/scripts/generate-openapi.ts +135 -14
- package/scripts/sync-llm-catalog.ts +165 -0
- package/scripts/sync-web-search-catalog.ts +129 -0
- package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +169 -0
- package/src/__tests__/agent-image-optimize.test.ts +11 -3
- package/src/__tests__/agent-loop-override-profile.test.ts +26 -1
- package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +131 -0
- package/src/__tests__/anthropic-provider.test.ts +137 -2
- package/src/__tests__/app-builder-tool-scripts.test.ts +9 -3
- package/src/__tests__/app-control-flow.test.ts +7 -0
- package/src/__tests__/app-executors.test.ts +220 -4
- package/src/__tests__/assistant-events-sse-shed.test.ts +232 -0
- package/src/__tests__/auto-analysis-end-to-end.test.ts +35 -0
- package/src/__tests__/avatar-identity-sync.test.ts +87 -0
- package/src/__tests__/background-workers-disk-pressure.test.ts +11 -22
- package/src/__tests__/btw-routes.test.ts +1 -0
- package/src/__tests__/bundled-asset.test.ts +6 -6
- package/src/__tests__/call-site-routing-provider.test.ts +172 -45
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +44 -3
- package/src/__tests__/channel-availability-routes.test.ts +206 -0
- package/src/__tests__/channel-delivery-store.test.ts +289 -1
- package/src/__tests__/channel-policy.test.ts +12 -0
- package/src/__tests__/checker.test.ts +89 -0
- package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -1
- package/src/__tests__/clawhub.test.ts +75 -16
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +35 -7
- package/src/__tests__/compact-event-conversation-id-guard.test.ts +33 -5
- package/src/__tests__/compaction-strip-metadata-clear.test.ts +26 -1
- package/src/__tests__/compactor-tail-resolution.test.ts +41 -0
- package/src/__tests__/config-loader-backfill.test.ts +526 -102
- package/src/__tests__/config-loader-corrupt.test.ts +68 -0
- package/src/__tests__/config-loader-platform-defaults.test.ts +77 -23
- package/src/__tests__/config-schema-cmd.test.ts +63 -29
- package/src/__tests__/config-schema.test.ts +35 -3
- package/src/__tests__/config-set-platform-guard.test.ts +75 -152
- package/src/__tests__/config-set-route.test.ts +278 -0
- package/src/__tests__/config-sounds-sync.test.ts +97 -0
- package/src/__tests__/config-watcher-skill-reseed.test.ts +453 -0
- package/src/__tests__/config-watcher.test.ts +6 -0
- package/src/__tests__/contacts-tools.test.ts +51 -199
- package/src/__tests__/context-search-agent-protocol.test.ts +21 -2
- package/src/__tests__/context-search-agent-runner.test.ts +22 -138
- package/src/__tests__/context-search-conversations-source.test.ts +159 -18
- package/src/__tests__/context-search-fanout.test.ts +20 -157
- package/src/__tests__/context-search-memory-v2-source.test.ts +3 -4
- package/src/__tests__/context-search-types.test.ts +7 -2
- package/src/__tests__/context-search-workspace-source.test.ts +7 -0
- package/src/__tests__/context-token-estimator.test.ts +1 -0
- package/src/__tests__/conversation-abort-tool-results.test.ts +4 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +93 -92
- package/src/__tests__/conversation-agent-loop.test.ts +2 -0
- package/src/__tests__/conversation-crud-inference-profile.test.ts +100 -0
- package/src/__tests__/conversation-error.test.ts +80 -3
- package/src/__tests__/conversation-fork-crud.test.ts +323 -1
- package/src/__tests__/conversation-inference-profile-route.test.ts +54 -18
- package/src/__tests__/conversation-init.benchmark.test.ts +1 -0
- package/src/__tests__/conversation-lifecycle.test.ts +297 -0
- package/src/__tests__/conversation-message-sync-tags.test.ts +97 -0
- package/src/__tests__/conversation-pairing.test.ts +54 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +100 -1
- package/src/__tests__/conversation-process-callsite.test.ts +25 -2
- package/src/__tests__/conversation-provider-retry-repair.test.ts +5 -1
- package/src/__tests__/conversation-queue.test.ts +4 -1
- package/src/__tests__/conversation-runtime-assembly.test.ts +80 -13
- package/src/__tests__/conversation-slash-commands.test.ts +194 -2
- package/src/__tests__/conversation-slash-queue.test.ts +59 -1
- package/src/__tests__/conversation-slash-unknown.test.ts +4 -1
- package/src/__tests__/conversation-surfaces-app-control.test.ts +323 -3
- package/src/__tests__/conversation-surfaces-table-action.test.ts +360 -0
- package/src/__tests__/conversation-sync-tags.test.ts +235 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
- package/src/__tests__/credential-security-invariants.test.ts +8 -8
- package/src/__tests__/daemon-credential-client.test.ts +56 -1
- package/src/__tests__/db-activation-state-fk-cascade.test.ts +132 -0
- package/src/__tests__/db-conversation-inference-profile-migration.test.ts +37 -0
- package/src/__tests__/db-memory-graph-event-date-repair.test.ts +43 -20
- package/src/__tests__/db-proxy-transaction.test.ts +206 -0
- package/src/__tests__/db-slack-external-content-normalization.test.ts +301 -0
- package/src/__tests__/delete-managed-skill-tool.test.ts +55 -13
- package/src/__tests__/disk-pressure-tools.test.ts +1 -0
- package/src/__tests__/dm-backfill.test.ts +121 -10
- package/src/__tests__/document-tool-security.test.ts +258 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
- package/src/__tests__/edit-propagation.test.ts +33 -0
- package/src/__tests__/empty-response-pipeline.test.ts +0 -4
- package/src/__tests__/external-plugin-loader.test.ts +482 -0
- package/src/__tests__/filing-service.test.ts +163 -3
- package/src/__tests__/fixtures/mock-chrome-extension.ts +5 -0
- package/src/__tests__/gateway-only-guard.test.ts +0 -1
- package/src/__tests__/get-skill-detail-audit.test.ts +0 -4
- package/src/__tests__/graph-extraction-event-date.test.ts +34 -0
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +42 -69
- package/src/__tests__/heartbeat-disk-pressure.test.ts +21 -8
- package/src/__tests__/heartbeat-service.test.ts +50 -233
- package/src/__tests__/helpers/tar-fixtures.ts +39 -0
- package/src/__tests__/helpers/wait-for.ts +21 -0
- package/src/__tests__/history-repair-pipeline.test.ts +0 -3
- package/src/__tests__/history-repair.test.ts +162 -0
- package/src/__tests__/host-app-control-proxy.test.ts +365 -1
- package/src/__tests__/host-app-control-routes.test.ts +247 -1
- package/src/__tests__/host-browser-proxy.test.ts +416 -20
- package/src/__tests__/host-browser-routes.test.ts +325 -33
- package/src/__tests__/host-proxy-preactivation.test.ts +211 -0
- package/src/__tests__/image-credentials.test.ts +1 -1
- package/src/__tests__/inbound-slack-persistence.test.ts +2 -0
- package/src/__tests__/inference-no-mode-boot-e2e.test.ts +246 -0
- package/src/__tests__/inference-profile-reaper.test.ts +156 -0
- package/src/__tests__/inference-profile-session-handler.test.ts +410 -0
- package/src/__tests__/inference-profile-session-ipc.test.ts +248 -0
- package/src/__tests__/injector-chain.test.ts +10 -8
- package/src/__tests__/inline-skill-load-permissions.test.ts +6 -1
- package/src/__tests__/install-skill-routing.test.ts +157 -39
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +107 -3
- package/src/__tests__/list-messages-page-latest.test.ts +55 -0
- package/src/__tests__/llm-call-pipeline.test.ts +0 -3
- package/src/__tests__/llm-callsite-catalog.test.ts +20 -1
- package/src/__tests__/llm-catalog-parity.test.ts +190 -2
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +222 -0
- package/src/__tests__/llm-request-log-source-factory.test.ts +100 -0
- package/src/__tests__/llm-resolver.test.ts +46 -0
- package/src/__tests__/llm-usage-store.test.ts +114 -0
- package/src/__tests__/managed-profile-guard.test.ts +145 -14
- package/src/__tests__/managed-skill-lifecycle.test.ts +109 -18
- package/src/__tests__/managed-store.test.ts +84 -192
- package/src/__tests__/mcp-auth-routes.test.ts +1 -0
- package/src/__tests__/mcp-cli.test.ts +182 -220
- package/src/__tests__/mcp-health-check.test.ts +56 -27
- package/src/__tests__/media-generate-image.test.ts +1 -1
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +18 -11
- package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -2
- package/src/__tests__/message-complete-display-id.test.ts +175 -0
- package/src/__tests__/messages-after-tiebreaker.test.ts +122 -0
- package/src/__tests__/notification-platform-adapter.test.ts +229 -0
- package/src/__tests__/oauth-cli.test.ts +38 -2009
- package/src/__tests__/oauth-commands-routes.test.ts +863 -0
- package/src/__tests__/oauth-connect-routes.test.ts +174 -11
- package/src/__tests__/oauth-provider-profiles.test.ts +9 -0
- package/src/__tests__/oauth-providers-routes.test.ts +14 -10
- package/src/__tests__/openai-provider.test.ts +24 -0
- package/src/__tests__/openai-responses-cutover-guard.test.ts +48 -19
- package/src/__tests__/openai-responses-provider.test.ts +17 -0
- package/src/__tests__/overflow-reduce-pipeline.test.ts +0 -2
- package/src/__tests__/persistence-pipeline.test.ts +0 -2
- package/src/__tests__/{managed-proxy-context.test.ts → platform-proxy-context.test.ts} +1 -1
- package/src/__tests__/platform.test.ts +2 -0
- package/src/__tests__/plugin-api-shim.test.ts +125 -0
- package/src/__tests__/plugin-bootstrap.test.ts +41 -38
- package/src/__tests__/plugin-external-api.test.ts +68 -0
- package/src/__tests__/plugin-registry.test.ts +0 -77
- package/src/__tests__/plugin-route-contribution.test.ts +31 -4
- package/src/__tests__/plugin-skill-contribution.test.ts +0 -2
- package/src/__tests__/plugin-tool-contribution.test.ts +47 -18
- package/src/__tests__/plugin-types.test.ts +15 -23
- package/src/__tests__/process-message-background-slack.test.ts +53 -0
- package/src/__tests__/process-message-display-content.test.ts +421 -0
- package/src/__tests__/profile-entry-status.test.ts +43 -0
- package/src/__tests__/provider-catalog-visibility.test.ts +142 -0
- package/src/__tests__/provider-error-scenarios.test.ts +111 -0
- package/src/__tests__/{provider-managed-proxy-integration.test.ts → provider-platform-proxy-integration.test.ts} +20 -12
- package/src/__tests__/provider-registry-ollama.test.ts +12 -4
- package/src/__tests__/provider-send-message-override-profile.test.ts +10 -4
- package/src/__tests__/relay-server.test.ts +118 -0
- package/src/__tests__/retry-thinking-tool-choice.test.ts +15 -0
- package/src/__tests__/scaffold-managed-skill-tool.test.ts +65 -13
- package/src/__tests__/schedule-retry.test.ts +56 -4
- package/src/__tests__/schedule-routes.test.ts +151 -0
- package/src/__tests__/schedule-store.test.ts +94 -0
- package/src/__tests__/scheduler-disk-pressure.test.ts +0 -4
- package/src/__tests__/scheduler-recurrence.test.ts +87 -34
- package/src/__tests__/scheduler-reuse-conversation.test.ts +208 -5
- package/src/__tests__/scheduler-wake.test.ts +0 -63
- package/src/__tests__/schema-transforms.test.ts +20 -0
- package/src/__tests__/search-skills-unified.test.ts +0 -5
- package/src/__tests__/secret-allowlist.test.ts +1 -0
- package/src/__tests__/{secret-routes-managed-proxy.test.ts → secret-routes-platform-proxy.test.ts} +12 -4
- package/src/__tests__/server-history-render.test.ts +43 -0
- package/src/__tests__/shell-credential-ref.test.ts +95 -3
- package/src/__tests__/shell-tool-proxy-mode.test.ts +14 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +1 -12
- package/src/__tests__/skill-load-tool.test.ts +29 -93
- package/src/__tests__/skill-memory.test.ts +23 -3
- package/src/__tests__/skills-file-content-endpoint.test.ts +9 -38
- package/src/__tests__/skills-files-catalog-fallback.test.ts +0 -3
- package/src/__tests__/skills-install-extract.test.ts +49 -38
- package/src/__tests__/skills-install-staging.test.ts +159 -0
- package/src/__tests__/skills-uninstall.test.ts +9 -41
- package/src/__tests__/skills.test.ts +51 -58
- package/src/__tests__/slack-channel-config.test.ts +9 -0
- package/src/__tests__/subagent-call-site-routing.test.ts +78 -16
- package/src/__tests__/subagent-tool-filtering.test.ts +50 -0
- package/src/__tests__/suggestion-routes.test.ts +3 -3
- package/src/__tests__/sync-message-contract.test.ts +63 -0
- package/src/__tests__/system-prompt.test.ts +737 -63
- package/src/__tests__/task-scheduler.test.ts +88 -23
- package/src/__tests__/terminal-tools.test.ts +28 -1
- package/src/__tests__/thread-backfill.test.ts +557 -27
- package/src/__tests__/title-generate-pipeline.test.ts +0 -13
- package/src/__tests__/token-estimate-pipeline.test.ts +0 -3
- package/src/__tests__/tool-error-pipeline.test.ts +0 -3
- package/src/__tests__/tool-execute-pipeline.test.ts +0 -5
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
- package/src/__tests__/tool-executor.test.ts +16 -4
- package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -12
- package/src/__tests__/turn-events-store.test.ts +256 -0
- package/src/__tests__/twilio-routes.test.ts +4 -0
- package/src/__tests__/update-bulletin-job.test.ts +96 -193
- package/src/__tests__/usage-cli.test.ts +11 -73
- package/src/__tests__/user-plugin-loader.test.ts +143 -5
- package/src/__tests__/vercel-config.test.ts +168 -0
- package/src/__tests__/voice-session-bridge.test.ts +198 -0
- package/src/__tests__/web-search-catalog-parity.test.ts +108 -0
- package/src/__tests__/web-search.test.ts +303 -2
- package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +1 -21
- package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +170 -0
- package/src/__tests__/workspace-migration-069-seed-onboarding-threads.test.ts +53 -20
- package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +241 -0
- package/src/__tests__/workspace-migration-073-repair-recall-callsite-empty-profile.test.ts +153 -0
- package/src/__tests__/workspace-migration-076-drop-services-inference-mode.test.ts +211 -0
- package/src/__tests__/workspace-migration-077-seed-memory-router-callsite.test.ts +174 -0
- package/src/__tests__/workspace-migration-079-home-feed-notification-only.test.ts +323 -0
- package/src/__tests__/workspace-migration-080-restrict-vercel-api-token-metadata.test.ts +299 -0
- package/src/__tests__/workspace-migration-081-backfill-bash-allowed-tools.test.ts +410 -0
- package/src/__tests__/workspace-migration-082-backfill-managed-profile-labels.test.ts +268 -0
- package/src/__tests__/workspace-migration-085-memory-v2-bm25-b-reembed-disabled-v2-pages.test.ts +220 -0
- package/src/__tests__/workspace-migration-086-revert-stale-gemini-mis-rewrites.test.ts +269 -0
- package/src/__tests__/workspace-migration-remove-legacy-skills-index.test.ts +309 -0
- package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +3 -3
- package/src/__tests__/workspace-migrations-runner.test.ts +111 -3
- package/src/__tests__/workspace-release-notes-feature-flag-guard.test.ts +115 -0
- package/src/acp/__tests__/helpers/which-stub.ts +4 -2
- package/src/acp/resolve-agent.test.ts +25 -0
- package/src/acp/resolve-agent.ts +13 -2
- package/src/acp/session-manager.ts +14 -0
- package/src/agent/image-optimize.ts +13 -5
- package/src/approvals/guardian-request-resolvers.ts +32 -87
- package/src/calls/relay-server.ts +35 -0
- package/src/calls/relay-setup-router.ts +36 -0
- package/src/calls/types.ts +1 -0
- package/src/calls/voice-session-bridge.ts +74 -36
- package/src/channels/config.ts +14 -1
- package/src/channels/types.ts +109 -0
- package/src/cli/AGENTS.md +164 -4
- package/src/cli/__tests__/notifications.test.ts +54 -0
- package/src/cli/__tests__/unknown-command.test.ts +24 -0
- package/src/cli/commands/__tests__/avatar.test.ts +540 -0
- package/src/cli/commands/__tests__/backup.test.ts +236 -776
- package/src/cli/commands/__tests__/cache.test.ts +1 -1
- package/src/cli/commands/__tests__/changelog.test.ts +578 -0
- package/src/cli/commands/__tests__/channel-verification-sessions.test.ts +503 -0
- package/src/cli/commands/__tests__/conversations-import.test.ts +515 -0
- package/src/cli/commands/__tests__/domain-register.test.ts +140 -167
- package/src/cli/commands/__tests__/domain-status.test.ts +137 -76
- package/src/cli/commands/__tests__/email-attachment.test.ts +314 -337
- package/src/cli/commands/__tests__/email-core.test.ts +579 -0
- package/src/cli/commands/__tests__/image-generation.test.ts +87 -824
- package/src/cli/commands/__tests__/inference-send.test.ts +30 -266
- package/src/cli/commands/__tests__/inference-session.test.ts +423 -0
- package/src/cli/commands/__tests__/memory-v2.test.ts +81 -110
- package/src/cli/commands/__tests__/schedules.test.ts +491 -0
- package/src/cli/commands/__tests__/skills.test.ts +563 -0
- package/src/cli/commands/__tests__/status.test.ts +249 -0
- package/src/cli/commands/__tests__/stt.test.ts +320 -0
- package/src/cli/commands/__tests__/tts-synthesize.test.ts +4 -603
- package/src/cli/commands/__tests__/tts.test.ts +321 -0
- package/src/cli/commands/__tests__/webhooks.test.ts +86 -511
- package/src/cli/commands/attachment.ts +8 -3
- package/src/cli/commands/audit.ts +95 -64
- package/src/cli/commands/auth.ts +61 -58
- package/src/cli/commands/avatar.ts +276 -390
- package/src/cli/commands/backup.ts +409 -505
- package/src/cli/commands/bash.ts +9 -5
- package/src/cli/commands/browser.ts +28 -9
- package/src/cli/commands/cache.ts +9 -4
- package/src/cli/commands/changelog.ts +478 -0
- package/src/cli/commands/channel-verification-sessions.ts +238 -317
- package/src/cli/commands/clients.ts +8 -3
- package/src/cli/commands/completions.ts +9 -9
- package/src/cli/commands/config.ts +102 -72
- package/src/cli/commands/contacts.ts +575 -696
- package/src/cli/commands/conversations-defer.ts +17 -69
- package/src/cli/commands/conversations-import.ts +90 -253
- package/src/cli/commands/conversations.ts +429 -434
- package/src/cli/commands/credential-execution.ts +9 -6
- package/src/cli/commands/credentials.ts +456 -736
- package/src/cli/commands/default-action.ts +10 -53
- package/src/cli/commands/domain.ts +128 -206
- package/src/cli/commands/email.ts +606 -794
- package/src/cli/commands/gateway.ts +8 -1
- package/src/cli/commands/image-generation.ts +157 -205
- package/src/cli/commands/inference-providers.ts +352 -0
- package/src/cli/commands/inference-session.ts +415 -0
- package/src/cli/commands/inference.ts +87 -65
- package/src/cli/commands/keys.ts +8 -3
- package/src/cli/commands/mcp.ts +103 -287
- package/src/cli/commands/memory-v2.ts +162 -516
- package/src/cli/commands/notifications.ts +342 -304
- package/src/cli/commands/oauth/apps.ts +292 -261
- package/src/cli/commands/oauth/connect.ts +176 -297
- package/src/cli/commands/oauth/disconnect.ts +16 -215
- package/src/cli/commands/oauth/index.ts +49 -45
- package/src/cli/commands/oauth/mode.ts +43 -199
- package/src/cli/commands/oauth/ping.ts +17 -125
- package/src/cli/commands/oauth/providers.ts +732 -921
- package/src/cli/commands/oauth/request.ts +60 -350
- package/src/cli/commands/oauth/shared.ts +11 -121
- package/src/cli/commands/oauth/status.ts +31 -121
- package/src/cli/commands/oauth/token.ts +13 -55
- package/src/cli/commands/pending.ts +19 -10
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +133 -183
- package/src/cli/commands/platform/__tests__/connect.test.ts +66 -181
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +71 -227
- package/src/cli/commands/platform/__tests__/status.test.ts +169 -287
- package/src/cli/commands/platform/connect.ts +16 -80
- package/src/cli/commands/platform/disconnect.ts +14 -112
- package/src/cli/commands/platform/index.ts +177 -246
- package/src/cli/commands/plugins.ts +185 -0
- package/src/cli/commands/routes.ts +153 -336
- package/src/cli/commands/schedules.ts +391 -0
- package/src/cli/commands/sequence.ts +316 -360
- package/src/cli/commands/skills.ts +449 -671
- package/src/cli/commands/status.ts +58 -37
- package/src/cli/commands/stt.ts +94 -262
- package/src/cli/commands/task.ts +14 -40
- package/src/cli/commands/telemetry.ts +40 -0
- package/src/cli/commands/trust.ts +8 -3
- package/src/cli/commands/tts.ts +162 -167
- package/src/cli/commands/ui.ts +35 -42
- package/src/cli/commands/usage.ts +188 -126
- package/src/cli/commands/watchers.ts +8 -3
- package/src/cli/commands/webhooks.ts +99 -193
- package/src/cli/lib/__tests__/cli-colors.test.ts +48 -0
- package/src/cli/lib/__tests__/confirm-prompt.test.ts +159 -0
- package/src/cli/lib/__tests__/install-from-github.test.ts +355 -0
- package/src/cli/lib/__tests__/list-installed-plugins.test.ts +154 -0
- package/src/cli/lib/__tests__/register-command.test.ts +85 -0
- package/src/cli/lib/__tests__/uninstall-plugin.test.ts +124 -0
- package/src/cli/lib/__tests__/unknown-command.test.ts +106 -0
- package/src/cli/lib/cli-colors.ts +12 -0
- package/src/cli/lib/confirm-prompt.ts +79 -0
- package/src/cli/lib/daemon-credential-client.ts +4 -5
- package/src/cli/lib/install-from-github.ts +304 -0
- package/src/cli/lib/list-installed-plugins.ts +137 -0
- package/src/cli/lib/nested-value.ts +44 -0
- package/src/cli/lib/open-browser.ts +36 -0
- package/src/cli/lib/register-command.ts +19 -0
- package/src/cli/lib/time-ago.ts +34 -0
- package/src/cli/lib/uninstall-plugin.ts +82 -0
- package/src/cli/lib/unknown-command.ts +111 -0
- package/src/cli/program.ts +40 -6
- package/src/cli/utils/__tests__/conversation-id.test.ts +66 -0
- package/src/cli/utils/__tests__/parse-duration.test.ts +49 -0
- package/src/cli/utils/conversation-id.ts +30 -0
- package/src/cli/utils/parse-duration.ts +41 -0
- package/src/config/acp-defaults.test.ts +5 -1
- package/src/config/acp-defaults.ts +11 -4
- package/src/config/bundled-skills/acp/TOOLS.json +2 -2
- package/src/config/bundled-skills/app-builder/SKILL.md +23 -21
- package/src/config/bundled-skills/app-builder/TOOLS.json +7 -0
- package/src/config/bundled-skills/app-control/TOOLS.json +32 -0
- package/src/config/bundled-skills/computer-use/TOOLS.json +15 -52
- package/src/config/bundled-skills/contacts/SKILL.md +12 -45
- package/src/config/bundled-skills/contacts/TOOLS.json +0 -57
- package/src/config/bundled-skills/document/SKILL.md +23 -3
- package/src/config/bundled-skills/document/TOOLS.json +53 -0
- package/src/config/bundled-skills/document/tools/document-delete.ts +12 -0
- package/src/config/bundled-skills/document/tools/document-list.ts +12 -0
- package/src/config/bundled-skills/document/tools/document-read.ts +12 -0
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +0 -12
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +0 -58
- package/src/config/bundled-skills/skill-management/SKILL.md +2 -2
- package/src/config/bundled-skills/skill-management/TOOLS.json +7 -7
- package/src/config/bundled-tool-registry.ts +6 -2
- package/src/config/feature-flag-registry.json +57 -1
- package/src/config/llm-resolver.ts +16 -1
- package/src/config/loader.ts +140 -52
- package/src/config/raw-config-utils.ts +2 -30
- package/src/config/schema.ts +8 -7
- package/src/config/schemas/__tests__/llm-request-logs.test.ts +36 -0
- package/src/config/schemas/__tests__/memory-v2.test.ts +49 -0
- package/src/config/schemas/call-site-catalog.ts +29 -7
- package/src/config/schemas/channels.ts +8 -0
- package/src/config/schemas/compaction.ts +28 -0
- package/src/config/schemas/heartbeat.ts +9 -0
- package/src/config/schemas/llm-request-logs.ts +81 -0
- package/src/config/schemas/llm.ts +55 -2
- package/src/config/schemas/memory-retrieval.ts +18 -0
- package/src/config/schemas/memory-retrospective.ts +48 -0
- package/src/config/schemas/memory-v2.ts +32 -1
- package/src/config/schemas/memory.ts +4 -0
- package/src/config/schemas/services.ts +15 -12
- package/src/config/schemas/tools.ts +14 -0
- package/src/config/seed-inference-profiles.ts +195 -134
- package/src/config/skills.ts +3 -96
- package/src/contacts/contact-store.ts +0 -61
- package/src/context/compactor.ts +1047 -0
- package/src/context/token-estimator.ts +2 -2
- package/src/context/window-manager.ts +197 -1334
- package/src/credential-execution/managed-catalog.ts +37 -0
- package/src/credential-health/credential-health-service.ts +280 -19
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +113 -0
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +138 -0
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +183 -4
- package/src/daemon/__tests__/daemon-skill-host.test.ts +10 -4
- package/src/daemon/approval-generators.ts +26 -30
- package/src/daemon/config-watcher.ts +94 -29
- package/src/daemon/conversation-agent-loop-handlers.ts +24 -0
- package/src/daemon/conversation-agent-loop.ts +293 -103
- package/src/daemon/conversation-error.ts +188 -33
- package/src/daemon/conversation-lifecycle.ts +80 -26
- package/src/daemon/conversation-messaging.ts +25 -6
- package/src/daemon/conversation-process.ts +85 -31
- package/src/daemon/conversation-runtime-assembly.ts +30 -6
- package/src/daemon/conversation-slash.ts +184 -25
- package/src/daemon/conversation-store.ts +24 -10
- package/src/daemon/conversation-surfaces.ts +76 -12
- package/src/daemon/conversation-tool-setup.ts +63 -21
- package/src/daemon/conversation.ts +81 -10
- package/src/daemon/external-plugins-bootstrap.ts +231 -185
- package/src/daemon/first-greeting.ts +22 -2
- package/src/daemon/guardian-action-generators.ts +7 -22
- package/src/daemon/handlers/config-model.ts +13 -130
- package/src/daemon/handlers/config-slack-channel.ts +25 -10
- package/src/daemon/handlers/config-vercel.ts +3 -1
- package/src/daemon/handlers/shared.ts +14 -5
- package/src/daemon/handlers/skills.ts +166 -84
- package/src/daemon/history-repair.ts +61 -7
- package/src/daemon/host-app-control-proxy.ts +129 -29
- package/src/daemon/host-bash-proxy.ts +85 -158
- package/src/daemon/host-browser-proxy.ts +96 -35
- package/src/daemon/host-proxy-base.ts +13 -1
- package/src/daemon/host-proxy-preactivation.ts +25 -1
- package/src/daemon/identity-helpers.ts +19 -0
- package/src/daemon/lifecycle.ts +79 -70
- package/src/daemon/meet-host-supervisor.ts +20 -19
- package/src/daemon/memory-v2-startup.ts +58 -2
- package/src/daemon/message-protocol.ts +7 -0
- package/src/daemon/message-types/bookmarks.ts +18 -0
- package/src/daemon/message-types/conversations.ts +37 -9
- package/src/daemon/message-types/messages.ts +70 -1
- package/src/daemon/message-types/subagents.ts +1 -0
- package/src/daemon/message-types/sync.ts +61 -0
- package/src/daemon/pkb-reminder-builder.test.ts +54 -13
- package/src/daemon/pkb-reminder-builder.ts +21 -7
- package/src/daemon/plugin-source-watcher.ts +146 -0
- package/src/daemon/process-message.ts +77 -26
- package/src/daemon/server.ts +34 -20
- package/src/daemon/shutdown-handlers.ts +0 -2
- package/src/daemon/skill-memory-refresh.ts +29 -0
- package/src/daemon/tool-setup-types.ts +9 -0
- package/src/daemon/tool-side-effects.ts +6 -4
- package/src/daemon/wake-target-adapter.ts +11 -0
- package/src/documents/document-store.ts +221 -3
- package/src/embedded/plugin-api.ts +40 -0
- package/src/export/transcript-formatter.ts +61 -2
- package/src/filing/filing-service.ts +79 -53
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +444 -0
- package/src/heartbeat/heartbeat-run-store.ts +3 -1
- package/src/heartbeat/heartbeat-service.ts +189 -127
- package/src/home/__tests__/feed-types.test.ts +99 -127
- package/src/home/__tests__/feed-writer.test.ts +77 -278
- package/src/home/__tests__/post-connect-feed.test.ts +9 -12
- package/src/home/feed-types.ts +41 -73
- package/src/home/feed-writer.ts +25 -156
- package/src/home/post-connect-feed.ts +2 -3
- package/src/index.ts +18 -1
- package/src/ipc/__tests__/cli-ipc.test.ts +2 -0
- package/src/ipc/__tests__/email-ipc.test.ts +506 -0
- package/src/ipc/__tests__/exit-helper.test.ts +104 -0
- package/src/ipc/__tests__/streaming-client.test.ts +237 -0
- package/src/ipc/__tests__/streaming-framing.test.ts +142 -0
- package/src/ipc/assistant-server.ts +55 -6
- package/src/ipc/cli-client.ts +370 -50
- package/src/ipc/routes/db-proxy-transaction.ts +151 -0
- package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +60 -0
- package/src/ipc/skill-routes/events.ts +30 -3
- package/src/live-voice/__tests__/live-voice-session-manager.test.ts +46 -0
- package/src/live-voice/__tests__/live-voice-stt.test.ts +57 -0
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +1 -0
- package/src/live-voice/live-voice-session-manager.ts +11 -4
- package/src/live-voice/live-voice-session.ts +14 -6
- package/src/mcp/client.ts +20 -4
- package/src/media/image-credentials.ts +3 -3
- package/src/memory/__tests__/bookmark-crud.test.ts +264 -0
- package/src/memory/__tests__/bookmark-schema.test.ts +181 -0
- package/src/memory/__tests__/conversation-queries.test.ts +263 -0
- package/src/memory/__tests__/conversation-types.test.ts +36 -0
- package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +130 -0
- package/src/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +113 -0
- package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +177 -0
- package/src/memory/__tests__/memory-retrospective-job.test.ts +328 -0
- package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +318 -0
- package/src/memory/__tests__/memory-retrospective-trigger-check.test.ts +90 -0
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +69 -0
- package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -0
- package/src/memory/__tests__/message-content.test.ts +35 -0
- package/src/memory/bookmark-crud.ts +211 -0
- package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +31 -9
- package/src/memory/context-search/agent-protocol.ts +5 -1
- package/src/memory/context-search/agent-runner.ts +60 -85
- package/src/memory/context-search/limits.ts +1 -4
- package/src/memory/context-search/search.ts +23 -113
- package/src/memory/context-search/sources/conversations.ts +80 -8
- package/src/memory/context-search/sources/memory-v2.ts +39 -14
- package/src/memory/context-search/sources/memory.ts +7 -0
- package/src/memory/context-search/sources/workspace.ts +17 -10
- package/src/memory/context-search/types.ts +1 -1
- package/src/memory/conversation-bootstrap.ts +11 -0
- package/src/memory/conversation-crud.ts +368 -22
- package/src/memory/conversation-queries.ts +116 -12
- package/src/memory/conversation-title-service.ts +1 -0
- package/src/memory/conversation-types.ts +16 -0
- package/src/memory/db-init.ts +20 -0
- package/src/memory/delivery-crud.ts +152 -5
- package/src/memory/embedding-backend.ts +6 -5
- package/src/memory/embedding-runtime-manager.ts +1 -2
- package/src/memory/external-conversation-store.ts +66 -5
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +66 -9
- package/src/memory/graph/__tests__/remember-description.test.ts +55 -0
- package/src/memory/graph/conversation-graph-memory.ts +92 -5
- package/src/memory/graph/extraction.ts +4 -0
- package/src/memory/graph/graph-memory-state-store.ts +16 -3
- package/src/memory/graph/tool-handlers.ts +17 -7
- package/src/memory/graph/tools.ts +45 -6
- package/src/memory/indexer.ts +51 -29
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +86 -15
- package/src/memory/jobs/embed-concept-page.ts +65 -20
- package/src/memory/jobs-store.ts +51 -1
- package/src/memory/jobs-worker.ts +57 -3
- package/src/memory/llm-request-log-source-clickhouse.ts +324 -0
- package/src/memory/llm-request-log-source-local.ts +26 -0
- package/src/memory/llm-request-log-source.ts +64 -0
- package/src/memory/llm-request-log-store.ts +1 -1
- package/src/memory/llm-usage-store.ts +125 -5
- package/src/memory/memory-retrospective-constants.ts +13 -0
- package/src/memory/memory-retrospective-enqueue.ts +114 -0
- package/src/memory/memory-retrospective-job.ts +351 -0
- package/src/memory/memory-retrospective-startup-cleanup.ts +175 -0
- package/src/memory/memory-retrospective-state.ts +162 -0
- package/src/memory/memory-retrospective-trigger-check.ts +91 -0
- package/src/memory/memory-v2-activation-log-store.ts +49 -5
- package/src/memory/memory-v2-concept-frequency.ts +4 -0
- package/src/memory/message-content.ts +38 -1
- package/src/memory/migrations/109-external-conversation-bindings.ts +15 -4
- package/src/memory/migrations/227-add-conversation-inference-profile.ts +6 -1
- package/src/memory/migrations/228-rename-inference-profile-snake-case.ts +20 -7
- package/src/memory/migrations/229-delete-private-conversations.test.ts +107 -1
- package/src/memory/migrations/229-delete-private-conversations.ts +19 -0
- package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +16 -2
- package/src/memory/migrations/240-conversation-inference-profile-session.ts +25 -0
- package/src/memory/migrations/241-activation-state-fk-cascade.ts +50 -0
- package/src/memory/migrations/242-message-bookmarks.ts +38 -0
- package/src/memory/migrations/243-provider-connections.ts +68 -0
- package/src/memory/migrations/244-provider-connection-status-label.ts +23 -0
- package/src/memory/migrations/245-memory-retrospective-state.ts +36 -0
- package/src/memory/migrations/246-backfill-provider-connection-label.ts +81 -0
- package/src/memory/migrations/247-external-conversation-binding-thread-id.ts +78 -0
- package/src/memory/migrations/248-create-onboarding-events.ts +21 -0
- package/src/memory/migrations/249-normalize-slack-external-content.ts +240 -0
- package/src/memory/migrations/__tests__/244-provider-connection-status-label.test.ts +84 -0
- package/src/memory/migrations/__tests__/245-memory-retrospective-state.test.ts +125 -0
- package/src/memory/migrations/__tests__/246-backfill-provider-connection-label.test.ts +192 -0
- package/src/memory/migrations/index.ts +13 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/onboarding-events-store.ts +106 -0
- package/src/memory/published-pages-store.ts +16 -0
- package/src/memory/schema/bookmarks.ts +36 -0
- package/src/memory/schema/calls.ts +1 -0
- package/src/memory/schema/conversations.ts +2 -0
- package/src/memory/schema/index.ts +2 -0
- package/src/memory/schema/inference.ts +27 -0
- package/src/memory/schema/infrastructure.ts +12 -0
- package/src/memory/schema/memory-core.ts +9 -0
- package/src/memory/search/semantic.ts +1 -4
- package/src/memory/turn-events-store.ts +127 -2
- package/src/memory/v2/__tests__/__snapshots__/prompts-router.test.ts.snap +27 -0
- package/src/memory/v2/__tests__/activation-store.test.ts +5 -5
- package/src/memory/v2/__tests__/activation.test.ts +11 -12
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +38 -21
- package/src/memory/v2/__tests__/consolidation-job.test.ts +123 -135
- package/src/memory/v2/__tests__/edge-index.test.ts +1 -1
- package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +111 -0
- package/src/memory/v2/__tests__/injection.test.ts +726 -18
- package/src/memory/v2/__tests__/migration.test.ts +94 -3
- package/src/memory/v2/__tests__/page-index.test.ts +360 -0
- package/src/memory/v2/__tests__/page-store.test.ts +14 -1
- package/src/memory/v2/__tests__/prompts-router.test.ts +309 -0
- package/src/memory/v2/__tests__/qdrant.test.ts +138 -3
- package/src/memory/v2/__tests__/reranker.test.ts +4 -4
- package/src/memory/v2/__tests__/router.test.ts +531 -0
- package/src/memory/v2/__tests__/sim.test.ts +45 -1
- package/src/memory/v2/__tests__/skill-store.test.ts +445 -11
- package/src/memory/v2/__tests__/static-context.test.ts +7 -22
- package/src/memory/v2/__tests__/sweep-job.test.ts +95 -0
- package/src/memory/v2/activation-store.ts +34 -5
- package/src/memory/v2/activation.ts +40 -27
- package/src/memory/v2/backfill-jobs.ts +17 -84
- package/src/memory/v2/consolidation-job.ts +85 -78
- package/src/memory/v2/frontmatter-sweep.ts +91 -0
- package/src/memory/v2/injection.ts +466 -109
- package/src/memory/v2/migration.ts +147 -20
- package/src/memory/v2/page-index.ts +221 -0
- package/src/memory/v2/page-store.ts +3 -0
- package/src/memory/v2/prompts/consolidation.ts +9 -7
- package/src/memory/v2/prompts/router.ts +195 -0
- package/src/memory/v2/prompts/sweep.ts +2 -2
- package/src/memory/v2/qdrant.ts +234 -93
- package/src/memory/v2/reranker.ts +14 -7
- package/src/memory/v2/router.ts +323 -0
- package/src/memory/v2/sim.ts +25 -12
- package/src/memory/v2/skill-store.ts +204 -30
- package/src/memory/v2/static-context.ts +16 -9
- package/src/memory/v2/sweep-job.ts +122 -96
- package/src/memory/v2/types.ts +10 -6
- package/src/memory/validation.ts +13 -0
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +45 -5
- package/src/messaging/providers/slack/__tests__/download.test.ts +231 -0
- package/src/messaging/providers/slack/adapter.ts +43 -5
- package/src/messaging/providers/slack/client.ts +27 -0
- package/src/messaging/providers/slack/deep-link.ts +65 -0
- package/src/messaging/providers/slack/download.ts +104 -0
- package/src/messaging/providers/slack/message-metadata.test.ts +32 -0
- package/src/messaging/providers/slack/message-metadata.ts +27 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +134 -0
- package/src/messaging/providers/slack/render-transcript.ts +69 -5
- package/src/messaging/providers/slack/types.ts +20 -1
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +182 -0
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +199 -0
- package/src/notifications/__tests__/signal-registry.test.ts +17 -0
- package/src/notifications/adapters/platform.ts +171 -0
- package/src/notifications/conversation-pairing.ts +4 -3
- package/src/notifications/copy-composer.ts +15 -0
- package/src/notifications/decision-engine.ts +2 -1
- package/src/notifications/destination-resolver.ts +21 -0
- package/src/notifications/emit-signal.ts +48 -2
- package/src/notifications/home-feed-side-effect.ts +165 -0
- package/src/notifications/signal.ts +8 -1
- package/src/oauth/connection-resolver.ts +8 -4
- package/src/oauth/platform-connection.ts +6 -2
- package/src/oauth/seed-providers.ts +10 -1
- package/src/permissions/checker.ts +14 -0
- package/src/permissions/ipc-risk-types.ts +3 -0
- package/src/permissions/question-prompter.test.ts +416 -0
- package/src/permissions/question-prompter.ts +294 -0
- package/src/platform/client.test.ts +1 -1
- package/src/platform/client.ts +1 -1
- package/src/plugin-api/constants.ts +26 -0
- package/src/plugin-api/index.ts +46 -0
- package/src/plugin-api/package.json +12 -0
- package/src/plugin-api/types.ts +144 -0
- package/src/plugins/defaults/circuit-breaker.ts +0 -5
- package/src/plugins/defaults/compaction.ts +0 -4
- package/src/plugins/defaults/empty-response.ts +0 -2
- package/src/plugins/defaults/history-repair.ts +0 -2
- package/src/plugins/defaults/injectors.ts +55 -6
- package/src/plugins/defaults/llm-call.ts +0 -2
- package/src/plugins/defaults/memory-retrieval.ts +0 -1
- package/src/plugins/defaults/overflow-reduce.ts +0 -1
- package/src/plugins/defaults/persistence.ts +0 -2
- package/src/plugins/defaults/title-generate.ts +0 -5
- package/src/plugins/defaults/token-estimate.ts +0 -2
- package/src/plugins/defaults/tool-error.ts +0 -7
- package/src/plugins/defaults/tool-execute.ts +0 -2
- package/src/plugins/defaults/tool-result-truncate.ts +0 -4
- package/src/plugins/ensure-plugin-api-shim.ts +96 -0
- package/src/plugins/external-api.ts +104 -0
- package/src/plugins/external-plugin-loader.ts +367 -0
- package/src/plugins/feature-gate.ts +22 -0
- package/src/plugins/pipeline.ts +37 -0
- package/src/plugins/registry.ts +48 -80
- package/src/plugins/types.ts +74 -53
- package/src/plugins/user-loader.ts +85 -43
- package/src/proactive-artifact/aux-message-injector.ts +11 -0
- package/src/proactive-artifact/job.test.ts +49 -9
- package/src/proactive-artifact/job.ts +4 -0
- package/src/proactive-artifact/trigger-state.test.ts +9 -0
- package/src/proactive-artifact/trigger-state.ts +4 -0
- package/src/prompts/__tests__/system-prompt.test.ts +117 -0
- package/src/prompts/__tests__/task-progress-hint-section.test.ts +99 -0
- package/src/prompts/normalize-onboarding.ts +27 -0
- package/src/prompts/sections.ts +302 -0
- package/src/prompts/system-prompt.ts +72 -154
- package/src/prompts/templates/BOOTSTRAP.md +17 -1
- package/src/prompts/templates/system-sections.ts +173 -0
- package/src/prompts/update-bulletin-job.ts +61 -73
- package/src/providers/__tests__/dispatch-connection-routing.test.ts +279 -0
- package/src/providers/__tests__/inference.test.ts +303 -0
- package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
- package/src/providers/__tests__/provider-secret-catalog.test.ts +6 -0
- package/src/providers/__tests__/retry-callsite.test.ts +14 -32
- package/src/providers/__tests__/satellite-connection-routing.test.ts +510 -0
- package/src/providers/__tests__/search-provider-catalog.test.ts +80 -0
- package/src/providers/anthropic/client.ts +123 -54
- package/src/providers/call-site-routing.ts +94 -16
- package/src/providers/connection-resolution.ts +170 -0
- package/src/providers/inference/__tests__/connections-status-label.test.ts +250 -0
- package/src/providers/inference/adapter-factory.ts +210 -0
- package/src/providers/inference/auth.ts +112 -0
- package/src/providers/inference/backfill.ts +196 -0
- package/src/providers/inference/connections.ts +401 -0
- package/src/providers/inference/resolve-auth.ts +73 -0
- package/src/providers/model-catalog.ts +386 -6
- package/src/providers/openai/chat-completions-provider.ts +10 -2
- package/src/providers/openai/responses-provider.ts +4 -2
- package/src/providers/openrouter/client.ts +7 -0
- package/src/providers/{managed-proxy → platform-proxy}/constants.ts +4 -1
- package/src/providers/{managed-proxy → platform-proxy}/context.ts +3 -3
- package/src/providers/provider-availability.ts +17 -2
- package/src/providers/provider-catalog-visibility.ts +36 -0
- package/src/providers/provider-env-vars.ts +17 -7
- package/src/providers/provider-secret-catalog.ts +49 -30
- package/src/providers/provider-send-message.ts +41 -20
- package/src/providers/registry.ts +151 -159
- package/src/providers/retry.ts +65 -11
- package/src/providers/search-provider-catalog.ts +121 -0
- package/src/runtime/AGENTS.md +18 -5
- package/src/runtime/__tests__/agent-wake.test.ts +152 -0
- package/src/runtime/__tests__/background-job-runner.test.ts +357 -0
- package/src/runtime/__tests__/pre-first-message-gate.test.ts +82 -0
- package/src/runtime/actor-trust-resolver.ts +32 -10
- package/src/runtime/agent-wake.ts +64 -7
- package/src/runtime/assistant-event-hub.ts +3 -85
- package/src/runtime/auth/route-policy.ts +311 -9
- package/src/runtime/auth/same-actor.ts +2 -0
- package/src/runtime/background-job-runner.ts +339 -0
- package/src/runtime/btw-sidechain.ts +3 -0
- package/src/runtime/http-router.ts +36 -1
- package/src/runtime/http-server.ts +31 -5
- package/src/runtime/http-types.ts +21 -0
- package/src/runtime/middleware/__tests__/request-logger.test.ts +162 -0
- package/src/runtime/middleware/request-logger.ts +62 -1
- package/src/runtime/migrations/origin-mode.ts +1 -1
- package/src/runtime/pending-interactions.ts +1 -0
- package/src/runtime/pre-first-message-gate.ts +83 -0
- package/src/runtime/routes/__tests__/backup-routes.test.ts +8 -1
- package/src/runtime/routes/__tests__/bookmark-routes.test.ts +268 -0
- package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +142 -0
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +319 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +280 -4
- package/src/runtime/routes/__tests__/home-feed-routes.test.ts +15 -136
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +736 -0
- package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +4 -4
- package/src/runtime/routes/__tests__/question-routes.test.ts +395 -0
- package/src/runtime/routes/__tests__/stt-routes.test.ts +5 -1
- package/src/runtime/routes/__tests__/surface-action-routes.test.ts +384 -0
- package/src/runtime/routes/__tests__/tts-routes.test.ts +70 -3
- package/src/runtime/routes/acp-routes-list.test.ts +143 -0
- package/src/runtime/routes/acp-routes.ts +12 -8
- package/src/runtime/routes/app-management-routes.ts +228 -3
- package/src/runtime/routes/approval-routes.ts +0 -18
- package/src/runtime/routes/audit-routes.ts +43 -0
- package/src/runtime/routes/auth-routes.ts +72 -0
- package/src/runtime/routes/avatar-routes.ts +273 -20
- package/src/runtime/routes/backup-routes.ts +406 -2
- package/src/runtime/routes/bookmark-routes.ts +156 -0
- package/src/runtime/routes/btw-routes.ts +5 -1
- package/src/runtime/routes/channel-availability-routes.ts +121 -0
- package/src/runtime/routes/channel-verification-routes.ts +2 -1
- package/src/runtime/routes/contact-routes.ts +0 -160
- package/src/runtime/routes/conversation-cli-routes.ts +233 -0
- package/src/runtime/routes/conversation-list-routes.ts +3 -20
- package/src/runtime/routes/conversation-management-routes.ts +47 -85
- package/src/runtime/routes/conversation-query-routes.ts +350 -97
- package/src/runtime/routes/conversation-routes.ts +121 -21
- package/src/runtime/routes/conversations-import-routes.ts +229 -0
- package/src/runtime/routes/credential-routes.ts +540 -0
- package/src/runtime/routes/debug-routes.ts +2 -2
- package/src/runtime/routes/document-pdf-renderer.ts +5 -1
- package/src/runtime/routes/documents-routes.ts +25 -86
- package/src/runtime/routes/domain-routes.ts +167 -0
- package/src/runtime/routes/email-routes.ts +603 -0
- package/src/runtime/routes/errors.ts +2 -2
- package/src/runtime/routes/events-routes.ts +192 -0
- package/src/runtime/routes/group-routes.ts +5 -0
- package/src/runtime/routes/home-feed-routes.ts +6 -78
- package/src/runtime/routes/host-app-control-routes.ts +44 -2
- package/src/runtime/routes/host-browser-routes.ts +103 -22
- package/src/runtime/routes/http-adapter.ts +2 -0
- package/src/runtime/routes/identity-routes.ts +5 -0
- package/src/runtime/routes/image-generation-routes.ts +99 -0
- package/src/runtime/routes/inbound-conversation.ts +28 -8
- package/src/runtime/routes/inbound-message-handler.ts +236 -41
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +248 -1
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +118 -7
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +17 -4
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +156 -0
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +22 -4
- package/src/runtime/routes/index.ts +42 -0
- package/src/runtime/routes/inference-profile-session-handler.ts +285 -0
- package/src/runtime/routes/inference-profile-session-reaper.ts +84 -0
- package/src/runtime/routes/inference-profile-session-routes.ts +146 -0
- package/src/runtime/routes/inference-provider-connection-routes.ts +361 -0
- package/src/runtime/routes/inference-send-routes.ts +115 -0
- package/src/runtime/routes/integrations/slack/share.ts +4 -52
- package/src/runtime/routes/integrations/slack/token.ts +43 -0
- package/src/runtime/routes/integrations/twilio.ts +7 -13
- package/src/runtime/routes/mcp-auth-routes.ts +283 -9
- package/src/runtime/routes/memory-v2-routes.ts +13 -398
- package/src/runtime/routes/notification-routes.ts +3 -1
- package/src/runtime/routes/oauth-apps.ts +112 -7
- package/src/runtime/routes/oauth-commands-routes.ts +1097 -0
- package/src/runtime/routes/oauth-connect-routes.ts +67 -5
- package/src/runtime/routes/oauth-lifecycle-routes.ts +43 -0
- package/src/runtime/routes/oauth-providers.ts +298 -8
- package/src/runtime/routes/platform-routes.ts +336 -0
- package/src/runtime/routes/playground/inject-failures.ts +2 -1
- package/src/runtime/routes/playground/reset-circuit.ts +2 -1
- package/src/runtime/routes/playground/state.ts +2 -1
- package/src/runtime/routes/publish-routes.ts +221 -0
- package/src/runtime/routes/question-routes.ts +259 -0
- package/src/runtime/routes/rename-conversation-routes.ts +2 -33
- package/src/runtime/routes/schedule-routes.ts +79 -0
- package/src/runtime/routes/sequence-routes.ts +291 -0
- package/src/runtime/routes/settings-routes.ts +2 -10
- package/src/runtime/routes/skills-routes.ts +31 -1
- package/src/runtime/routes/stt-routes.ts +240 -3
- package/src/runtime/routes/subagents-routes.ts +57 -18
- package/src/runtime/routes/surface-action-routes.ts +43 -7
- package/src/runtime/routes/telemetry-routes.ts +27 -0
- package/src/runtime/routes/tts-routes.ts +93 -1
- package/src/runtime/routes/types.ts +32 -0
- package/src/runtime/routes/user-routes-cli.ts +243 -0
- package/src/runtime/routes/webhook-routes.ts +165 -0
- package/src/runtime/routes/workspace-routes.test.ts +43 -0
- package/src/runtime/routes/workspace-routes.ts +28 -0
- package/src/runtime/services/conversation-serializer.ts +39 -7
- package/src/runtime/sync/resource-sync-events.ts +117 -0
- package/src/runtime/sync/sync-publisher.test.ts +105 -0
- package/src/runtime/sync/sync-publisher.ts +21 -0
- package/src/schedule/schedule-store.ts +27 -2
- package/src/schedule/scheduler.ts +208 -123
- package/src/security/__tests__/provider-key-env-fallback.test.ts +12 -6
- package/src/security/__tests__/untrusted-content.test.ts +86 -0
- package/src/security/secret-patterns.ts +3 -0
- package/src/security/untrusted-content.ts +93 -8
- package/src/sequence/engine.ts +38 -40
- package/src/skills/catalog-files.ts +1 -1
- package/src/skills/catalog-install.ts +233 -116
- package/src/skills/clawhub.ts +70 -13
- package/src/skills/managed-store.ts +4 -119
- package/src/skills/skillssh-registry.ts +27 -48
- package/src/subagent/manager.ts +28 -15
- package/src/telemetry/types.ts +113 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +312 -5
- package/src/telemetry/usage-telemetry-reporter.ts +113 -7
- package/src/tools/apps/executors.ts +58 -7
- package/src/tools/ask-question/ask-question-tool.test.ts +509 -0
- package/src/tools/ask-question/ask-question-tool.ts +304 -0
- package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +206 -0
- package/src/tools/browser/browser-execution.ts +29 -14
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +174 -0
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +16 -13
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +24 -1
- package/src/tools/browser/cdp-client/factory.ts +66 -5
- package/src/tools/browser/runtime-check.ts +77 -0
- package/src/tools/computer-use/definitions.ts +3 -3
- package/src/tools/credentials/vault.ts +1 -1
- package/src/tools/document/document-tool.ts +124 -1
- package/src/tools/filesystem/edit.ts +1 -1
- package/src/tools/filesystem/list.ts +1 -1
- package/src/tools/filesystem/read.ts +1 -1
- package/src/tools/filesystem/write.ts +5 -2
- package/src/tools/host-filesystem/transfer.ts +1 -1
- package/src/tools/host-terminal/host-shell.ts +1 -1
- package/src/tools/memory/register.test.ts +3 -3
- package/src/tools/memory/register.ts +9 -1
- package/src/tools/network/__tests__/web-search.test.ts +156 -0
- package/src/tools/network/web-search.ts +280 -37
- package/src/tools/permission-checker.ts +14 -6
- package/src/tools/registry.ts +17 -7
- package/src/tools/schedule/create.ts +2 -2
- package/src/tools/schema-transforms.ts +7 -2
- package/src/tools/side-effects.ts +1 -0
- package/src/tools/skills/delete-managed.ts +4 -4
- package/src/tools/skills/execute.ts +1 -1
- package/src/tools/skills/scaffold-managed.ts +3 -2
- package/src/tools/subagent/notify-parent.ts +1 -1
- package/src/tools/subagent/spawn.ts +3 -3
- package/src/tools/system/request-permission.ts +2 -2
- package/src/tools/terminal/safe-env.ts +60 -1
- package/src/tools/terminal/shell.ts +44 -0
- package/src/tools/tool-manifest.ts +2 -0
- package/src/tools/types.ts +72 -21
- package/src/tools/ui-surface/definitions.ts +6 -5
- package/src/tts/__tests__/provider-adapters.test.ts +76 -2
- package/src/tts/providers/elevenlabs-provider.ts +75 -1
- package/src/types/onboarding-context.ts +2 -0
- package/src/usage/attribution.ts +3 -2
- package/src/util/errors.ts +17 -0
- package/src/util/platform.ts +10 -0
- package/src/util/pricing.ts +86 -160
- package/src/watcher/__tests__/engine.test.ts +323 -0
- package/src/watcher/constants.ts +7 -0
- package/src/watcher/engine.ts +94 -90
- package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +6 -9
- package/src/workspace/migrations/054-seed-recall-callsite.ts +10 -1
- package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +94 -5
- package/src/workspace/migrations/069-seed-onboarding-threads.ts +8 -2
- package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +117 -0
- package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +95 -0
- package/src/workspace/migrations/074-drop-deprecated-secret-detection-keys.ts +117 -0
- package/src/workspace/migrations/075-memory-v2-bm25-b-default-reembed.ts +61 -0
- package/src/workspace/migrations/076-drop-services-inference-mode.ts +62 -0
- package/src/workspace/migrations/077-seed-memory-router-callsite.ts +89 -0
- package/src/workspace/migrations/078-release-notes-tavily-web-search.ts +66 -0
- package/src/workspace/migrations/079-home-feed-notification-only.ts +197 -0
- package/src/workspace/migrations/080-restrict-vercel-api-token-metadata.ts +182 -0
- package/src/workspace/migrations/081-backfill-bash-allowed-tools-for-injection-credentials.ts +160 -0
- package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +154 -0
- package/src/workspace/migrations/083-system-prompt-prefix-to-file.ts +191 -0
- package/src/workspace/migrations/084-remove-legacy-skills-index.ts +276 -0
- package/src/workspace/migrations/085-memory-v2-bm25-b-reembed-disabled-v2-pages.ts +137 -0
- package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +198 -0
- package/src/workspace/migrations/registry.ts +30 -0
- package/src/workspace/migrations/runner.ts +46 -5
- package/src/workspace/migrations/types.ts +17 -3
- package/src/workspace/provider-commit-message-generator.ts +3 -2
- package/examples/plugins/echo/bun.lock +0 -25
- package/src/__tests__/context-search-pkb-source.test.ts +0 -498
- package/src/__tests__/context-window-manager.test.ts +0 -2093
- package/src/__tests__/credentials-cli.test.ts +0 -1225
- package/src/__tests__/memory-admin-recall.test.ts +0 -213
- package/src/approvals/__tests__/guardian-feed-event.test.ts +0 -303
- package/src/cli/commands/__tests__/email-download.test.ts +0 -260
- package/src/cli/commands/__tests__/email-list.test.ts +0 -216
- package/src/cli/commands/__tests__/email-register.test.ts +0 -186
- package/src/cli/commands/__tests__/email-send.test.ts +0 -416
- package/src/cli/commands/__tests__/email-status.test.ts +0 -185
- package/src/cli/commands/__tests__/email-unregister.test.ts +0 -168
- package/src/cli/commands/__tests__/routes.test.ts +0 -562
- package/src/cli/commands/__tests__/stt-transcribe.test.ts +0 -454
- package/src/cli/commands/autonomy.ts +0 -365
- package/src/cli/commands/memory.ts +0 -424
- package/src/cli/commands/oauth/__tests__/connect.test.ts +0 -947
- package/src/cli/commands/oauth/__tests__/disconnect.test.ts +0 -686
- package/src/cli/commands/oauth/__tests__/mode.test.ts +0 -632
- package/src/cli/commands/oauth/__tests__/ping.test.ts +0 -631
- package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +0 -573
- package/src/cli/commands/oauth/__tests__/providers-register.test.ts +0 -330
- package/src/cli/commands/oauth/__tests__/providers-update.test.ts +0 -521
- package/src/cli/commands/oauth/__tests__/status.test.ts +0 -551
- package/src/cli/commands/oauth/__tests__/token.test.ts +0 -420
- package/src/cli/lib/daemon-avatar-client.ts +0 -37
- package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -87
- package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +0 -207
- package/src/context/__tests__/compact-prompt.test.ts +0 -63
- package/src/context/prompts/compact.md +0 -26
- package/src/daemon/__tests__/conversation-feed-event.test.ts +0 -304
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +0 -233
- package/src/home/__tests__/assistant-feed-authoring.test.ts +0 -156
- package/src/home/__tests__/emit-feed-event.test.ts +0 -169
- package/src/home/__tests__/feed-population-integration.test.ts +0 -312
- package/src/home/__tests__/feed-scheduler.test.ts +0 -222
- package/src/home/__tests__/phase5-exit-criteria.test.ts +0 -229
- package/src/home/__tests__/platform-gmail-digest.test.ts +0 -222
- package/src/home/__tests__/rollup-producer.test.ts +0 -507
- package/src/home/assistant-feed-authoring.ts +0 -135
- package/src/home/emit-feed-event.ts +0 -169
- package/src/home/feed-scheduler.ts +0 -281
- package/src/home/platform-gmail-digest.ts +0 -163
- package/src/home/rewrite-command-preview.ts +0 -66
- package/src/home/rewrite-feed-title.ts +0 -58
- package/src/home/rollup-producer.ts +0 -426
- package/src/memory/admin.ts +0 -326
- package/src/memory/context-search/sources/pkb.ts +0 -476
- package/src/memory/graph/compaction.ts +0 -299
- package/src/prompts/__tests__/build-cli-reference-section.test.ts +0 -37
- /package/src/cli/{commands → lib}/cache-fs.ts +0 -0
package/src/memory/indexer.ts
CHANGED
|
@@ -12,6 +12,8 @@ import { getMemoryCheckpoint, setMemoryCheckpoint } from "./checkpoints.js";
|
|
|
12
12
|
import { getDb } from "./db-connection.js";
|
|
13
13
|
import { selectedBackendSupportsMultimodal } from "./embedding-backend.js";
|
|
14
14
|
import { enqueueMemoryJob, upsertDebouncedJob } from "./jobs-store.js";
|
|
15
|
+
import { isMemoryRetrospectiveConversation } from "./memory-retrospective-enqueue.js";
|
|
16
|
+
import { maybeEnqueueRetrospective } from "./memory-retrospective-trigger-check.js";
|
|
15
17
|
import {
|
|
16
18
|
extractMediaBlockMeta,
|
|
17
19
|
extractTextFromStoredMessageContent,
|
|
@@ -167,32 +169,30 @@ export async function indexMessageNow(
|
|
|
167
169
|
const batchSize = config.extraction.batchSize ?? 10;
|
|
168
170
|
const idleTimeoutMs = config.extraction.idleTimeoutMs ?? 300_000;
|
|
169
171
|
|
|
172
|
+
// Reading config here is best-effort: when it fails we treat v2 as
|
|
173
|
+
// inactive (failing-open to v1) so a config error never silently
|
|
174
|
+
// drops the extraction or summarization paths.
|
|
175
|
+
let triggerConfig: ReturnType<typeof getConfig> | null = null;
|
|
176
|
+
try {
|
|
177
|
+
triggerConfig = getConfig();
|
|
178
|
+
} catch (err) {
|
|
179
|
+
log.debug(
|
|
180
|
+
{ err, conversationId: input.conversationId },
|
|
181
|
+
"Skipping feature-gated extraction triggers: failed to load config",
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const v2Config =
|
|
186
|
+
triggerConfig != null && triggerConfig.memory.v2.enabled
|
|
187
|
+
? triggerConfig
|
|
188
|
+
: null;
|
|
189
|
+
|
|
170
190
|
// Recursion guard: skip graph extraction + auto-analysis enqueues
|
|
171
191
|
// when the source conversation is itself an auto-analysis
|
|
172
192
|
// conversation. The analysis agent writes memory directly via tools,
|
|
173
193
|
// so extracting from its reflective musings would double-count and
|
|
174
194
|
// analyzing its own output would loop indefinitely.
|
|
175
|
-
// Summaries still run — they feed the graph retrieval pipeline and
|
|
176
|
-
// are not recursion-prone.
|
|
177
195
|
if (!isAutoAnalysisSource) {
|
|
178
|
-
// Reading config here is best-effort: when it fails we treat v2 as
|
|
179
|
-
// inactive (failing-open to v1) so a config error never silently
|
|
180
|
-
// drops both extraction paths.
|
|
181
|
-
let triggerConfig: ReturnType<typeof getConfig> | null = null;
|
|
182
|
-
try {
|
|
183
|
-
triggerConfig = getConfig();
|
|
184
|
-
} catch (err) {
|
|
185
|
-
log.debug(
|
|
186
|
-
{ err, conversationId: input.conversationId },
|
|
187
|
-
"Skipping feature-gated extraction triggers: failed to load config",
|
|
188
|
-
);
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
const v2Config =
|
|
192
|
-
triggerConfig != null && triggerConfig.memory.v2.enabled
|
|
193
|
-
? triggerConfig
|
|
194
|
-
: null;
|
|
195
|
-
|
|
196
196
|
// ── Graph extraction (v1) ───────────────────────────────────────
|
|
197
197
|
// Suppressed when v2 is active — v2 reads memory from buffer.md
|
|
198
198
|
// and concept pages, so the v1 graph would be stale data nobody
|
|
@@ -283,17 +283,39 @@ export async function indexMessageNow(
|
|
|
283
283
|
});
|
|
284
284
|
}
|
|
285
285
|
}
|
|
286
|
+
|
|
287
|
+
// ── Memory retrospective triggers ─────────────────────────────────
|
|
288
|
+
// Independent of auto-analyze: the retrospective is a focused,
|
|
289
|
+
// memory-only pass that re-reads messages since its last successful
|
|
290
|
+
// run and saves what the in-conversation `remember` calls didn't
|
|
291
|
+
// capture. Triggers (interval / message_count) are evaluated by
|
|
292
|
+
// `maybeEnqueueRetrospective`, which also enforces the per-conversation
|
|
293
|
+
// cooldown gate against retry storms. Recursion guard skips the
|
|
294
|
+
// memory-retrospective background conversation itself.
|
|
295
|
+
if (
|
|
296
|
+
triggerConfig != null &&
|
|
297
|
+
!isMemoryRetrospectiveConversation(input.conversationId)
|
|
298
|
+
) {
|
|
299
|
+
maybeEnqueueRetrospective(input.conversationId, triggerConfig);
|
|
300
|
+
}
|
|
286
301
|
}
|
|
287
302
|
|
|
288
|
-
// ── Conversation summarization (
|
|
289
|
-
// Summaries feed the graph retrieval pipeline
|
|
290
|
-
//
|
|
291
|
-
//
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
303
|
+
// ── Conversation summarization (v1) ───────────────────────────────
|
|
304
|
+
// Summaries feed the v1 graph retrieval pipeline (fetchRecentSummaries,
|
|
305
|
+
// semantic search). Suppressed when v2 is active — v2 readers (concept
|
|
306
|
+
// pages, activation pipeline) do not consume `memorySummaries`, so the
|
|
307
|
+
// summarization LLM call would produce rows nothing reads. Stale rows
|
|
308
|
+
// from before v2 was enabled are short-circuited at dispatch in
|
|
309
|
+
// jobs-worker.ts. Debounced on the same idle timeout — no threshold
|
|
310
|
+
// trigger needed since summaries compress the whole conversation, not
|
|
311
|
+
// incremental batches.
|
|
312
|
+
if (v2Config == null) {
|
|
313
|
+
upsertDebouncedJob(
|
|
314
|
+
"build_conversation_summary",
|
|
315
|
+
{ conversationId: input.conversationId },
|
|
316
|
+
Date.now() + idleTimeoutMs,
|
|
317
|
+
);
|
|
318
|
+
}
|
|
297
319
|
}
|
|
298
320
|
|
|
299
321
|
if (skippedShortSegments > 0) {
|
|
@@ -151,6 +151,8 @@ type MemoryJob = ReturnType<MemoryJobMod["claimMemoryJobs"]>[number];
|
|
|
151
151
|
const { embedConceptPageJob, enqueueEmbedConceptPageJob } =
|
|
152
152
|
await import("../embed-concept-page.js");
|
|
153
153
|
const { writePage } = await import("../../v2/page-store.js");
|
|
154
|
+
const { _resetQdrantBreaker, isQdrantBreakerOpen, withQdrantBreaker } =
|
|
155
|
+
await import("../../qdrant-circuit-breaker.js");
|
|
154
156
|
|
|
155
157
|
// Use a tiny vectorSize so the cache-dim check matches our stub vector.
|
|
156
158
|
const TEST_CONFIG = {
|
|
@@ -186,6 +188,7 @@ beforeEach(() => {
|
|
|
186
188
|
embedWithBackendCalls.length = 0;
|
|
187
189
|
upsertCalls.length = 0;
|
|
188
190
|
deleteCalls.length = 0;
|
|
191
|
+
_resetQdrantBreaker();
|
|
189
192
|
});
|
|
190
193
|
|
|
191
194
|
afterEach(() => {
|
|
@@ -203,7 +206,7 @@ describe("embedConceptPageJob — happy path", () => {
|
|
|
203
206
|
test("reads the page, embeds it, and upserts to the v2 collection", async () => {
|
|
204
207
|
await writePage(tmpWorkspace, {
|
|
205
208
|
slug: "alice-prefers-vs-code",
|
|
206
|
-
frontmatter: { edges: [], ref_files: [] },
|
|
209
|
+
frontmatter: { edges: [], ref_files: [], ref_urls: [] },
|
|
207
210
|
body: "Alice prefers VS Code over Vim.\nShe ships at end of day.\n",
|
|
208
211
|
});
|
|
209
212
|
|
|
@@ -231,7 +234,7 @@ describe("embedConceptPageJob — happy path", () => {
|
|
|
231
234
|
test("populates the SQLite embedding cache row keyed on (concept_page, slug)", async () => {
|
|
232
235
|
await writePage(tmpWorkspace, {
|
|
233
236
|
slug: "bob-uses-zsh",
|
|
234
|
-
frontmatter: { edges: [], ref_files: [] },
|
|
237
|
+
frontmatter: { edges: [], ref_files: [], ref_urls: [] },
|
|
235
238
|
body: "Bob uses zsh.\n",
|
|
236
239
|
});
|
|
237
240
|
|
|
@@ -257,6 +260,7 @@ describe("embedConceptPageJob — summary embedding", () => {
|
|
|
257
260
|
frontmatter: {
|
|
258
261
|
edges: [],
|
|
259
262
|
ref_files: [],
|
|
263
|
+
ref_urls: [],
|
|
260
264
|
summary: "A short prose summary that retrieval indexes separately.",
|
|
261
265
|
},
|
|
262
266
|
body: "Long-form body content.\n",
|
|
@@ -282,7 +286,7 @@ describe("embedConceptPageJob — summary embedding", () => {
|
|
|
282
286
|
test("skips summary embedding when the page has no summary in frontmatter", async () => {
|
|
283
287
|
await writePage(tmpWorkspace, {
|
|
284
288
|
slug: "legacy-page",
|
|
285
|
-
frontmatter: { edges: [], ref_files: [] },
|
|
289
|
+
frontmatter: { edges: [], ref_files: [], ref_urls: [] },
|
|
286
290
|
body: "Body only — no summary in frontmatter.\n",
|
|
287
291
|
});
|
|
288
292
|
|
|
@@ -303,6 +307,7 @@ describe("embedConceptPageJob — summary embedding", () => {
|
|
|
303
307
|
frontmatter: {
|
|
304
308
|
edges: [],
|
|
305
309
|
ref_files: [],
|
|
310
|
+
ref_urls: [],
|
|
306
311
|
summary: " ",
|
|
307
312
|
},
|
|
308
313
|
body: "Body content.\n",
|
|
@@ -324,14 +329,12 @@ describe("embedConceptPageJob — summary embedding", () => {
|
|
|
324
329
|
frontmatter: {
|
|
325
330
|
edges: [],
|
|
326
331
|
ref_files: [],
|
|
332
|
+
ref_urls: [],
|
|
327
333
|
summary: "First version of the summary.",
|
|
328
334
|
},
|
|
329
335
|
body: "Stable body that never changes.\n",
|
|
330
336
|
});
|
|
331
|
-
await embedConceptPageJob(
|
|
332
|
-
makeJob({ slug: "cached-summary" }),
|
|
333
|
-
TEST_CONFIG,
|
|
334
|
-
);
|
|
337
|
+
await embedConceptPageJob(makeJob({ slug: "cached-summary" }), TEST_CONFIG);
|
|
335
338
|
// Body + summary batched into a single backend call on first run.
|
|
336
339
|
expect(embedWithBackendCalls).toHaveLength(1);
|
|
337
340
|
expect(embedWithBackendCalls[0].inputs).toHaveLength(2);
|
|
@@ -344,14 +347,12 @@ describe("embedConceptPageJob — summary embedding", () => {
|
|
|
344
347
|
frontmatter: {
|
|
345
348
|
edges: [],
|
|
346
349
|
ref_files: [],
|
|
350
|
+
ref_urls: [],
|
|
347
351
|
summary: "Second version of the summary, different wording.",
|
|
348
352
|
},
|
|
349
353
|
body: "Stable body that never changes.\n",
|
|
350
354
|
});
|
|
351
|
-
await embedConceptPageJob(
|
|
352
|
-
makeJob({ slug: "cached-summary" }),
|
|
353
|
-
TEST_CONFIG,
|
|
354
|
-
);
|
|
355
|
+
await embedConceptPageJob(makeJob({ slug: "cached-summary" }), TEST_CONFIG);
|
|
355
356
|
// One additional backend call with only the summary text — body hit the cache.
|
|
356
357
|
expect(embedWithBackendCalls).toHaveLength(2);
|
|
357
358
|
expect(embedWithBackendCalls[1].inputs).toHaveLength(1);
|
|
@@ -362,7 +363,7 @@ describe("embedConceptPageJob — cache hit", () => {
|
|
|
362
363
|
test("reuses the cached dense vector when content hash matches", async () => {
|
|
363
364
|
await writePage(tmpWorkspace, {
|
|
364
365
|
slug: "alice-prefers-vs-code",
|
|
365
|
-
frontmatter: { edges: [], ref_files: [] },
|
|
366
|
+
frontmatter: { edges: [], ref_files: [], ref_urls: [] },
|
|
366
367
|
body: "Stable content.\n",
|
|
367
368
|
});
|
|
368
369
|
|
|
@@ -387,7 +388,7 @@ describe("embedConceptPageJob — cache hit", () => {
|
|
|
387
388
|
test("re-embeds when the body changes (content hash mismatch)", async () => {
|
|
388
389
|
await writePage(tmpWorkspace, {
|
|
389
390
|
slug: "alice-prefers-vs-code",
|
|
390
|
-
frontmatter: { edges: [], ref_files: [] },
|
|
391
|
+
frontmatter: { edges: [], ref_files: [], ref_urls: [] },
|
|
391
392
|
body: "First content.\n",
|
|
392
393
|
});
|
|
393
394
|
await embedConceptPageJob(
|
|
@@ -398,7 +399,7 @@ describe("embedConceptPageJob — cache hit", () => {
|
|
|
398
399
|
// Rewrite with different body.
|
|
399
400
|
await writePage(tmpWorkspace, {
|
|
400
401
|
slug: "alice-prefers-vs-code",
|
|
401
|
-
frontmatter: { edges: [], ref_files: [] },
|
|
402
|
+
frontmatter: { edges: [], ref_files: [], ref_urls: [] },
|
|
402
403
|
body: "Second content (different).\n",
|
|
403
404
|
});
|
|
404
405
|
await embedConceptPageJob(
|
|
@@ -438,6 +439,76 @@ describe("embedConceptPageJob — defensive", () => {
|
|
|
438
439
|
});
|
|
439
440
|
});
|
|
440
441
|
|
|
442
|
+
describe("embedConceptPageJob — Qdrant breaker integration", () => {
|
|
443
|
+
test("half-open probe success closes the breaker so embed catch-up unthrottles", async () => {
|
|
444
|
+
// Trip the breaker by recording 5 consecutive Qdrant failures. Without
|
|
445
|
+
// this fix, `embed_concept_page` bypassed the breaker entirely — winning
|
|
446
|
+
// the half-open probe slot did not transition state back to closed and
|
|
447
|
+
// the embed lane stayed throttled at one job per tick indefinitely.
|
|
448
|
+
for (let i = 0; i < 5; i++) {
|
|
449
|
+
try {
|
|
450
|
+
await withQdrantBreaker(async () => {
|
|
451
|
+
throw new Error("simulated qdrant failure");
|
|
452
|
+
});
|
|
453
|
+
} catch {
|
|
454
|
+
// expected
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
expect(isQdrantBreakerOpen()).toBe(true);
|
|
458
|
+
|
|
459
|
+
// Advance time past the 30s cooldown so the next breaker call transitions
|
|
460
|
+
// open → half-open and allows the probe through.
|
|
461
|
+
const originalNow = Date.now;
|
|
462
|
+
Date.now = () => originalNow() + 60_000;
|
|
463
|
+
try {
|
|
464
|
+
await writePage(tmpWorkspace, {
|
|
465
|
+
slug: "probe-success",
|
|
466
|
+
frontmatter: { edges: [], ref_files: [], ref_urls: [] },
|
|
467
|
+
body: "Probe body.\n",
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
await embedConceptPageJob(
|
|
471
|
+
makeJob({ slug: "probe-success" }),
|
|
472
|
+
TEST_CONFIG,
|
|
473
|
+
);
|
|
474
|
+
} finally {
|
|
475
|
+
Date.now = originalNow;
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
expect(upsertCalls).toHaveLength(1);
|
|
479
|
+
// Probe succeeded → breaker should now be closed (not open, not
|
|
480
|
+
// half-open), restoring full embed-lane concurrency.
|
|
481
|
+
expect(isQdrantBreakerOpen()).toBe(false);
|
|
482
|
+
});
|
|
483
|
+
|
|
484
|
+
test("half-open probe success on the delete path also closes the breaker", async () => {
|
|
485
|
+
// Same flow as above but exercising the missing-page branch — both v2
|
|
486
|
+
// Qdrant calls (`upsert` and `delete`) must close the breaker on success.
|
|
487
|
+
for (let i = 0; i < 5; i++) {
|
|
488
|
+
try {
|
|
489
|
+
await withQdrantBreaker(async () => {
|
|
490
|
+
throw new Error("simulated qdrant failure");
|
|
491
|
+
});
|
|
492
|
+
} catch {
|
|
493
|
+
// expected
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
expect(isQdrantBreakerOpen()).toBe(true);
|
|
497
|
+
|
|
498
|
+
const originalNow = Date.now;
|
|
499
|
+
Date.now = () => originalNow() + 60_000;
|
|
500
|
+
try {
|
|
501
|
+
// No `writePage` — the handler takes the delete branch.
|
|
502
|
+
await embedConceptPageJob(makeJob({ slug: "missing-slug" }), TEST_CONFIG);
|
|
503
|
+
} finally {
|
|
504
|
+
Date.now = originalNow;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
expect(deleteCalls).toEqual(["missing-slug"]);
|
|
508
|
+
expect(isQdrantBreakerOpen()).toBe(false);
|
|
509
|
+
});
|
|
510
|
+
});
|
|
511
|
+
|
|
441
512
|
describe("enqueueEmbedConceptPageJob", () => {
|
|
442
513
|
test("enqueues a pending embed_concept_page job with the slug payload", () => {
|
|
443
514
|
const id = enqueueEmbedConceptPageJob({ slug: "alice-prefers-vs-code" });
|
|
@@ -453,7 +524,7 @@ describe("enqueueEmbedConceptPageJob", () => {
|
|
|
453
524
|
test("round-trip: enqueued job dispatches through embedConceptPageJob", async () => {
|
|
454
525
|
await writePage(tmpWorkspace, {
|
|
455
526
|
slug: "round-trip-slug",
|
|
456
|
-
frontmatter: { edges: [], ref_files: [] },
|
|
527
|
+
frontmatter: { edges: [], ref_files: [], ref_urls: [] },
|
|
457
528
|
body: "Round-trip body.\n",
|
|
458
529
|
});
|
|
459
530
|
|
|
@@ -34,6 +34,7 @@ import {
|
|
|
34
34
|
import { embeddingInputContentHash } from "../embedding-types.js";
|
|
35
35
|
import { asString, blobToVector, vectorToBlob } from "../job-utils.js";
|
|
36
36
|
import { enqueueMemoryJob, type MemoryJob } from "../jobs-store.js";
|
|
37
|
+
import { withQdrantBreaker } from "../qdrant-circuit-breaker.js";
|
|
37
38
|
import { memoryEmbeddings } from "../schema.js";
|
|
38
39
|
import { readPage } from "../v2/page-store.js";
|
|
39
40
|
import {
|
|
@@ -81,7 +82,10 @@ export async function embedConceptPageJob(
|
|
|
81
82
|
if (!page) {
|
|
82
83
|
// Page was deleted out from under us — clean up the prior embedding so
|
|
83
84
|
// retrieval no longer surfaces a slug whose disk-side prose is gone.
|
|
84
|
-
|
|
85
|
+
// Route through the Qdrant breaker so success on the half-open probe
|
|
86
|
+
// slot transitions the breaker back to closed and unthrottles embed
|
|
87
|
+
// catch-up.
|
|
88
|
+
await withQdrantBreaker(() => deleteConceptPageEmbedding(slug));
|
|
85
89
|
return;
|
|
86
90
|
}
|
|
87
91
|
|
|
@@ -163,21 +167,54 @@ export async function embedConceptPageJob(
|
|
|
163
167
|
slots.push("summary");
|
|
164
168
|
}
|
|
165
169
|
|
|
166
|
-
let bodyDense: number[] | undefined = bodyCacheHit
|
|
170
|
+
let bodyDense: number[] | undefined = bodyCacheHit
|
|
171
|
+
? bodyCache!.dense
|
|
172
|
+
: undefined;
|
|
167
173
|
let summaryDense: number[] | undefined = summaryCacheHit
|
|
168
174
|
? summaryCache!.dense
|
|
169
175
|
: undefined;
|
|
170
176
|
let writeProvider = cacheProvider;
|
|
171
177
|
let writeModel = cacheModel;
|
|
178
|
+
let bodyFresh = false;
|
|
179
|
+
let summaryFresh = false;
|
|
172
180
|
if (toEmbed.length > 0) {
|
|
173
|
-
|
|
181
|
+
let embedded = await embedWithBackend(config, toEmbed);
|
|
182
|
+
let appliedSlots = slots;
|
|
183
|
+
// Backend rotation between `getMemoryBackendStatus()` and
|
|
184
|
+
// `embedWithBackend()` would tag the cached half with the old
|
|
185
|
+
// provider/model and the fresh half with the new — writing both into
|
|
186
|
+
// one Qdrant point mixes embedding spaces. Re-embed every slot fresh
|
|
187
|
+
// when we detect the rotation so the point's named vectors share one
|
|
188
|
+
// identity.
|
|
189
|
+
const rotated =
|
|
190
|
+
(bodyCacheHit || summaryCacheHit) &&
|
|
191
|
+
(embedded.provider !== cacheProvider || embedded.model !== cacheModel);
|
|
192
|
+
if (rotated) {
|
|
193
|
+
const allTexts: Array<{ type: "text"; text: string }> = [
|
|
194
|
+
{ type: "text", text },
|
|
195
|
+
];
|
|
196
|
+
const allSlots: Slot[] = ["body"];
|
|
197
|
+
if (hasSummary) {
|
|
198
|
+
allTexts.push({ type: "text", text: summaryText });
|
|
199
|
+
allSlots.push("summary");
|
|
200
|
+
}
|
|
201
|
+
embedded = await embedWithBackend(config, allTexts);
|
|
202
|
+
appliedSlots = allSlots;
|
|
203
|
+
bodyDense = undefined;
|
|
204
|
+
summaryDense = undefined;
|
|
205
|
+
}
|
|
174
206
|
writeProvider = embedded.provider;
|
|
175
207
|
writeModel = embedded.model;
|
|
176
|
-
for (let i = 0; i <
|
|
208
|
+
for (let i = 0; i < appliedSlots.length; i++) {
|
|
177
209
|
const vector = embedded.vectors[i];
|
|
178
210
|
if (!vector) continue;
|
|
179
|
-
if (
|
|
180
|
-
|
|
211
|
+
if (appliedSlots[i] === "body") {
|
|
212
|
+
bodyDense = vector;
|
|
213
|
+
bodyFresh = true;
|
|
214
|
+
} else {
|
|
215
|
+
summaryDense = vector;
|
|
216
|
+
summaryFresh = true;
|
|
217
|
+
}
|
|
181
218
|
}
|
|
182
219
|
}
|
|
183
220
|
// Body embedding is the ground truth — without it the page can't surface.
|
|
@@ -205,9 +242,12 @@ export async function embedConceptPageJob(
|
|
|
205
242
|
const now = Date.now();
|
|
206
243
|
// Persist freshly embedded vectors for cross-restart reuse. On cache hit
|
|
207
244
|
// the existing row already has identical content + hash, so the write
|
|
208
|
-
// would be a no-op — skip it.
|
|
209
|
-
//
|
|
210
|
-
|
|
245
|
+
// would be a no-op — skip it. Backend rotation flips a cache hit into a
|
|
246
|
+
// fresh embed (see `rotated` above); the `*Fresh` flags capture that so
|
|
247
|
+
// the new vector overwrites the now-stale cache row under the new
|
|
248
|
+
// provider/model identity. Best-effort: write failure is not fatal, we
|
|
249
|
+
// still want the Qdrant upsert below to fire.
|
|
250
|
+
if (bodyFresh) {
|
|
211
251
|
writeEmbeddingCache(db, {
|
|
212
252
|
slug,
|
|
213
253
|
cacheId: slug,
|
|
@@ -218,7 +258,7 @@ export async function embedConceptPageJob(
|
|
|
218
258
|
now,
|
|
219
259
|
});
|
|
220
260
|
}
|
|
221
|
-
if (hasSummary &&
|
|
261
|
+
if (hasSummary && summaryFresh && summaryDense && summaryContentHash) {
|
|
222
262
|
writeEmbeddingCache(db, {
|
|
223
263
|
slug,
|
|
224
264
|
cacheId: summaryCacheId,
|
|
@@ -244,16 +284,21 @@ export async function embedConceptPageJob(
|
|
|
244
284
|
? await applyCorrectionIfCalibrated(summaryDense, writeProvider, writeModel)
|
|
245
285
|
: undefined;
|
|
246
286
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
287
|
+
// Route through the Qdrant breaker so a probe-slot success transitions the
|
|
288
|
+
// breaker back to closed; without this wrapper the embed lane stays
|
|
289
|
+
// throttled at one job per tick indefinitely after a half-open success.
|
|
290
|
+
await withQdrantBreaker(() =>
|
|
291
|
+
upsertConceptPageEmbedding({
|
|
292
|
+
slug,
|
|
293
|
+
dense: correctedDense,
|
|
294
|
+
sparse,
|
|
295
|
+
summary:
|
|
296
|
+
correctedSummaryDense && summarySparse
|
|
297
|
+
? { dense: correctedSummaryDense, sparse: summarySparse }
|
|
298
|
+
: undefined,
|
|
299
|
+
updatedAt: now,
|
|
300
|
+
}),
|
|
301
|
+
);
|
|
257
302
|
}
|
|
258
303
|
|
|
259
304
|
/** SQLite cache row shape returned by `readEmbeddingCache`. */
|
package/src/memory/jobs-store.ts
CHANGED
|
@@ -42,7 +42,8 @@ export type MemoryJobType =
|
|
|
42
42
|
| "memory_v2_consolidate"
|
|
43
43
|
| "memory_v2_migrate"
|
|
44
44
|
| "memory_v2_reembed"
|
|
45
|
-
| "memory_v2_activation_recompute"
|
|
45
|
+
| "memory_v2_activation_recompute"
|
|
46
|
+
| "memory_retrospective";
|
|
46
47
|
|
|
47
48
|
export const EMBED_JOB_TYPES: MemoryJobType[] = [
|
|
48
49
|
"embed_segment",
|
|
@@ -52,6 +53,7 @@ export const EMBED_JOB_TYPES: MemoryJobType[] = [
|
|
|
52
53
|
"embed_graph_node",
|
|
53
54
|
"embed_pkb_file",
|
|
54
55
|
"graph_trigger_embed",
|
|
56
|
+
"embed_concept_page",
|
|
55
57
|
];
|
|
56
58
|
|
|
57
59
|
export const SLOW_LLM_JOB_TYPES: MemoryJobType[] = [
|
|
@@ -65,6 +67,7 @@ export const SLOW_LLM_JOB_TYPES: MemoryJobType[] = [
|
|
|
65
67
|
"memory_v2_sweep",
|
|
66
68
|
"memory_v2_consolidate",
|
|
67
69
|
"memory_v2_migrate",
|
|
70
|
+
"memory_retrospective",
|
|
68
71
|
"backfill",
|
|
69
72
|
"graph_bootstrap",
|
|
70
73
|
];
|
|
@@ -251,6 +254,53 @@ export function upsertAutoAnalysisJob(
|
|
|
251
254
|
}
|
|
252
255
|
}
|
|
253
256
|
|
|
257
|
+
/**
|
|
258
|
+
* Upsert a pending `memory_retrospective` job keyed by `conversationId`. All
|
|
259
|
+
* four retrospective triggers (interval, message_count, compaction,
|
|
260
|
+
* lifecycle) collapse into a single pending row per conversation — rapid
|
|
261
|
+
* triggers coalesce instead of double-firing. The `runAfter` parameter on a
|
|
262
|
+
* follow-up enqueue overwrites the existing row's `runAfter` so a sooner
|
|
263
|
+
* trigger can pull a later-scheduled job earlier; a later-scheduled trigger
|
|
264
|
+
* does NOT push a sooner-scheduled row further out (consumer takes the
|
|
265
|
+
* minimum). The trigger metadata is intentionally not retained — it is only
|
|
266
|
+
* useful for observability at enqueue time.
|
|
267
|
+
*/
|
|
268
|
+
export function upsertMemoryRetrospectiveJob(
|
|
269
|
+
payload: { conversationId: string },
|
|
270
|
+
runAfter: number = Date.now(),
|
|
271
|
+
dbOverride?: Parameters<ReturnType<typeof getDb>["transaction"]>[0] extends (
|
|
272
|
+
tx: infer T,
|
|
273
|
+
) => unknown
|
|
274
|
+
? T
|
|
275
|
+
: never,
|
|
276
|
+
): void {
|
|
277
|
+
const db = dbOverride ?? getDb();
|
|
278
|
+
const existing = db
|
|
279
|
+
.select()
|
|
280
|
+
.from(memoryJobs)
|
|
281
|
+
.where(
|
|
282
|
+
and(
|
|
283
|
+
eq(memoryJobs.type, "memory_retrospective"),
|
|
284
|
+
eq(memoryJobs.status, "pending"),
|
|
285
|
+
sql`json_extract(${memoryJobs.payload}, '$.conversationId') = ${payload.conversationId}`,
|
|
286
|
+
),
|
|
287
|
+
)
|
|
288
|
+
.get();
|
|
289
|
+
if (existing) {
|
|
290
|
+
// Take the minimum of the existing and incoming runAfter so the earliest
|
|
291
|
+
// trigger always wins. A later trigger never pushes work further out.
|
|
292
|
+
const nextRunAfter = Math.min(existing.runAfter, runAfter);
|
|
293
|
+
if (nextRunAfter !== existing.runAfter) {
|
|
294
|
+
db.update(memoryJobs)
|
|
295
|
+
.set({ runAfter: nextRunAfter, updatedAt: Date.now() })
|
|
296
|
+
.where(eq(memoryJobs.id, existing.id))
|
|
297
|
+
.run();
|
|
298
|
+
}
|
|
299
|
+
return;
|
|
300
|
+
}
|
|
301
|
+
enqueueMemoryJob("memory_retrospective", payload, runAfter, dbOverride);
|
|
302
|
+
}
|
|
303
|
+
|
|
254
304
|
/**
|
|
255
305
|
* Check whether a pending or running job of the given type already exists.
|
|
256
306
|
* Used to prevent duplicate enqueues for long-running maintenance jobs.
|
|
@@ -67,6 +67,8 @@ import {
|
|
|
67
67
|
resetRunningJobsToPending,
|
|
68
68
|
SLOW_LLM_JOB_TYPES,
|
|
69
69
|
} from "./jobs-store.js";
|
|
70
|
+
import { memoryRetrospectiveJob } from "./memory-retrospective-job.js";
|
|
71
|
+
import { sweepOrphanMemoryRetrospectiveConversations } from "./memory-retrospective-startup-cleanup.js";
|
|
70
72
|
import { QdrantCircuitOpenError } from "./qdrant-circuit-breaker.js";
|
|
71
73
|
import {
|
|
72
74
|
memoryV2ActivationRecomputeJob,
|
|
@@ -78,6 +80,25 @@ import { memoryV2SweepJob } from "./v2/sweep-job.js";
|
|
|
78
80
|
|
|
79
81
|
const log = getLogger("memory-jobs-worker");
|
|
80
82
|
|
|
83
|
+
/**
|
|
84
|
+
* V1 job types that read or write the v1 Qdrant collection via
|
|
85
|
+
* `getQdrantClient()`. When `memory.v2.enabled` is true, the v1 client is
|
|
86
|
+
* intentionally left uninitialized in `lifecycle.ts`, so these handlers would
|
|
87
|
+
* throw `BackendUnavailableError` and accumulate as a deferred backlog. Stale
|
|
88
|
+
* rows from indexer.ts and other unguarded enqueue sites must short-circuit
|
|
89
|
+
* here for the same reason `graph_extract` does below.
|
|
90
|
+
*/
|
|
91
|
+
const V1_QDRANT_JOB_TYPES = new Set<MemoryJobType>([
|
|
92
|
+
"embed_segment",
|
|
93
|
+
"embed_summary",
|
|
94
|
+
"embed_media",
|
|
95
|
+
"embed_attachment",
|
|
96
|
+
"embed_graph_node",
|
|
97
|
+
"embed_pkb_file",
|
|
98
|
+
"rebuild_index",
|
|
99
|
+
"delete_qdrant_vectors",
|
|
100
|
+
]);
|
|
101
|
+
|
|
81
102
|
/**
|
|
82
103
|
* Job types whose handlers have been removed. Existing rows may still sit in
|
|
83
104
|
* the database — the worker completes them silently instead of throwing.
|
|
@@ -111,6 +132,19 @@ export function startMemoryJobsWorker(): MemoryJobsWorker {
|
|
|
111
132
|
log.info({ recovered }, "Recovered stale running memory jobs");
|
|
112
133
|
}
|
|
113
134
|
|
|
135
|
+
// After running-job recovery (so legitimate in-flight retries aren't
|
|
136
|
+
// swept), clean up orphan memory-retrospective background conversations
|
|
137
|
+
// left behind by daemon crashes mid-job. Best-effort — never block worker
|
|
138
|
+
// startup on cleanup failures.
|
|
139
|
+
try {
|
|
140
|
+
sweepOrphanMemoryRetrospectiveConversations();
|
|
141
|
+
} catch (err) {
|
|
142
|
+
log.warn(
|
|
143
|
+
{ err },
|
|
144
|
+
"Memory-retrospective startup cleanup failed; continuing worker startup",
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
|
|
114
148
|
let stopped = false;
|
|
115
149
|
let tickRunning = false;
|
|
116
150
|
let timer: ReturnType<typeof setTimeout>;
|
|
@@ -124,16 +158,24 @@ export function startMemoryJobsWorker(): MemoryJobsWorker {
|
|
|
124
158
|
enableScheduledCleanup: true,
|
|
125
159
|
});
|
|
126
160
|
if (processed > 0) {
|
|
127
|
-
|
|
161
|
+
// Per-tick claim budget equals the lane caps, so when a tick
|
|
162
|
+
// processed work the next tick must run immediately to drain any
|
|
163
|
+
// remaining backlog. Holding the 1.5s floor between ticks would cap
|
|
164
|
+
// sustained throughput at lane-cap jobs per 1.5s and starve large
|
|
165
|
+
// backlogs of short jobs.
|
|
166
|
+
currentIntervalMs = 0;
|
|
128
167
|
} else {
|
|
129
168
|
currentIntervalMs = Math.min(
|
|
130
|
-
currentIntervalMs * 2,
|
|
169
|
+
Math.max(currentIntervalMs * 2, POLL_INTERVAL_MIN_MS),
|
|
131
170
|
POLL_INTERVAL_MAX_MS,
|
|
132
171
|
);
|
|
133
172
|
}
|
|
134
173
|
} catch (err) {
|
|
135
174
|
log.error({ err }, "Memory worker tick failed");
|
|
136
|
-
currentIntervalMs = Math.min(
|
|
175
|
+
currentIntervalMs = Math.min(
|
|
176
|
+
Math.max(currentIntervalMs * 2, POLL_INTERVAL_MIN_MS),
|
|
177
|
+
POLL_INTERVAL_MAX_MS,
|
|
178
|
+
);
|
|
137
179
|
} finally {
|
|
138
180
|
tickRunning = false;
|
|
139
181
|
}
|
|
@@ -462,6 +504,9 @@ async function processJob(
|
|
|
462
504
|
job: MemoryJob,
|
|
463
505
|
config: AssistantConfig,
|
|
464
506
|
): Promise<void> {
|
|
507
|
+
if (config.memory.v2.enabled && V1_QDRANT_JOB_TYPES.has(job.type)) {
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
465
510
|
switch (job.type) {
|
|
466
511
|
case "embed_segment":
|
|
467
512
|
await embedSegmentJob(job, config);
|
|
@@ -479,6 +524,12 @@ async function processJob(
|
|
|
479
524
|
pruneOldTraceEventsJob(job, config);
|
|
480
525
|
return;
|
|
481
526
|
case "build_conversation_summary":
|
|
527
|
+
// Stale rows enqueued before v2 was enabled must not consume the
|
|
528
|
+
// `conversationSummarization` LLM budget — v2 readers do not consume
|
|
529
|
+
// `memorySummaries`, mirroring the `graph_extract` gate below.
|
|
530
|
+
if (config.memory.v2.enabled) {
|
|
531
|
+
return;
|
|
532
|
+
}
|
|
482
533
|
await buildConversationSummaryJob(job, config);
|
|
483
534
|
return;
|
|
484
535
|
case "backfill":
|
|
@@ -555,6 +606,9 @@ async function processJob(
|
|
|
555
606
|
case "memory_v2_activation_recompute":
|
|
556
607
|
await memoryV2ActivationRecomputeJob(job, config);
|
|
557
608
|
return;
|
|
609
|
+
case "memory_retrospective":
|
|
610
|
+
await memoryRetrospectiveJob(job, config);
|
|
611
|
+
return;
|
|
558
612
|
|
|
559
613
|
default: {
|
|
560
614
|
const rawType = (job as { type: string }).type;
|