@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
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory v2 — router prompt template.
|
|
3
|
+
*
|
|
4
|
+
* The router runs once per assistant turn and decides which concept pages (if
|
|
5
|
+
* any) should be injected on top of the always-on essentials/threads/recent
|
|
6
|
+
* block. The body lives here (under `prompts/`) so it is reviewable on its
|
|
7
|
+
* own, mirroring the convention established in `sweep.ts`.
|
|
8
|
+
*
|
|
9
|
+
* Three placeholders are substituted at runtime:
|
|
10
|
+
*
|
|
11
|
+
* - `{{ASSISTANT_NAME}}` — assistant display name (from IDENTITY.md when
|
|
12
|
+
* available, else the neutral fallback "the assistant").
|
|
13
|
+
* - `{{USER_NAME}}` — guardian display name (from the guardian persona when
|
|
14
|
+
* available, else "the user").
|
|
15
|
+
* - `{{PAGE_INDEX}}` — pre-rendered page index. Each line has the shape
|
|
16
|
+
* `[id] slug — summary (edges: a, b, c)` where edges are numeric IDs into
|
|
17
|
+
* the same list. The caller renders this so the prompt module stays
|
|
18
|
+
* stateless.
|
|
19
|
+
*
|
|
20
|
+
* Operators may replace the bundled body via
|
|
21
|
+
* `memory.v2.router.router_prompt_path` and {@link resolveRouterPrompt} — the
|
|
22
|
+
* same placeholder substitution applies to overrides.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
import { lstatSync, readFileSync } from "node:fs";
|
|
26
|
+
import { homedir } from "node:os";
|
|
27
|
+
import { isAbsolute, join } from "node:path";
|
|
28
|
+
|
|
29
|
+
import { getLogger } from "../../../util/logger.js";
|
|
30
|
+
|
|
31
|
+
const log = getLogger("memory-v2-router-prompt");
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Hard upper bound on the override file size. The bundled prompt is well
|
|
35
|
+
* under 4 KiB; 1 MiB is generous-enough for any reasonable hand-edit while
|
|
36
|
+
* still preventing pathological inputs from being slurped into memory on
|
|
37
|
+
* every router call.
|
|
38
|
+
*/
|
|
39
|
+
const MAX_PROMPT_BYTES = 1 * 1024 * 1024;
|
|
40
|
+
|
|
41
|
+
/** Sentinel substituted with the assistant's display name at runtime. */
|
|
42
|
+
const ASSISTANT_NAME_PLACEHOLDER = "{{ASSISTANT_NAME}}";
|
|
43
|
+
|
|
44
|
+
/** Sentinel substituted with the guardian's display name at runtime. */
|
|
45
|
+
const USER_NAME_PLACEHOLDER = "{{USER_NAME}}";
|
|
46
|
+
|
|
47
|
+
/** Sentinel substituted with the rendered page index block at runtime. */
|
|
48
|
+
const PAGE_INDEX_PLACEHOLDER = "{{PAGE_INDEX}}";
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Router prompt — picks at most a handful of concept pages to inject for the
|
|
52
|
+
* next assistant turn. The model emits a `select_pages_to_inject` tool call
|
|
53
|
+
* with a `page_ids` array; the runtime parses the response via the tool
|
|
54
|
+
* definition declared in the router job module.
|
|
55
|
+
*
|
|
56
|
+
* Recent message context and `<now>` / `<already_injected_ids>` blocks are
|
|
57
|
+
* appended at the call site so we don't inadvertently expand `{{` inside
|
|
58
|
+
* dynamic content.
|
|
59
|
+
*/
|
|
60
|
+
const ROUTER_PROMPT = `You are a background helper for ${ASSISTANT_NAME_PLACEHOLDER}. Your job is to route memory pages for the next assistant turn between ${ASSISTANT_NAME_PLACEHOLDER} and ${USER_NAME_PLACEHOLDER}.
|
|
61
|
+
|
|
62
|
+
You will be shown the recent conversation, a \`<now>\` marker for the current time, an \`<already_injected_ids>\` block listing pages picked on the previous turn, and a \`# Concept Page Index\` listing every routable page on this workspace.
|
|
63
|
+
|
|
64
|
+
Pick the concept pages whose contents would help ${ASSISTANT_NAME_PLACEHOLDER} respond well on this turn. Lean toward inclusion when in doubt — missing a relevant page is a worse error than surfacing a few unused ones, because the assistant can ignore extras but can't summon context that wasn't loaded. Abstain (return an empty list) only when nothing in the index plausibly bears on the turn.
|
|
65
|
+
|
|
66
|
+
Index format. Each line of the index has the shape:
|
|
67
|
+
|
|
68
|
+
[id] slug — summary (edges: a, b, c)
|
|
69
|
+
|
|
70
|
+
\`id\` is a small integer used to refer to this page. \`edges\` are numeric IDs into the same list, pointing at related pages; you may follow them when one page strongly implies another.
|
|
71
|
+
|
|
72
|
+
Already-injected pages. Pages whose IDs appear in \`<already_injected_ids>\` were picked on the previous turn. Do not pick them again unless ${ASSISTANT_NAME_PLACEHOLDER} should re-anchor on that material — e.g., the topic genuinely returns after drifting away. Routine continuity does not require re-picking; the prior turn's pages are already in the assistant's working context.
|
|
73
|
+
|
|
74
|
+
Time. Bias toward pages that match the current state implied by \`<now>\` and the active conversational threads (what is happening today, what was just decided, who is being discussed). Stale pages with no bearing on the live conversation should be skipped even if their summaries look superficially relevant.
|
|
75
|
+
|
|
76
|
+
Emit your selection by calling \`select_pages_to_inject\` with the chosen \`page_ids\`. Return an empty array to abstain.
|
|
77
|
+
|
|
78
|
+
# Concept Page Index
|
|
79
|
+
|
|
80
|
+
${PAGE_INDEX_PLACEHOLDER}`;
|
|
81
|
+
|
|
82
|
+
interface RenderRouterPromptOpts {
|
|
83
|
+
assistantName: string | null;
|
|
84
|
+
userName: string | null;
|
|
85
|
+
pageIndexBlock: string;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Resolve `ROUTER_PROMPT` with assistant name, user name, and the rendered
|
|
90
|
+
* page index substituted in. Falls back to neutral defaults so the prompt
|
|
91
|
+
* still produces well-formed English when either name is unavailable on this
|
|
92
|
+
* workspace. The page index is substituted verbatim — callers are responsible
|
|
93
|
+
* for trimming/formatting it.
|
|
94
|
+
*/
|
|
95
|
+
export function renderRouterPrompt(opts: RenderRouterPromptOpts): string {
|
|
96
|
+
return substitutePlaceholders(ROUTER_PROMPT, opts);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/**
|
|
100
|
+
* Load the router prompt template, optionally overridden from the file
|
|
101
|
+
* referenced by `memory.v2.router.router_prompt_path`, then substitute the
|
|
102
|
+
* standard placeholders. Path-resolution rules mirror the consolidation
|
|
103
|
+
* prompt override: absolute paths used as-is, leading `~/` expanded to home,
|
|
104
|
+
* relative paths resolved under `workspaceDir`.
|
|
105
|
+
*
|
|
106
|
+
* Failure handling is intentionally permissive — missing file, read error,
|
|
107
|
+
* oversized file, or empty/whitespace-only body all log a warning and fall
|
|
108
|
+
* back to the bundled prompt. Router selection must never break because of
|
|
109
|
+
* a bad override.
|
|
110
|
+
*/
|
|
111
|
+
export function resolveRouterPrompt(
|
|
112
|
+
overridePath: string | null,
|
|
113
|
+
workspaceDir: string,
|
|
114
|
+
opts: RenderRouterPromptOpts,
|
|
115
|
+
): string {
|
|
116
|
+
if (overridePath === null) return renderRouterPrompt(opts);
|
|
117
|
+
|
|
118
|
+
const resolvedPath = resolveOverridePath(overridePath, workspaceDir);
|
|
119
|
+
let contents: string;
|
|
120
|
+
try {
|
|
121
|
+
const stat = lstatSync(resolvedPath);
|
|
122
|
+
if (!stat.isFile()) {
|
|
123
|
+
log.warn(
|
|
124
|
+
{
|
|
125
|
+
configuredPath: overridePath,
|
|
126
|
+
resolvedPath,
|
|
127
|
+
reason: "not_regular_file",
|
|
128
|
+
fallback: "bundled",
|
|
129
|
+
},
|
|
130
|
+
"router prompt override is not a regular file; using bundled prompt",
|
|
131
|
+
);
|
|
132
|
+
return renderRouterPrompt(opts);
|
|
133
|
+
}
|
|
134
|
+
if (stat.size > MAX_PROMPT_BYTES) {
|
|
135
|
+
log.warn(
|
|
136
|
+
{
|
|
137
|
+
configuredPath: overridePath,
|
|
138
|
+
resolvedPath,
|
|
139
|
+
size: stat.size,
|
|
140
|
+
limit: MAX_PROMPT_BYTES,
|
|
141
|
+
reason: "oversized_override",
|
|
142
|
+
fallback: "bundled",
|
|
143
|
+
},
|
|
144
|
+
"router prompt override exceeds size limit; using bundled prompt",
|
|
145
|
+
);
|
|
146
|
+
return renderRouterPrompt(opts);
|
|
147
|
+
}
|
|
148
|
+
contents = readFileSync(resolvedPath, "utf-8");
|
|
149
|
+
} catch (err) {
|
|
150
|
+
const code = (err as NodeJS.ErrnoException).code;
|
|
151
|
+
log.warn(
|
|
152
|
+
{ configuredPath: overridePath, resolvedPath, code, fallback: "bundled" },
|
|
153
|
+
"router prompt override unreadable; using bundled prompt",
|
|
154
|
+
);
|
|
155
|
+
return renderRouterPrompt(opts);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (contents.trim().length === 0) {
|
|
159
|
+
log.warn(
|
|
160
|
+
{
|
|
161
|
+
configuredPath: overridePath,
|
|
162
|
+
resolvedPath,
|
|
163
|
+
reason: "empty_override",
|
|
164
|
+
fallback: "bundled",
|
|
165
|
+
},
|
|
166
|
+
"router prompt override is empty; using bundled prompt",
|
|
167
|
+
);
|
|
168
|
+
return renderRouterPrompt(opts);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return substitutePlaceholders(contents, opts);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
function substitutePlaceholders(
|
|
175
|
+
template: string,
|
|
176
|
+
opts: RenderRouterPromptOpts,
|
|
177
|
+
): string {
|
|
178
|
+
const assistant = opts.assistantName?.trim() || "the assistant";
|
|
179
|
+
const user = opts.userName?.trim() || "the user";
|
|
180
|
+
return template
|
|
181
|
+
.replaceAll(ASSISTANT_NAME_PLACEHOLDER, () => assistant)
|
|
182
|
+
.replaceAll(USER_NAME_PLACEHOLDER, () => user)
|
|
183
|
+
.replaceAll(PAGE_INDEX_PLACEHOLDER, () => opts.pageIndexBlock);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
function resolveOverridePath(
|
|
187
|
+
overridePath: string,
|
|
188
|
+
workspaceDir: string,
|
|
189
|
+
): string {
|
|
190
|
+
if (overridePath.startsWith("~/")) {
|
|
191
|
+
return join(homedir(), overridePath.slice(2));
|
|
192
|
+
}
|
|
193
|
+
if (isAbsolute(overridePath)) return overridePath;
|
|
194
|
+
return join(workspaceDir, overridePath);
|
|
195
|
+
}
|
|
@@ -51,6 +51,6 @@ export function renderSweepPrompt(opts: {
|
|
|
51
51
|
const user = opts.userName?.trim() || "the user";
|
|
52
52
|
return SWEEP_PROMPT.replaceAll(
|
|
53
53
|
ASSISTANT_NAME_PLACEHOLDER,
|
|
54
|
-
assistant,
|
|
55
|
-
).replaceAll(USER_NAME_PLACEHOLDER, user);
|
|
54
|
+
() => assistant,
|
|
55
|
+
).replaceAll(USER_NAME_PLACEHOLDER, () => user);
|
|
56
56
|
}
|
package/src/memory/v2/qdrant.ts
CHANGED
|
@@ -18,11 +18,16 @@
|
|
|
18
18
|
// fusion using `dense_weight` / `sparse_weight` from `config.memory.v2`,
|
|
19
19
|
// which RRF fusion would discard.
|
|
20
20
|
|
|
21
|
+
import { existsSync } from "node:fs";
|
|
22
|
+
import { mkdir, unlink, writeFile } from "node:fs/promises";
|
|
23
|
+
import { dirname, join } from "node:path";
|
|
24
|
+
|
|
21
25
|
import { QdrantClient as QdrantRestClient } from "@qdrant/js-client-rest";
|
|
22
26
|
import { v5 as uuidv5 } from "uuid";
|
|
23
27
|
|
|
24
28
|
import { getConfig } from "../../config/loader.js";
|
|
25
29
|
import { getLogger } from "../../util/logger.js";
|
|
30
|
+
import { getDataDir } from "../../util/platform.js";
|
|
26
31
|
import type { SparseEmbedding } from "../embedding-types.js";
|
|
27
32
|
import { resolveQdrantUrl } from "../qdrant-client.js";
|
|
28
33
|
|
|
@@ -86,6 +91,49 @@ let _collectionReadyPromise: Promise<{ migrated: boolean }> | null = null;
|
|
|
86
91
|
const REQUIRED_DENSE_VECTORS = ["dense", "summary_dense"] as const;
|
|
87
92
|
const REQUIRED_SPARSE_VECTORS = ["sparse", "summary_sparse"] as const;
|
|
88
93
|
|
|
94
|
+
/**
|
|
95
|
+
* Marker file written before the destructive collection-recreate path runs,
|
|
96
|
+
* cleared by the lifecycle hook once the reembed job has been enqueued.
|
|
97
|
+
*
|
|
98
|
+
* The sentinel exists to close a narrow data-loss window in
|
|
99
|
+
* `ensureConceptPageCollectionOnce`: a transient Qdrant failure between
|
|
100
|
+
* `deleteCollection` and `createCollection` would otherwise lose the
|
|
101
|
+
* "needs reembed" signal — `migrated` is reinitialized on the next call,
|
|
102
|
+
* any subsequent caller (e.g. an upsert) recreates the collection empty,
|
|
103
|
+
* and the lifecycle hook never enqueues the backfill. By persisting the
|
|
104
|
+
* intent on disk *before* delete, the signal survives crashes and
|
|
105
|
+
* intra-process retries: every later `ensureConceptPageCollection` call
|
|
106
|
+
* returns `migrated: true` until the lifecycle hook enqueues the reembed
|
|
107
|
+
* and clears the sentinel.
|
|
108
|
+
*/
|
|
109
|
+
const REEMBED_SENTINEL_FILENAME = ".memory-v2-reembed-required";
|
|
110
|
+
|
|
111
|
+
function reembedSentinelPath(): string {
|
|
112
|
+
return join(getDataDir(), REEMBED_SENTINEL_FILENAME);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function reembedSentinelExists(): boolean {
|
|
116
|
+
return existsSync(reembedSentinelPath());
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
async function writeReembedSentinel(): Promise<void> {
|
|
120
|
+
const path = reembedSentinelPath();
|
|
121
|
+
await mkdir(dirname(path), { recursive: true });
|
|
122
|
+
await writeFile(path, "");
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Remove the reembed sentinel after the lifecycle hook has enqueued the
|
|
127
|
+
* `memory_v2_reembed` job. Idempotent — missing-file is not an error.
|
|
128
|
+
*/
|
|
129
|
+
export async function clearReembedSentinel(): Promise<void> {
|
|
130
|
+
try {
|
|
131
|
+
await unlink(reembedSentinelPath());
|
|
132
|
+
} catch (err) {
|
|
133
|
+
if ((err as NodeJS.ErrnoException).code !== "ENOENT") throw err;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
89
137
|
/** Lazily create a Qdrant REST client bound to the resolved URL. */
|
|
90
138
|
function getClient(): QdrantRestClient {
|
|
91
139
|
if (_client) return _client;
|
|
@@ -127,7 +175,11 @@ async function ensureConceptPageCollectionOnce(): Promise<{
|
|
|
127
175
|
const vectorSize = config.memory.qdrant.vectorSize;
|
|
128
176
|
const onDisk = config.memory.qdrant.onDisk;
|
|
129
177
|
|
|
130
|
-
|
|
178
|
+
// A leftover sentinel means a prior call deleted the collection but never
|
|
179
|
+
// got to enqueue the reembed (e.g. createCollection threw, or the process
|
|
180
|
+
// died mid-rebuild). Carry that signal forward until the lifecycle hook
|
|
181
|
+
// clears it.
|
|
182
|
+
let migrated = reembedSentinelExists();
|
|
131
183
|
|
|
132
184
|
try {
|
|
133
185
|
const exists = await client.collectionExists(MEMORY_V2_COLLECTION);
|
|
@@ -148,6 +200,9 @@ async function ensureConceptPageCollectionOnce(): Promise<{
|
|
|
148
200
|
|
|
149
201
|
const missing = missingNamedVectors(info);
|
|
150
202
|
if (missing.length === 0) {
|
|
203
|
+
// Long-lived installs may predate the `kind` payload index; ensure
|
|
204
|
+
// every required index exists before declaring the collection ready.
|
|
205
|
+
await ensurePayloadIndexes();
|
|
151
206
|
_collectionReady = true;
|
|
152
207
|
return { migrated: false };
|
|
153
208
|
}
|
|
@@ -156,6 +211,10 @@ async function ensureConceptPageCollectionOnce(): Promise<{
|
|
|
156
211
|
{ collection: MEMORY_V2_COLLECTION, missingNamedVectors: missing },
|
|
157
212
|
"Memory v2 concept-page collection schema drift detected — deleting and recreating; embeddings will be regenerated by background reembed",
|
|
158
213
|
);
|
|
214
|
+
// Persist the reembed intent BEFORE the destructive delete so a crash
|
|
215
|
+
// (or transient createCollection failure) between delete and recreate
|
|
216
|
+
// still triggers reembed on the next ensure call.
|
|
217
|
+
await writeReembedSentinel();
|
|
159
218
|
await client.deleteCollection(MEMORY_V2_COLLECTION);
|
|
160
219
|
migrated = true;
|
|
161
220
|
// Fall through to creation below.
|
|
@@ -215,17 +274,62 @@ async function ensureConceptPageCollectionOnce(): Promise<{
|
|
|
215
274
|
throw err;
|
|
216
275
|
}
|
|
217
276
|
|
|
218
|
-
|
|
219
|
-
// so upserts and slug-restricted queries don't pay a per-call indexing cost.
|
|
220
|
-
await client.createPayloadIndex(MEMORY_V2_COLLECTION, {
|
|
221
|
-
field_name: "slug",
|
|
222
|
-
field_schema: "keyword",
|
|
223
|
-
});
|
|
277
|
+
await ensurePayloadIndexes();
|
|
224
278
|
|
|
225
279
|
_collectionReady = true;
|
|
226
280
|
return { migrated };
|
|
227
281
|
}
|
|
228
282
|
|
|
283
|
+
/**
|
|
284
|
+
* Idempotently create the payload indexes the collection's query and
|
|
285
|
+
* filter paths rely on:
|
|
286
|
+
*
|
|
287
|
+
* - `slug` (keyword): every slug-restricted query and prefix scan filters on it.
|
|
288
|
+
* - `kind` (keyword): the skill-backfill scroll filters with `is_empty` on
|
|
289
|
+
* `kind`. Strict-mode Qdrant deployments reject filters on unindexed
|
|
290
|
+
* payload fields, so without this the backfill consistently fails and
|
|
291
|
+
* legacy skill points remain untagged.
|
|
292
|
+
*
|
|
293
|
+
* Same-schema `createPayloadIndex` calls are idempotent server-side in
|
|
294
|
+
* Qdrant (200 OK), so the only "already exists" failures we expect are
|
|
295
|
+
* narrow races where a concurrent caller created the same index a moment
|
|
296
|
+
* earlier. Those are benign and swallowed. Every other failure — strict-mode
|
|
297
|
+
* rejection, index-limit, transient network blip — must propagate so the
|
|
298
|
+
* caller does not latch readiness on a collection whose `slug`/`kind`
|
|
299
|
+
* filters will keep rejecting queries until the next daemon restart.
|
|
300
|
+
*/
|
|
301
|
+
async function ensurePayloadIndexes(): Promise<void> {
|
|
302
|
+
const client = getClient();
|
|
303
|
+
const indexes = [
|
|
304
|
+
{ field_name: "slug", field_schema: "keyword" as const },
|
|
305
|
+
{ field_name: "kind", field_schema: "keyword" as const },
|
|
306
|
+
];
|
|
307
|
+
// Parallel so one "already exists" race on a single index doesn't stall
|
|
308
|
+
// the other create round-trip. v1's `qdrant-client.ts` uses the same
|
|
309
|
+
// Promise.all shape.
|
|
310
|
+
await Promise.all(
|
|
311
|
+
indexes.map(async (index) => {
|
|
312
|
+
try {
|
|
313
|
+
await client.createPayloadIndex(MEMORY_V2_COLLECTION, index);
|
|
314
|
+
} catch (err) {
|
|
315
|
+
if (isPayloadIndexAlreadyExists(err)) return;
|
|
316
|
+
throw err;
|
|
317
|
+
}
|
|
318
|
+
}),
|
|
319
|
+
);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* True when a `createPayloadIndex` error indicates the index already
|
|
324
|
+
* exists with matching parameters — the only failure shape it is safe to
|
|
325
|
+
* swallow. Qdrant returns 4xx with messages like
|
|
326
|
+
* `"Wrong input: Payload field 'kind' already exists ..."`.
|
|
327
|
+
*/
|
|
328
|
+
function isPayloadIndexAlreadyExists(err: unknown): boolean {
|
|
329
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
330
|
+
return /already exists/i.test(msg);
|
|
331
|
+
}
|
|
332
|
+
|
|
229
333
|
/**
|
|
230
334
|
* Return the names of required named vectors absent from the collection's
|
|
231
335
|
* current schema. An empty array means the collection is fully migrated.
|
|
@@ -279,10 +383,17 @@ export async function upsertConceptPageEmbedding(params: {
|
|
|
279
383
|
sparse: SparseEmbedding;
|
|
280
384
|
summary?: { dense: number[]; sparse: SparseEmbedding };
|
|
281
385
|
updatedAt: number;
|
|
386
|
+
/**
|
|
387
|
+
* Optional payload discriminator. Used to distinguish skill-seeded points
|
|
388
|
+
* (`kind: "skill"`) from user-authored concept pages so namespace pruning
|
|
389
|
+
* via {@link pruneSlugsWithPrefixExcept} can scope deletes to a single kind.
|
|
390
|
+
* Omitted for plain concept pages.
|
|
391
|
+
*/
|
|
392
|
+
kind?: string;
|
|
282
393
|
}): Promise<void> {
|
|
283
394
|
await ensureConceptPageCollection();
|
|
284
395
|
|
|
285
|
-
const { slug, dense, sparse, summary, updatedAt } = params;
|
|
396
|
+
const { slug, dense, sparse, summary, updatedAt, kind } = params;
|
|
286
397
|
const client = getClient();
|
|
287
398
|
const pointId = pointIdForSlug(slug);
|
|
288
399
|
|
|
@@ -296,6 +407,9 @@ export async function upsertConceptPageEmbedding(params: {
|
|
|
296
407
|
vector.summary_sparse = summary.sparse;
|
|
297
408
|
}
|
|
298
409
|
|
|
410
|
+
const payload: Record<string, unknown> = { slug, updated_at: updatedAt };
|
|
411
|
+
if (kind !== undefined) payload.kind = kind;
|
|
412
|
+
|
|
299
413
|
const upsertOnce = () =>
|
|
300
414
|
client.upsert(MEMORY_V2_COLLECTION, {
|
|
301
415
|
wait: true,
|
|
@@ -303,7 +417,7 @@ export async function upsertConceptPageEmbedding(params: {
|
|
|
303
417
|
{
|
|
304
418
|
id: pointId,
|
|
305
419
|
vector,
|
|
306
|
-
payload
|
|
420
|
+
payload,
|
|
307
421
|
},
|
|
308
422
|
],
|
|
309
423
|
});
|
|
@@ -352,17 +466,28 @@ export async function deleteConceptPageEmbedding(slug: string): Promise<void> {
|
|
|
352
466
|
* since skills now share the concept-page collection rather than living in a
|
|
353
467
|
* dedicated one.
|
|
354
468
|
*
|
|
469
|
+
* `kind` scopes pruning to a payload discriminator: only points whose
|
|
470
|
+
* `payload.kind` matches are eligible for deletion. This is critical because
|
|
471
|
+
* `validateSlug` permits user-authored concept pages slugged like
|
|
472
|
+
* `skills/foo`; without a kind filter they would collide with the skill
|
|
473
|
+
* namespace and be repeatedly pruned every seed run. The companion
|
|
474
|
+
* {@link backfillKindOnPointsWithPrefix} preserves this invariant for legacy
|
|
475
|
+
* untagged rows by tagging only suffixes the caller knows are skills —
|
|
476
|
+
* user-authored `skills/<slug>` rows stay kindless and outside this prune.
|
|
477
|
+
*
|
|
355
478
|
* Idempotent: when the live `<prefix>*` slugs already match `activeSuffixes`,
|
|
356
479
|
* the function performs a single scroll and no deletes.
|
|
357
480
|
*/
|
|
358
481
|
export async function pruneSlugsWithPrefixExcept(
|
|
359
482
|
prefix: string,
|
|
360
483
|
activeSuffixes: readonly string[],
|
|
484
|
+
options: { kind?: string } = {},
|
|
361
485
|
): Promise<void> {
|
|
362
486
|
await ensureConceptPageCollection();
|
|
363
487
|
|
|
364
488
|
const client = getClient();
|
|
365
489
|
const activeSet = new Set(activeSuffixes);
|
|
490
|
+
const requiredKind = options.kind;
|
|
366
491
|
|
|
367
492
|
const doPrune = async (): Promise<void> => {
|
|
368
493
|
const stalePointIds: Array<string | number> = [];
|
|
@@ -377,9 +502,15 @@ export async function pruneSlugsWithPrefixExcept(
|
|
|
377
502
|
...(offset !== undefined ? { offset } : {}),
|
|
378
503
|
});
|
|
379
504
|
for (const point of result.points) {
|
|
380
|
-
const
|
|
505
|
+
const payload = point.payload as {
|
|
506
|
+
slug?: unknown;
|
|
507
|
+
kind?: unknown;
|
|
508
|
+
} | null;
|
|
509
|
+
const slug = payload?.slug;
|
|
381
510
|
if (typeof slug !== "string") continue;
|
|
382
511
|
if (!slug.startsWith(prefix)) continue;
|
|
512
|
+
if (requiredKind !== undefined && payload?.kind !== requiredKind)
|
|
513
|
+
continue;
|
|
383
514
|
const suffix = slug.slice(prefix.length);
|
|
384
515
|
if (!activeSet.has(suffix)) {
|
|
385
516
|
stalePointIds.push(point.id);
|
|
@@ -411,6 +542,83 @@ export async function pruneSlugsWithPrefixExcept(
|
|
|
411
542
|
}
|
|
412
543
|
}
|
|
413
544
|
|
|
545
|
+
/**
|
|
546
|
+
* Set `payload.kind` on every point whose slug starts with `prefix`, whose
|
|
547
|
+
* suffix is in `allowedSuffixes`, and is currently missing the `kind`
|
|
548
|
+
* discriminator. Used to tag legacy rows that predate the kind field so the
|
|
549
|
+
* kind-scoped {@link pruneSlugsWithPrefixExcept} no longer leaves them as
|
|
550
|
+
* orphans.
|
|
551
|
+
*
|
|
552
|
+
* `allowedSuffixes` is required because `validateSlug` permits user-authored
|
|
553
|
+
* concept pages slugged like `skills/my-notes` — those rows also lack `kind`
|
|
554
|
+
* and would otherwise be tagged here and then deleted by the kind-scoped
|
|
555
|
+
* prune. Callers must pass the closed set of legitimate suffixes (e.g. the
|
|
556
|
+
* union of installed + remote-catalog skill IDs) so user pages stay untagged.
|
|
557
|
+
*
|
|
558
|
+
* The "missing kind" predicate is pushed to Qdrant via `is_empty`, so once
|
|
559
|
+
* every legacy row has been tagged the scroll returns the bounded set of
|
|
560
|
+
* other kindless concept pages without ever touching the already-tagged
|
|
561
|
+
* rows. Idempotent across retries: a row tagged by an earlier partial run
|
|
562
|
+
* no longer matches the filter and is silently skipped.
|
|
563
|
+
*/
|
|
564
|
+
export async function backfillKindOnPointsWithPrefix(
|
|
565
|
+
prefix: string,
|
|
566
|
+
kind: string,
|
|
567
|
+
allowedSuffixes: ReadonlySet<string>,
|
|
568
|
+
): Promise<number> {
|
|
569
|
+
if (allowedSuffixes.size === 0) return 0;
|
|
570
|
+
await ensureConceptPageCollection();
|
|
571
|
+
|
|
572
|
+
const client = getClient();
|
|
573
|
+
|
|
574
|
+
const doBackfill = async (): Promise<number> => {
|
|
575
|
+
const pointIds: Array<string | number> = [];
|
|
576
|
+
let offset: string | number | undefined = undefined;
|
|
577
|
+
const maxIterations = 10_000;
|
|
578
|
+
const batchSize = 256;
|
|
579
|
+
for (let i = 0; i < maxIterations; i++) {
|
|
580
|
+
const result = await client.scroll(MEMORY_V2_COLLECTION, {
|
|
581
|
+
limit: batchSize,
|
|
582
|
+
with_payload: true,
|
|
583
|
+
with_vector: false,
|
|
584
|
+
filter: { must: [{ is_empty: { key: "kind" } }] },
|
|
585
|
+
...(offset !== undefined ? { offset } : {}),
|
|
586
|
+
});
|
|
587
|
+
for (const point of result.points) {
|
|
588
|
+
const slug = (point.payload as { slug?: unknown } | null)?.slug;
|
|
589
|
+
if (typeof slug !== "string") continue;
|
|
590
|
+
if (!slug.startsWith(prefix)) continue;
|
|
591
|
+
const suffix = slug.slice(prefix.length);
|
|
592
|
+
if (!allowedSuffixes.has(suffix)) continue;
|
|
593
|
+
pointIds.push(point.id);
|
|
594
|
+
}
|
|
595
|
+
const next = result.next_page_offset;
|
|
596
|
+
if (next == null) break;
|
|
597
|
+
offset = typeof next === "string" ? next : (next as number);
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
if (pointIds.length === 0) return 0;
|
|
601
|
+
|
|
602
|
+
await client.setPayload(MEMORY_V2_COLLECTION, {
|
|
603
|
+
payload: { kind },
|
|
604
|
+
points: pointIds,
|
|
605
|
+
wait: true,
|
|
606
|
+
});
|
|
607
|
+
return pointIds.length;
|
|
608
|
+
};
|
|
609
|
+
|
|
610
|
+
try {
|
|
611
|
+
return await doBackfill();
|
|
612
|
+
} catch (err) {
|
|
613
|
+
if (isCollectionMissing(err)) {
|
|
614
|
+
_collectionReady = false;
|
|
615
|
+
await ensureConceptPageCollection();
|
|
616
|
+
return await doBackfill();
|
|
617
|
+
}
|
|
618
|
+
throw err;
|
|
619
|
+
}
|
|
620
|
+
}
|
|
621
|
+
|
|
414
622
|
/**
|
|
415
623
|
* Approximate count of points in the v2 concept-page collection. Used by the
|
|
416
624
|
* daemon-startup rebuild hook to detect "collection exists but empty" — the
|
|
@@ -435,6 +643,22 @@ export async function countConceptPagePoints(): Promise<number> {
|
|
|
435
643
|
}
|
|
436
644
|
}
|
|
437
645
|
|
|
646
|
+
/**
|
|
647
|
+
* Probe whether the v2 concept-page collection currently exists in Qdrant
|
|
648
|
+
* **without** triggering creation. Read-only diagnostics use this to avoid
|
|
649
|
+
* the side effect of bootstrapping storage just by inspecting it.
|
|
650
|
+
*/
|
|
651
|
+
export async function conceptPageCollectionExists(): Promise<boolean> {
|
|
652
|
+
const client = getClient();
|
|
653
|
+
try {
|
|
654
|
+
const result = await client.collectionExists(MEMORY_V2_COLLECTION);
|
|
655
|
+
return result.exists;
|
|
656
|
+
} catch (err) {
|
|
657
|
+
if (isCollectionMissing(err)) return false;
|
|
658
|
+
throw err;
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
|
|
438
662
|
/**
|
|
439
663
|
* Best-effort delete of the legacy `memory_v2_skills` Qdrant collection. Skill
|
|
440
664
|
* embeddings now live alongside concept pages in `memory_v2_concept_pages`
|
|
@@ -579,89 +803,6 @@ export async function hybridQueryConceptPages(
|
|
|
579
803
|
return Array.from(merged.values());
|
|
580
804
|
}
|
|
581
805
|
|
|
582
|
-
/**
|
|
583
|
-
* Page through the v2 concept-page collection and return up to `maxSamples`
|
|
584
|
-
* stored dense vectors. Used by the anisotropy-fit pipeline to compute a
|
|
585
|
-
* corpus mean + top-k principal components without re-embedding every page.
|
|
586
|
-
*
|
|
587
|
-
* Sparse vectors are skipped — anisotropy is a dense-embedding phenomenon, and
|
|
588
|
-
* pulling the sparse side would just inflate the response. Payload is also
|
|
589
|
-
* skipped because the fit doesn't need slug identity.
|
|
590
|
-
*
|
|
591
|
-
* Returns an empty array when the collection is empty or missing. Caller
|
|
592
|
-
* decides what to do (typically: surface a "no vectors to fit" error).
|
|
593
|
-
*/
|
|
594
|
-
export async function sampleConceptPageDenseVectors(
|
|
595
|
-
maxSamples: number,
|
|
596
|
-
): Promise<number[][]> {
|
|
597
|
-
if (maxSamples <= 0) return [];
|
|
598
|
-
await ensureConceptPageCollection();
|
|
599
|
-
|
|
600
|
-
const client = getClient();
|
|
601
|
-
const out: number[][] = [];
|
|
602
|
-
let offset: string | number | undefined = undefined;
|
|
603
|
-
// Same pagination guard pattern as the rest of the file — bounds the loop
|
|
604
|
-
// even if Qdrant somehow keeps handing back a non-null offset.
|
|
605
|
-
const maxIterations = 10_000;
|
|
606
|
-
const batchSize = Math.min(256, maxSamples);
|
|
607
|
-
|
|
608
|
-
for (let i = 0; i < maxIterations; i++) {
|
|
609
|
-
if (out.length >= maxSamples) break;
|
|
610
|
-
const remaining = maxSamples - out.length;
|
|
611
|
-
let result;
|
|
612
|
-
try {
|
|
613
|
-
result = await client.scroll(MEMORY_V2_COLLECTION, {
|
|
614
|
-
limit: Math.min(batchSize, remaining),
|
|
615
|
-
with_payload: false,
|
|
616
|
-
// Fetch only the dense named vector — sparse is irrelevant for
|
|
617
|
-
// anisotropy correction.
|
|
618
|
-
with_vector: ["dense"],
|
|
619
|
-
...(offset !== undefined ? { offset } : {}),
|
|
620
|
-
});
|
|
621
|
-
} catch (err) {
|
|
622
|
-
if (isCollectionMissing(err)) {
|
|
623
|
-
_collectionReady = false;
|
|
624
|
-
return out;
|
|
625
|
-
}
|
|
626
|
-
throw err;
|
|
627
|
-
}
|
|
628
|
-
|
|
629
|
-
for (const point of result.points) {
|
|
630
|
-
const v = extractDenseVector(point.vector);
|
|
631
|
-
if (v) out.push(v);
|
|
632
|
-
if (out.length >= maxSamples) break;
|
|
633
|
-
}
|
|
634
|
-
|
|
635
|
-
const next = result.next_page_offset;
|
|
636
|
-
if (next == null) break;
|
|
637
|
-
offset = typeof next === "string" ? next : (next as number);
|
|
638
|
-
}
|
|
639
|
-
|
|
640
|
-
return out;
|
|
641
|
-
}
|
|
642
|
-
|
|
643
|
-
/**
|
|
644
|
-
* Pull the `dense` named-vector payload out of a Qdrant point. Defensively
|
|
645
|
-
* handles both the named-vector shape (`{ dense: [...] }`) and the legacy
|
|
646
|
-
* unnamed-vector shape (`number[]`) so older collection layouts don't trip
|
|
647
|
-
* the sampler. Returns `null` for shapes we don't recognise.
|
|
648
|
-
*/
|
|
649
|
-
function extractDenseVector(vector: unknown): number[] | null {
|
|
650
|
-
if (Array.isArray(vector)) {
|
|
651
|
-
if (vector.every((n) => typeof n === "number")) {
|
|
652
|
-
return vector as number[];
|
|
653
|
-
}
|
|
654
|
-
return null;
|
|
655
|
-
}
|
|
656
|
-
if (vector && typeof vector === "object") {
|
|
657
|
-
const dense = (vector as { dense?: unknown }).dense;
|
|
658
|
-
if (Array.isArray(dense) && dense.every((n) => typeof n === "number")) {
|
|
659
|
-
return dense as number[];
|
|
660
|
-
}
|
|
661
|
-
}
|
|
662
|
-
return null;
|
|
663
|
-
}
|
|
664
|
-
|
|
665
806
|
/**
|
|
666
807
|
* Detect "collection not found" errors so callers can reset readiness and
|
|
667
808
|
* retry after an external deletion (e.g. workspace reset).
|