@vellumai/assistant 0.7.3 → 0.8.1
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 +29 -28
- package/Dockerfile +6 -4
- package/README.md +2 -2
- package/__tests__/permissions/gateway-threshold-reader.test.ts +236 -9
- package/bun.lock +3 -0
- package/docker-entrypoint.sh +16 -0
- 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/knip.json +3 -1
- package/node_modules/@vellumai/ipc-server-utils/bun.lock +24 -0
- package/node_modules/@vellumai/ipc-server-utils/package.json +18 -0
- package/node_modules/@vellumai/ipc-server-utils/src/index.ts +6 -0
- package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.test.ts +430 -0
- package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.ts +221 -0
- package/node_modules/@vellumai/ipc-server-utils/tsconfig.json +20 -0
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -1
- package/openapi.yaml +4126 -959
- package/package.json +5 -1
- package/scripts/generate-openapi.ts +52 -4
- package/scripts/sync-llm-catalog.ts +165 -0
- package/scripts/sync-web-search-catalog.ts +107 -0
- package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +169 -0
- package/src/__tests__/agent-loop-override-profile.test.ts +26 -1
- package/src/__tests__/annotate-risk-options.test.ts +291 -0
- package/src/__tests__/anthropic-provider.test.ts +92 -2
- package/src/__tests__/app-control-flow.test.ts +7 -0
- package/src/__tests__/approval-cascade.test.ts +8 -16
- package/src/__tests__/approval-routes-http.test.ts +6 -0
- package/src/__tests__/assistant-events-sse-shed.test.ts +232 -0
- package/src/__tests__/auto-analysis-end-to-end.test.ts +12 -25
- 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__/call-constants.test.ts +10 -1
- package/src/__tests__/call-controller.test.ts +127 -0
- 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-policy.test.ts +12 -0
- package/src/__tests__/checker.test.ts +89 -0
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +88 -30
- 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__/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 +345 -8
- package/src/__tests__/config-schema-cmd.test.ts +63 -29
- package/src/__tests__/config-schema.test.ts +14 -3
- package/src/__tests__/config-set-platform-guard.test.ts +75 -152
- package/src/__tests__/config-set-route.test.ts +198 -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 +42 -16
- package/src/__tests__/context-search-fanout.test.ts +20 -157
- package/src/__tests__/context-search-memory-source.test.ts +3 -26
- package/src/__tests__/context-search-memory-v2-source.test.ts +3 -3
- package/src/__tests__/context-search-types.test.ts +7 -2
- package/src/__tests__/context-window-manager.test.ts +389 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +1 -6
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -1
- package/src/__tests__/conversation-agent-loop.test.ts +3 -3
- package/src/__tests__/conversation-confirmation-signals.test.ts +5 -13
- package/src/__tests__/conversation-crud-inference-profile.test.ts +100 -0
- package/src/__tests__/conversation-error.test.ts +38 -0
- package/src/__tests__/conversation-fork-crud.test.ts +241 -1
- package/src/__tests__/conversation-inference-profile-route.test.ts +14 -14
- package/src/__tests__/conversation-init.benchmark.test.ts +2 -1
- package/src/__tests__/conversation-lifecycle.test.ts +124 -0
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +100 -1
- package/src/__tests__/conversation-process-callsite.test.ts +22 -7
- package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -6
- package/src/__tests__/conversation-runtime-assembly.test.ts +19 -10
- package/src/__tests__/conversation-slash-commands.test.ts +194 -2
- package/src/__tests__/conversation-slash-unknown.test.ts +1 -6
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +170 -9
- package/src/__tests__/conversation-surfaces-app-control.test.ts +323 -3
- package/src/__tests__/conversation-surfaces-data-persist.test.ts +73 -1
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +59 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +1 -7
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -7
- package/src/__tests__/credential-security-invariants.test.ts +5 -6
- 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__/external-plugin-loader.test.ts +458 -0
- package/src/__tests__/filing-service.test.ts +25 -22
- package/src/__tests__/fixtures/mock-chrome-extension.ts +5 -0
- package/src/__tests__/gateway-only-guard.test.ts +0 -1
- package/src/__tests__/graph-extraction-event-date.test.ts +34 -0
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +10 -34
- package/src/__tests__/heartbeat-disk-pressure.test.ts +21 -8
- package/src/__tests__/heartbeat-service.test.ts +50 -233
- package/src/__tests__/history-repair.test.ts +89 -0
- package/src/__tests__/host-app-control-proxy.test.ts +109 -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__/inference-no-mode-boot-e2e.test.ts +246 -0
- package/src/__tests__/inference-profile-reaper.test.ts +154 -0
- package/src/__tests__/inference-profile-session-handler.test.ts +398 -0
- package/src/__tests__/inference-profile-session-ipc.test.ts +236 -0
- package/src/__tests__/injector-chain.test.ts +24 -16
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +10 -7
- package/src/__tests__/inline-skill-load-permissions.test.ts +6 -1
- package/src/__tests__/install-skill-routing.test.ts +2 -2
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +169 -67
- package/src/__tests__/llm-callsite-catalog.test.ts +20 -1
- package/src/__tests__/llm-catalog-parity.test.ts +146 -0
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +188 -0
- package/src/__tests__/llm-request-log-source-factory.test.ts +124 -0
- package/src/__tests__/llm-resolver.test.ts +46 -0
- package/src/__tests__/managed-profile-guard.test.ts +131 -2
- 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__/memory-jobs-worker-lanes.test.ts +18 -11
- package/src/__tests__/message-complete-display-id.test.ts +175 -0
- package/src/__tests__/notification-decision-fallback.test.ts +91 -0
- package/src/__tests__/notification-decision-strategy.test.ts +22 -0
- package/src/__tests__/notification-platform-adapter.test.ts +229 -0
- package/src/__tests__/oauth-cli.test.ts +38 -1888
- package/src/__tests__/oauth-commands-routes.test.ts +711 -0
- package/src/__tests__/oauth-connect-routes.test.ts +174 -11
- package/src/__tests__/oauth-providers-routes.test.ts +14 -10
- package/src/__tests__/openai-responses-cutover-guard.test.ts +33 -12
- package/src/__tests__/openai-responses-provider.test.ts +17 -0
- package/src/__tests__/plugin-bootstrap.test.ts +31 -2
- package/src/__tests__/plugin-route-contribution.test.ts +31 -3
- package/src/__tests__/plugin-tool-contribution.test.ts +31 -3
- package/src/__tests__/plugin-types.test.ts +13 -11
- package/src/__tests__/process-message-background-slack.test.ts +46 -0
- package/src/__tests__/profile-entry-status.test.ts +43 -0
- package/src/__tests__/provider-managed-proxy-integration.test.ts +12 -4
- 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 +164 -2
- package/src/__tests__/retry-thinking-tool-choice.test.ts +15 -0
- package/src/__tests__/schedule-retry.test.ts +56 -4
- package/src/__tests__/schedule-routes.test.ts +104 -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 +161 -5
- package/src/__tests__/scheduler-wake.test.ts +0 -63
- package/src/__tests__/secret-allowlist.test.ts +1 -0
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +7 -5
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +7 -5
- package/src/__tests__/secret-response-routing.test.ts +7 -5
- package/src/__tests__/secret-routes-managed-proxy.test.ts +12 -4
- package/src/__tests__/server-history-render.test.ts +82 -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-include-graph.test.ts +31 -0
- package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
- package/src/__tests__/skill-load-tool.test.ts +42 -16
- package/src/__tests__/skills.test.ts +39 -0
- package/src/__tests__/subagent-call-site-routing.test.ts +78 -16
- package/src/__tests__/suggestion-routes.test.ts +3 -3
- package/src/__tests__/sync-message-contract.test.ts +63 -0
- package/src/__tests__/task-scheduler.test.ts +88 -23
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -42
- package/src/__tests__/tool-executor.test.ts +155 -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 +145 -0
- package/src/__tests__/vercel-config.test.ts +168 -0
- package/src/__tests__/voice-session-bridge.test.ts +3 -0
- package/src/__tests__/web-search-catalog-parity.test.ts +86 -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 +58 -0
- package/src/__tests__/workspace-migration-069-seed-onboarding-threads.test.ts +153 -0
- package/src/__tests__/workspace-migration-071-remove-safe-storage-release-note.test.ts +206 -0
- package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +191 -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-safe-storage-limits-release.test.ts +15 -27
- package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +3 -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/loop.ts +11 -0
- package/src/approvals/guardian-decision-primitive.ts +0 -13
- package/src/approvals/guardian-request-resolvers.ts +19 -102
- package/src/calls/call-constants.ts +5 -8
- package/src/calls/call-controller.ts +130 -67
- package/src/calls/relay-server.ts +42 -1
- package/src/calls/relay-setup-router.ts +36 -0
- package/src/calls/types.ts +1 -0
- package/src/calls/voice-session-bridge.ts +24 -5
- package/src/channels/config.ts +14 -1
- package/src/channels/types.ts +1 -0
- package/src/cli/AGENTS.md +164 -4
- package/src/cli/__tests__/notifications.test.ts +54 -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 +593 -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__/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 +414 -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 +346 -436
- package/src/cli/commands/credential-execution.ts +9 -6
- package/src/cli/commands/credentials.ts +456 -736
- 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 +163 -517
- package/src/cli/commands/notifications.ts +33 -7
- package/src/cli/commands/oauth/apps.ts +292 -261
- package/src/cli/commands/oauth/connect.ts +182 -345
- 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/routes.ts +153 -336
- 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/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__/register-command.test.ts +85 -0
- package/src/cli/lib/daemon-credential-client.ts +4 -5
- 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/program.ts +2 -4
- 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 +1 -3
- package/src/config/bundled-skills/app-control/TOOLS.json +32 -0
- 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/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-tool-registry.ts +0 -2
- package/src/config/feature-flag-registry.json +17 -17
- package/src/config/llm-resolver.ts +16 -1
- package/src/config/loader.ts +148 -33
- package/src/config/raw-config-utils.ts +2 -30
- package/src/config/schema.ts +4 -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/llm-request-logs.ts +57 -0
- package/src/config/schemas/llm.ts +52 -2
- package/src/config/schemas/memory-retrospective.ts +48 -0
- package/src/config/schemas/memory-v2.ts +33 -2
- package/src/config/schemas/memory.ts +4 -0
- package/src/config/schemas/services.ts +15 -12
- package/src/config/seed-inference-profiles.ts +195 -134
- package/src/contacts/contact-store.ts +0 -61
- package/src/context/window-manager.ts +191 -5
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +111 -0
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +109 -4
- package/src/daemon/__tests__/daemon-skill-host.test.ts +10 -4
- package/src/daemon/approval-generators.ts +23 -29
- package/src/daemon/config-watcher.ts +2 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +56 -0
- package/src/daemon/conversation-agent-loop.ts +140 -107
- package/src/daemon/conversation-error.ts +21 -0
- package/src/daemon/conversation-lifecycle.ts +68 -13
- package/src/daemon/conversation-process.ts +36 -19
- package/src/daemon/conversation-runtime-assembly.ts +14 -5
- package/src/daemon/conversation-slash.ts +175 -23
- package/src/daemon/conversation-store.ts +17 -10
- package/src/daemon/conversation-surfaces.ts +92 -26
- package/src/daemon/conversation-tool-setup.ts +33 -19
- package/src/daemon/conversation.ts +49 -10
- package/src/daemon/external-plugins-bootstrap.ts +18 -8
- package/src/daemon/guardian-action-generators.ts +7 -22
- package/src/daemon/handlers/config-model.ts +8 -126
- package/src/daemon/handlers/config-slack-channel.ts +10 -7
- package/src/daemon/handlers/config-vercel.ts +3 -1
- package/src/daemon/handlers/shared.ts +26 -0
- package/src/daemon/handlers/skills.ts +84 -5
- package/src/daemon/history-repair.ts +33 -6
- package/src/daemon/host-app-control-proxy.ts +44 -19
- package/src/daemon/host-bash-proxy.ts +85 -158
- package/src/daemon/host-browser-proxy.ts +97 -36
- package/src/daemon/host-cu-proxy.ts +1 -1
- package/src/daemon/host-file-proxy.ts +1 -1
- package/src/daemon/host-proxy-base.ts +13 -1
- package/src/daemon/host-proxy-preactivation.ts +25 -1
- package/src/daemon/host-transfer-proxy.ts +2 -2
- package/src/daemon/identity-helpers.ts +19 -0
- package/src/daemon/lifecycle.ts +128 -114
- package/src/daemon/meet-host-supervisor.ts +15 -15
- package/src/daemon/memory-v2-startup.ts +62 -14
- package/src/daemon/message-protocol.ts +6 -0
- package/src/daemon/message-types/bookmarks.ts +18 -0
- package/src/daemon/message-types/conversations.ts +12 -9
- package/src/daemon/message-types/messages.ts +28 -2
- package/src/daemon/message-types/sync.ts +60 -0
- package/src/daemon/pkb-reminder-builder.test.ts +54 -13
- package/src/daemon/pkb-reminder-builder.ts +21 -7
- package/src/daemon/process-message.ts +56 -23
- package/src/daemon/server.ts +23 -18
- package/src/daemon/shutdown-handlers.ts +0 -2
- 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 +35 -1
- package/src/export/transcript-formatter.ts +61 -2
- package/src/filing/filing-service.ts +42 -56
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +359 -0
- package/src/heartbeat/heartbeat-run-store.ts +2 -1
- package/src/heartbeat/heartbeat-service.ts +149 -128
- package/src/home/__tests__/feed-types.test.ts +63 -131
- 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 +19 -73
- package/src/home/feed-writer.ts +25 -156
- package/src/home/post-connect-feed.ts +1 -3
- 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 +148 -42
- 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/ipc/skill-server.ts +99 -42
- package/src/live-voice/__tests__/live-voice-session-manager.test.ts +46 -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/memory/__tests__/bookmark-crud.test.ts +258 -0
- package/src/memory/__tests__/bookmark-schema.test.ts +181 -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-schedule.test.ts +10 -57
- 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 +213 -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/bookmark-crud.ts +179 -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 +18 -6
- package/src/memory/context-search/sources/memory-v2.ts +40 -31
- package/src/memory/context-search/sources/memory.ts +9 -2
- package/src/memory/context-search/sources/workspace.ts +13 -10
- package/src/memory/context-search/types.ts +1 -1
- package/src/memory/conversation-bootstrap.ts +11 -0
- package/src/memory/conversation-crud.ts +312 -10
- package/src/memory/conversation-queries.ts +9 -5
- package/src/memory/conversation-title-service.ts +1 -0
- package/src/memory/conversation-types.ts +16 -0
- package/src/memory/db-init.ts +14 -0
- package/src/memory/embedding-backend.ts +2 -1
- package/src/memory/embedding-runtime-manager.ts +1 -2
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +104 -61
- package/src/memory/graph/__tests__/handle-remember-v2.test.ts +11 -26
- package/src/memory/graph/__tests__/remember-description.test.ts +55 -0
- package/src/memory/graph/conversation-graph-memory.ts +108 -14
- package/src/memory/graph/extraction.ts +4 -0
- package/src/memory/graph/graph-memory-state-store.ts +16 -3
- package/src/memory/graph/graph-search.test.ts +6 -5
- package/src/memory/graph/graph-search.ts +3 -4
- package/src/memory/graph/retriever.test.ts +12 -7
- package/src/memory/graph/retriever.ts +4 -5
- package/src/memory/graph/tool-handlers.ts +20 -11
- package/src/memory/graph/tools.ts +48 -9
- package/src/memory/indexer.ts +18 -2
- package/src/memory/jobs/__tests__/embed-concept-page.test.ts +120 -6
- package/src/memory/jobs/embed-concept-page.ts +261 -89
- package/src/memory/jobs-store.ts +51 -1
- package/src/memory/jobs-worker.ts +60 -7
- package/src/memory/llm-request-log-source-clickhouse.ts +317 -0
- package/src/memory/llm-request-log-source-local.ts +26 -0
- package/src/memory/llm-request-log-source.ts +97 -0
- package/src/memory/llm-request-log-store.ts +1 -1
- 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 +108 -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/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 +70 -1
- package/src/memory/migrations/229-delete-private-conversations.ts +12 -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/__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 +7 -0
- package/src/memory/pkb/pkb-search.test.ts +6 -5
- package/src/memory/pkb/pkb-search.ts +4 -5
- package/src/memory/published-pages-store.ts +16 -0
- package/src/memory/qdrant-client.ts +3 -0
- package/src/memory/schema/bookmarks.ts +38 -0
- package/src/memory/schema/conversations.ts +2 -0
- package/src/memory/schema/index.ts +2 -0
- package/src/memory/schema/inference.ts +29 -0
- package/src/memory/schema/memory-core.ts +9 -0
- package/src/memory/search/semantic.ts +5 -9
- 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 +46 -9
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +38 -21
- package/src/memory/v2/__tests__/consolidation-job.test.ts +140 -163
- 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 +768 -33
- package/src/memory/v2/__tests__/migration.test.ts +7 -3
- package/src/memory/v2/__tests__/page-index.test.ts +277 -0
- package/src/memory/v2/__tests__/page-store.test.ts +14 -1
- package/src/memory/v2/__tests__/prompts-router.test.ts +257 -0
- package/src/memory/v2/__tests__/qdrant.test.ts +382 -9
- package/src/memory/v2/__tests__/reranker.test.ts +4 -4
- package/src/memory/v2/__tests__/router.test.ts +516 -0
- package/src/memory/v2/__tests__/sim.test.ts +163 -8
- package/src/memory/v2/__tests__/skill-store.test.ts +58 -3
- package/src/memory/v2/__tests__/static-context.test.ts +8 -35
- package/src/memory/v2/__tests__/sweep-job.test.ts +114 -33
- 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 +92 -86
- package/src/memory/v2/frontmatter-sweep.ts +91 -0
- package/src/memory/v2/injection.ts +466 -115
- package/src/memory/v2/migration.ts +117 -20
- package/src/memory/v2/page-index.ts +191 -0
- package/src/memory/v2/page-store.ts +42 -0
- package/src/memory/v2/prompts/consolidation.ts +14 -7
- package/src/memory/v2/prompts/router.ts +192 -0
- package/src/memory/v2/qdrant.ts +307 -133
- package/src/memory/v2/reranker.ts +14 -7
- package/src/memory/v2/router.ts +322 -0
- package/src/memory/v2/sim.ts +88 -34
- package/src/memory/v2/skill-store.ts +118 -29
- package/src/memory/v2/static-context.ts +20 -17
- package/src/memory/v2/sweep-job.ts +127 -102
- package/src/memory/v2/types.ts +16 -5
- package/src/memory/validation.ts +13 -0
- 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 +2 -2
- package/src/notifications/copy-composer.ts +61 -12
- package/src/notifications/decision-engine.ts +46 -0
- package/src/notifications/destination-resolver.ts +21 -0
- package/src/notifications/emit-signal.ts +28 -1
- package/src/notifications/home-feed-side-effect.ts +111 -0
- package/src/notifications/signal.ts +5 -0
- package/src/permissions/checker.ts +12 -0
- package/src/permissions/gateway-threshold-reader.ts +116 -8
- package/src/permissions/ipc-risk-types.ts +2 -0
- package/src/permissions/prompter.ts +86 -96
- package/src/permissions/secret-prompter.ts +31 -31
- package/src/plugin-api/index.ts +13 -0
- package/src/plugin-api/package.json +12 -0
- package/src/plugin-api/types.ts +62 -0
- package/src/plugins/defaults/injectors.ts +20 -5
- package/src/plugins/external-plugin-loader.ts +294 -0
- package/src/plugins/types.ts +46 -30
- package/src/plugins/user-loader.ts +64 -41
- package/src/proactive-artifact/job.test.ts +63 -8
- package/src/proactive-artifact/job.ts +20 -2
- package/src/proactive-artifact/message-copy.ts +18 -1
- 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 +105 -0
- package/src/prompts/system-prompt.ts +22 -1
- package/src/prompts/templates/SOUL.md +13 -28
- 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 +288 -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 +95 -26
- package/src/providers/call-site-routing.ts +94 -16
- package/src/providers/connection-resolution.ts +163 -0
- package/src/providers/inference/__tests__/connections-status-label.test.ts +250 -0
- package/src/providers/inference/adapter-factory.ts +173 -0
- package/src/providers/inference/auth.ts +112 -0
- package/src/providers/inference/backfill.ts +196 -0
- package/src/providers/inference/connections.ts +356 -0
- package/src/providers/inference/resolve-auth.ts +65 -0
- package/src/providers/model-catalog.ts +104 -6
- package/src/providers/openai/responses-provider.ts +4 -2
- 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 +143 -159
- package/src/providers/retry.ts +18 -10
- package/src/providers/search-provider-catalog.ts +121 -0
- package/src/runtime/AGENTS.md +18 -5
- 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 +35 -6
- package/src/runtime/assistant-event-hub.ts +3 -85
- package/src/runtime/auth/route-policy.ts +304 -8
- package/src/runtime/auth/same-actor.ts +2 -0
- package/src/runtime/background-job-runner.ts +339 -0
- package/src/runtime/btw-sidechain.ts +1 -0
- package/src/runtime/channel-approvals.ts +3 -2
- package/src/runtime/guardian-reply-router.ts +0 -10
- package/src/runtime/http-router.ts +36 -1
- package/src/runtime/http-server.ts +31 -5
- package/src/runtime/http-types.ts +2 -0
- package/src/runtime/middleware/__tests__/request-logger.test.ts +162 -0
- package/src/runtime/middleware/request-logger.ts +62 -1
- package/src/runtime/pending-interactions.ts +19 -15
- 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 +251 -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 +315 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +189 -0
- 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 +147 -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 +6 -2
- package/src/runtime/routes/acp-routes.ts +10 -8
- package/src/runtime/routes/app-management-routes.ts +228 -3
- package/src/runtime/routes/approval-routes.ts +7 -21
- 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 +154 -0
- package/src/runtime/routes/channel-verification-routes.ts +2 -1
- package/src/runtime/routes/consolidation-routes.ts +8 -9
- package/src/runtime/routes/contact-routes.ts +0 -160
- package/src/runtime/routes/conversation-cli-routes.ts +192 -0
- package/src/runtime/routes/conversation-management-routes.ts +30 -43
- package/src/runtime/routes/conversation-query-routes.ts +373 -82
- package/src/runtime/routes/conversation-routes.ts +31 -10
- package/src/runtime/routes/conversations-import-routes.ts +229 -0
- package/src/runtime/routes/credential-routes.ts +540 -0
- package/src/runtime/routes/debug-bash-routes.ts +2 -0
- package/src/runtime/routes/debug-routes.ts +2 -2
- package/src/runtime/routes/document-pdf-renderer.ts +5 -1
- 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/filing-routes.ts +2 -3
- 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-stages/background-dispatch.test.ts +137 -1
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +87 -7
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +156 -0
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +22 -7
- package/src/runtime/routes/index.ts +36 -0
- package/src/runtime/routes/inference-profile-session-handler.ts +312 -0
- package/src/runtime/routes/inference-profile-session-reaper.ts +98 -0
- package/src/runtime/routes/inference-profile-session-routes.ts +146 -0
- package/src/runtime/routes/inference-provider-connection-routes.ts +317 -0
- package/src/runtime/routes/inference-send-routes.ts +115 -0
- package/src/runtime/routes/integrations/twilio.ts +1 -0
- package/src/runtime/routes/mcp-auth-routes.ts +283 -9
- package/src/runtime/routes/memory-item-routes.test.ts +3 -9
- package/src/runtime/routes/memory-item-routes.ts +5 -6
- package/src/runtime/routes/memory-v2-routes.ts +105 -404
- package/src/runtime/routes/notification-routes.ts +2 -0
- package/src/runtime/routes/oauth-apps.ts +112 -7
- package/src/runtime/routes/oauth-commands-routes.ts +1007 -0
- package/src/runtime/routes/oauth-connect-routes.ts +67 -5
- 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/schedule-routes.ts +82 -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/surface-action-routes.ts +43 -7
- package/src/runtime/routes/tts-routes.ts +67 -0
- 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/sync/resource-sync-events.ts +25 -0
- package/src/runtime/sync/sync-publisher.test.ts +105 -0
- package/src/runtime/sync/sync-publisher.ts +21 -0
- package/src/schedule/scheduler.ts +200 -123
- package/src/security/__tests__/provider-key-env-fallback.test.ts +12 -6
- package/src/security/secret-patterns.ts +3 -0
- package/src/sequence/engine.ts +38 -40
- package/src/skills/include-graph.ts +35 -13
- package/src/subagent/manager.ts +20 -15
- package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +206 -0
- package/src/tools/browser/browser-execution.ts +15 -4
- 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/document/document-tool.ts +20 -0
- package/src/tools/executor.ts +18 -2
- package/src/tools/memory/register.test.ts +10 -8
- 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 +28 -5
- package/src/tools/skills/load.ts +24 -20
- package/src/tools/subagent/spawn.ts +3 -3
- package/src/tools/terminal/shell.ts +44 -0
- package/src/tools/tool-name-aliases.ts +19 -0
- package/src/tools/types.ts +19 -1
- package/src/usage/attribution.ts +3 -2
- package/src/util/pricing.ts +86 -160
- package/src/watcher/__tests__/engine.test.ts +301 -0
- package/src/watcher/constants.ts +7 -0
- package/src/watcher/engine.ts +90 -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 +28 -4
- package/src/workspace/migrations/067-release-notes-safe-storage-limits.ts +4 -62
- package/src/workspace/migrations/069-seed-onboarding-threads.ts +34 -0
- package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +31 -0
- package/src/workspace/migrations/071-remove-safe-storage-release-note.ts +111 -0
- package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +104 -0
- package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +93 -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/registry.ts +28 -0
- package/src/workspace/migrations/runner.ts +13 -2
- package/src/workspace/migrations/types.ts +13 -3
- package/src/workspace/provider-commit-message-generator.ts +3 -2
- package/src/__tests__/context-search-pkb-source.test.ts +0 -492
- 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 -1201
- 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/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 -477
- package/src/memory/graph/compaction.ts +0 -299
- /package/src/cli/{commands → lib}/cache-fs.ts +0 -0
|
@@ -136,7 +136,11 @@ class MockQdrantClient {
|
|
|
136
136
|
limit: params.limit,
|
|
137
137
|
filter: params.filter,
|
|
138
138
|
});
|
|
139
|
-
|
|
139
|
+
// Both `dense` and `summary_dense` consume from the dense queue (and
|
|
140
|
+
// similarly for sparse). The four-channel hybrid query fires them in
|
|
141
|
+
// order: body-dense, body-sparse, summary-dense, summary-sparse — so
|
|
142
|
+
// the queue order matches the call order.
|
|
143
|
+
const channel = params.using.endsWith("sparse") ? "sparse" : "dense";
|
|
140
144
|
return state.queryResponses[channel].shift() ?? { points: [] };
|
|
141
145
|
}
|
|
142
146
|
}
|
|
@@ -185,10 +189,18 @@ function configWithWeights(
|
|
|
185
189
|
/**
|
|
186
190
|
* Stage a single Qdrant response that maps each (slug, denseScore?, sparseScore?)
|
|
187
191
|
* tuple onto the dense or sparse channel, mirroring how `hybridQueryConceptPages`
|
|
188
|
-
* merges per-channel hits.
|
|
192
|
+
* merges per-channel hits. Optional `summaryDenseScore` / `summarySparseScore`
|
|
193
|
+
* stage the summary-side channels — pages without those entries fall through
|
|
194
|
+
* to body-only scoring at fusion time.
|
|
189
195
|
*/
|
|
190
196
|
function stageHybridResponse(
|
|
191
|
-
hits: Array<{
|
|
197
|
+
hits: Array<{
|
|
198
|
+
slug: string;
|
|
199
|
+
denseScore?: number;
|
|
200
|
+
sparseScore?: number;
|
|
201
|
+
summaryDenseScore?: number;
|
|
202
|
+
summarySparseScore?: number;
|
|
203
|
+
}>,
|
|
192
204
|
): void {
|
|
193
205
|
state.queryResponses.dense.push({
|
|
194
206
|
points: hits
|
|
@@ -200,6 +212,20 @@ function stageHybridResponse(
|
|
|
200
212
|
.filter((h) => h.sparseScore !== undefined)
|
|
201
213
|
.map((h) => ({ score: h.sparseScore, payload: { slug: h.slug } })),
|
|
202
214
|
});
|
|
215
|
+
// The four-channel hybrid query also fires `summary_dense` and
|
|
216
|
+
// `summary_sparse` queries against the same collection. Tests that don't
|
|
217
|
+
// care about summary scores leave those channels empty so the fallback
|
|
218
|
+
// (body-only) path runs.
|
|
219
|
+
state.queryResponses.dense.push({
|
|
220
|
+
points: hits
|
|
221
|
+
.filter((h) => h.summaryDenseScore !== undefined)
|
|
222
|
+
.map((h) => ({ score: h.summaryDenseScore, payload: { slug: h.slug } })),
|
|
223
|
+
});
|
|
224
|
+
state.queryResponses.sparse.push({
|
|
225
|
+
points: hits
|
|
226
|
+
.filter((h) => h.summarySparseScore !== undefined)
|
|
227
|
+
.map((h) => ({ score: h.summarySparseScore, payload: { slug: h.slug } })),
|
|
228
|
+
});
|
|
203
229
|
}
|
|
204
230
|
|
|
205
231
|
beforeEach(resetState);
|
|
@@ -407,7 +433,7 @@ describe("simBatch", () => {
|
|
|
407
433
|
|
|
408
434
|
const out = await simBatch("query", ["dense-only-page"], config);
|
|
409
435
|
|
|
410
|
-
// 0.7 * 0.5 + 0.3 * 0 = 0.35
|
|
436
|
+
// cosine 0.5 (positive, passes through); 0.7 * 0.5 + 0.3 * 0 = 0.35
|
|
411
437
|
expect(out.get("dense-only-page")).toBeCloseTo(0.35, 6);
|
|
412
438
|
});
|
|
413
439
|
|
|
@@ -449,6 +475,7 @@ describe("simBatch", () => {
|
|
|
449
475
|
|
|
450
476
|
const out = await simBatch("query", ["alice", "bob"], config);
|
|
451
477
|
|
|
478
|
+
// Positive cosines pass through unchanged.
|
|
452
479
|
// alice: 0.4 * 0.5 + 0.6 * 1.0 = 0.8
|
|
453
480
|
// bob: 0.4 * 0.25 + 0.6 * 0.5 = 0.4
|
|
454
481
|
expect(out.get("alice")).toBeCloseTo(0.8, 6);
|
|
@@ -468,15 +495,16 @@ describe("simBatch", () => {
|
|
|
468
495
|
expect(out.get("loud-page")).toBe(1);
|
|
469
496
|
});
|
|
470
497
|
|
|
471
|
-
test("forwards the candidate slugs as a Qdrant slug-IN filter", async () => {
|
|
498
|
+
test("forwards the candidate slugs as a Qdrant slug-IN filter on every channel", async () => {
|
|
472
499
|
const config = configWithWeights(0.7, 0.3);
|
|
473
500
|
stageHybridResponse([]);
|
|
474
501
|
|
|
475
502
|
await simBatch("query", ["alice", "bob", "carol"], config);
|
|
476
503
|
|
|
477
|
-
//
|
|
478
|
-
// filter and the same per-channel limit
|
|
479
|
-
|
|
504
|
+
// All four channels (body dense + sparse, summary dense + sparse) ran
|
|
505
|
+
// with the same slug-restriction filter and the same per-channel limit
|
|
506
|
+
// equal to the candidate count.
|
|
507
|
+
expect(state.queryCalls).toHaveLength(4);
|
|
480
508
|
for (const call of state.queryCalls) {
|
|
481
509
|
expect(call.limit).toBe(3);
|
|
482
510
|
expect(call.filter).toEqual({
|
|
@@ -496,6 +524,133 @@ describe("simBatch", () => {
|
|
|
496
524
|
expect(state.sparseCalls).toEqual(["hello world"]);
|
|
497
525
|
});
|
|
498
526
|
|
|
527
|
+
test("takes max(body, summary) per slug — summary higher than body wins", async () => {
|
|
528
|
+
// Body channels return a modest score; summary channels return a much
|
|
529
|
+
// higher score. The max collapses to the summary score.
|
|
530
|
+
const config = configWithWeights(1.0, 0.0);
|
|
531
|
+
stageHybridResponse([
|
|
532
|
+
{
|
|
533
|
+
slug: "alice",
|
|
534
|
+
denseScore: 0.3,
|
|
535
|
+
summaryDenseScore: 0.7,
|
|
536
|
+
},
|
|
537
|
+
]);
|
|
538
|
+
|
|
539
|
+
const out = await simBatch("query", ["alice"], config);
|
|
540
|
+
|
|
541
|
+
// Positive cosines pass through unchanged: max(0.3, 0.7) = 0.7.
|
|
542
|
+
expect(out.get("alice")).toBeCloseTo(0.7, 6);
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
test("takes max(body, summary) per slug — body higher than summary wins", async () => {
|
|
546
|
+
// Inverse case: body dominates, max stays at body.
|
|
547
|
+
const config = configWithWeights(1.0, 0.0);
|
|
548
|
+
stageHybridResponse([
|
|
549
|
+
{
|
|
550
|
+
slug: "alice",
|
|
551
|
+
denseScore: 0.9,
|
|
552
|
+
summaryDenseScore: 0.4,
|
|
553
|
+
},
|
|
554
|
+
]);
|
|
555
|
+
|
|
556
|
+
const out = await simBatch("query", ["alice"], config);
|
|
557
|
+
|
|
558
|
+
// Positive cosines pass through unchanged: max(0.9, 0.4) = 0.9.
|
|
559
|
+
expect(out.get("alice")).toBeCloseTo(0.9, 6);
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
test("falls back to body-only when the page has no summary embedding", async () => {
|
|
563
|
+
// Pages predating the summary field have no summary_dense/sparse vectors.
|
|
564
|
+
// Their summary channels return no hits — the max collapses to body.
|
|
565
|
+
const config = configWithWeights(1.0, 0.0);
|
|
566
|
+
stageHybridResponse([
|
|
567
|
+
{
|
|
568
|
+
slug: "legacy-page",
|
|
569
|
+
denseScore: 0.6,
|
|
570
|
+
// summaryDenseScore / summarySparseScore omitted
|
|
571
|
+
},
|
|
572
|
+
]);
|
|
573
|
+
|
|
574
|
+
const out = await simBatch("query", ["legacy-page"], config);
|
|
575
|
+
|
|
576
|
+
// Positive cosine 0.6 passes through unchanged.
|
|
577
|
+
expect(out.get("legacy-page")).toBeCloseTo(0.6, 6);
|
|
578
|
+
});
|
|
579
|
+
|
|
580
|
+
test("normalizes body and summary sparse channels independently", async () => {
|
|
581
|
+
// Summary sparse scores live on a different scale than body sparse —
|
|
582
|
+
// a small absolute summary-sparse value (1.5) on the only page that
|
|
583
|
+
// has summary signal still normalizes to 1.0 within the summary
|
|
584
|
+
// channel, so the summary-only fused score should win out.
|
|
585
|
+
const config = configWithWeights(0.0, 1.0);
|
|
586
|
+
stageHybridResponse([
|
|
587
|
+
{
|
|
588
|
+
slug: "alice",
|
|
589
|
+
denseScore: 0.0,
|
|
590
|
+
sparseScore: 100, // body sparse max in this batch
|
|
591
|
+
},
|
|
592
|
+
{
|
|
593
|
+
slug: "bob",
|
|
594
|
+
denseScore: 0.0,
|
|
595
|
+
sparseScore: 0.5, // body sparse normalized = 0.005
|
|
596
|
+
summaryDenseScore: 0.0,
|
|
597
|
+
summarySparseScore: 1.5, // summary sparse max in this batch
|
|
598
|
+
},
|
|
599
|
+
]);
|
|
600
|
+
|
|
601
|
+
const out = await simBatch("query", ["alice", "bob"], config);
|
|
602
|
+
|
|
603
|
+
// Alice has only body. Body sparse normalized to 1.0; sparse_weight=1.0 → 1.0.
|
|
604
|
+
expect(out.get("alice")).toBeCloseTo(1.0, 6);
|
|
605
|
+
// Bob's summary side normalizes its 1.5 (only sparse-bearing summary
|
|
606
|
+
// hit) — a single sparse-bearing hit is below the adaptive-spread
|
|
607
|
+
// floor, so the channel collapses to base weights and the lone
|
|
608
|
+
// sparseNormalized=1.0 hit yields a fused summary score of 1.0.
|
|
609
|
+
// Body side has only bob's tiny sparse=0.5 against the body batch max
|
|
610
|
+
// of 100 → ~0.005. The max picks the summary side.
|
|
611
|
+
expect(out.get("bob")).toBeCloseTo(1.0, 6);
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
test("dense-favored config keeps the dense-strong candidate above the sparse-strong one", async () => {
|
|
615
|
+
// Regression guard: an earlier fix mapped cosines into [0, 1] via
|
|
616
|
+
// `(cos + 1) / 2` before fusion, which halved every pairwise dense
|
|
617
|
+
// difference and silently shifted ranking toward sparse. With dense
|
|
618
|
+
// weighted higher than sparse, the dense-only hit must outrank the
|
|
619
|
+
// sparse-only hit even though sparse normalizes to 1.0.
|
|
620
|
+
const config = configWithWeights(0.7, 0.3);
|
|
621
|
+
stageHybridResponse([
|
|
622
|
+
{ slug: "dense-strong", denseScore: 0.5 /* sparseScore omitted */ },
|
|
623
|
+
{ slug: "sparse-strong", denseScore: 0.0, sparseScore: 1 },
|
|
624
|
+
]);
|
|
625
|
+
|
|
626
|
+
const out = await simBatch(
|
|
627
|
+
"query",
|
|
628
|
+
["dense-strong", "sparse-strong"],
|
|
629
|
+
config,
|
|
630
|
+
);
|
|
631
|
+
|
|
632
|
+
// dense-strong: 0.7 * max(0, 0.5) + 0.3 * 0 = 0.35
|
|
633
|
+
// sparse-strong: 0.7 * max(0, 0.0) + 0.3 * 1.0 = 0.30
|
|
634
|
+
expect(out.get("dense-strong")).toBeCloseTo(0.35, 6);
|
|
635
|
+
expect(out.get("sparse-strong")).toBeCloseTo(0.3, 6);
|
|
636
|
+
expect(out.get("dense-strong")!).toBeGreaterThan(out.get("sparse-strong")!);
|
|
637
|
+
});
|
|
638
|
+
|
|
639
|
+
test("negative cosine maps to a non-negative dense contribution", async () => {
|
|
640
|
+
// Qdrant cosine search returns scores in [-1, 1]. A near-zero or
|
|
641
|
+
// negative cosine must not yield a negative dense contribution that
|
|
642
|
+
// depresses the fused score below the sparse-only floor.
|
|
643
|
+
const config = configWithWeights(0.7, 0.3);
|
|
644
|
+
stageHybridResponse([
|
|
645
|
+
{ slug: "anti-match", denseScore: -1.0, sparseScore: 1 },
|
|
646
|
+
]);
|
|
647
|
+
|
|
648
|
+
const out = await simBatch("query", ["anti-match"], config);
|
|
649
|
+
|
|
650
|
+
// cosine -1 → clamped to 0; sparse-norm = 1.0; fused = 0.7*0 + 0.3*1 = 0.3.
|
|
651
|
+
expect(out.get("anti-match")).toBeCloseTo(0.3, 6);
|
|
652
|
+
});
|
|
653
|
+
|
|
499
654
|
test("returned scores are always in [0, 1] for arbitrary inputs", async () => {
|
|
500
655
|
const config = configWithWeights(0.7, 0.3);
|
|
501
656
|
stageHybridResponse([
|
|
@@ -39,11 +39,13 @@ interface UpsertCall {
|
|
|
39
39
|
dense: number[];
|
|
40
40
|
sparse: { indices: number[]; values: number[] };
|
|
41
41
|
updatedAt: number;
|
|
42
|
+
kind?: string;
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
interface PruneCall {
|
|
45
46
|
prefix: string;
|
|
46
47
|
activeSuffixes: readonly string[];
|
|
48
|
+
options?: { kind?: string };
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
interface TestState {
|
|
@@ -118,8 +120,9 @@ mock.module("../qdrant.js", () => ({
|
|
|
118
120
|
pruneSlugsWithPrefixExcept: async (
|
|
119
121
|
prefix: string,
|
|
120
122
|
activeSuffixes: readonly string[],
|
|
123
|
+
options?: { kind?: string },
|
|
121
124
|
) => {
|
|
122
|
-
state.pruneCalls.push({ prefix, activeSuffixes });
|
|
125
|
+
state.pruneCalls.push({ prefix, activeSuffixes, options });
|
|
123
126
|
},
|
|
124
127
|
}));
|
|
125
128
|
|
|
@@ -131,8 +134,12 @@ mock.module("../../../skills/catalog-cache.js", () => ({
|
|
|
131
134
|
}));
|
|
132
135
|
|
|
133
136
|
// Imported AFTER all mocks are wired so the module under test sees the stubs.
|
|
134
|
-
const {
|
|
135
|
-
|
|
137
|
+
const {
|
|
138
|
+
seedV2SkillEntries,
|
|
139
|
+
getSkillCapability,
|
|
140
|
+
listSkillEntries,
|
|
141
|
+
_resetSkillStoreForTests,
|
|
142
|
+
} = await import("../skill-store.js");
|
|
136
143
|
|
|
137
144
|
// ---------------------------------------------------------------------------
|
|
138
145
|
// Helpers
|
|
@@ -467,3 +474,51 @@ describe("getSkillCapability", () => {
|
|
|
467
474
|
expect(getSkillCapability("does-not-exist")).toBeNull();
|
|
468
475
|
});
|
|
469
476
|
});
|
|
477
|
+
|
|
478
|
+
describe("listSkillEntries", () => {
|
|
479
|
+
test("returns [] when the cache is empty (pre-seed)", () => {
|
|
480
|
+
expect(listSkillEntries()).toEqual([]);
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
test("returns entries sorted by id after seeding", async () => {
|
|
484
|
+
// Insert in non-sorted order to prove the sort happens on read.
|
|
485
|
+
const skillB = makeSummary({ id: "example-skill-b" });
|
|
486
|
+
const skillA = makeSummary({ id: "example-skill-a" });
|
|
487
|
+
state.catalog = [skillB, skillA];
|
|
488
|
+
state.resolved = [
|
|
489
|
+
{ summary: skillB, state: "enabled" },
|
|
490
|
+
{ summary: skillA, state: "enabled" },
|
|
491
|
+
];
|
|
492
|
+
state.embedReturn = [
|
|
493
|
+
[0.1, 0.2, 0.3],
|
|
494
|
+
[0.4, 0.5, 0.6],
|
|
495
|
+
];
|
|
496
|
+
|
|
497
|
+
await seedV2SkillEntries();
|
|
498
|
+
|
|
499
|
+
const list = listSkillEntries();
|
|
500
|
+
expect(list).toHaveLength(2);
|
|
501
|
+
expect(list.map((e) => e.id)).toEqual([
|
|
502
|
+
"example-skill-a",
|
|
503
|
+
"example-skill-b",
|
|
504
|
+
]);
|
|
505
|
+
});
|
|
506
|
+
|
|
507
|
+
test("mutating the returned array does not affect subsequent calls", async () => {
|
|
508
|
+
const skillA = makeSummary({ id: "example-skill-a" });
|
|
509
|
+
state.catalog = [skillA];
|
|
510
|
+
state.resolved = [{ summary: skillA, state: "enabled" }];
|
|
511
|
+
state.embedReturn = [[0.1, 0.2, 0.3]];
|
|
512
|
+
|
|
513
|
+
await seedV2SkillEntries();
|
|
514
|
+
|
|
515
|
+
const first = listSkillEntries();
|
|
516
|
+
expect(first).toHaveLength(1);
|
|
517
|
+
first.length = 0;
|
|
518
|
+
first.push({ id: "injected", content: "junk" });
|
|
519
|
+
|
|
520
|
+
const second = listSkillEntries();
|
|
521
|
+
expect(second).toHaveLength(1);
|
|
522
|
+
expect(second[0].id).toBe("example-skill-a");
|
|
523
|
+
});
|
|
524
|
+
});
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tests for `readMemoryV2StaticContent` — the loader that powers the
|
|
3
|
-
* `memory-v2-static` user-message auto-injection.
|
|
4
|
-
* lived in the deprecated `system-prompt-memory-v2.test.ts`:
|
|
5
|
-
* - Returns null when the v2 flag is off.
|
|
3
|
+
* `memory-v2-static` user-message auto-injection.
|
|
6
4
|
* - Returns null when `config.memory.v2.enabled` is off.
|
|
7
5
|
* - Reads the four files in canonical order and joins them under headings.
|
|
8
6
|
* - Skips empty / missing files.
|
|
@@ -47,9 +45,7 @@ mock.module("../../../config/loader.js", () => ({
|
|
|
47
45
|
setNestedValue: () => {},
|
|
48
46
|
}));
|
|
49
47
|
|
|
50
|
-
const {
|
|
51
|
-
await import("../../../config/assistant-feature-flags.js");
|
|
52
|
-
const { readMemoryV2StaticContent, shouldLoadMemoryV2Static } =
|
|
48
|
+
const { readMemoryV2StaticContent, shouldExposePersonalMemory } =
|
|
53
49
|
await import("../static-context.js");
|
|
54
50
|
|
|
55
51
|
const MEMORY_FILES = [
|
|
@@ -75,18 +71,10 @@ describe("readMemoryV2StaticContent", () => {
|
|
|
75
71
|
beforeEach(() => {
|
|
76
72
|
mkdirSync(TEST_DIR, { recursive: true });
|
|
77
73
|
configMemoryV2Enabled = true;
|
|
78
|
-
_setOverridesForTesting({ "memory-v2-enabled": true });
|
|
79
74
|
});
|
|
80
75
|
|
|
81
76
|
afterEach(() => {
|
|
82
77
|
cleanupMemoryDir();
|
|
83
|
-
_setOverridesForTesting({});
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
test("returns null when the feature flag is off", () => {
|
|
87
|
-
_setOverridesForTesting({ "memory-v2-enabled": false });
|
|
88
|
-
for (const file of MEMORY_FILES) writeMemoryFile(file, `Content ${file}`);
|
|
89
|
-
expect(readMemoryV2StaticContent()).toBeNull();
|
|
90
78
|
});
|
|
91
79
|
|
|
92
80
|
test("returns null when config.memory.v2.enabled is off", () => {
|
|
@@ -152,21 +140,10 @@ describe("readMemoryV2StaticContent", () => {
|
|
|
152
140
|
});
|
|
153
141
|
});
|
|
154
142
|
|
|
155
|
-
describe("
|
|
156
|
-
test("blocks all turns until the cadence gate fires", () => {
|
|
157
|
-
expect(
|
|
158
|
-
shouldLoadMemoryV2Static({
|
|
159
|
-
shouldInjectNowAndPkb: false,
|
|
160
|
-
sourceChannel: "vellum",
|
|
161
|
-
isTrustedActor: true,
|
|
162
|
-
}),
|
|
163
|
-
).toBe(false);
|
|
164
|
-
});
|
|
165
|
-
|
|
143
|
+
describe("shouldExposePersonalMemory", () => {
|
|
166
144
|
test("allows guardian-trusted local conversations", () => {
|
|
167
145
|
expect(
|
|
168
|
-
|
|
169
|
-
shouldInjectNowAndPkb: true,
|
|
146
|
+
shouldExposePersonalMemory({
|
|
170
147
|
sourceChannel: "vellum",
|
|
171
148
|
isTrustedActor: true,
|
|
172
149
|
}),
|
|
@@ -175,8 +152,7 @@ describe("shouldLoadMemoryV2Static", () => {
|
|
|
175
152
|
|
|
176
153
|
test("allows local-channel conversations even when trust class is unknown (analyze runs, dev)", () => {
|
|
177
154
|
expect(
|
|
178
|
-
|
|
179
|
-
shouldInjectNowAndPkb: true,
|
|
155
|
+
shouldExposePersonalMemory({
|
|
180
156
|
sourceChannel: "vellum",
|
|
181
157
|
isTrustedActor: false,
|
|
182
158
|
}),
|
|
@@ -185,8 +161,7 @@ describe("shouldLoadMemoryV2Static", () => {
|
|
|
185
161
|
|
|
186
162
|
test("allows turns with no trust context (work-item task runs, internal background)", () => {
|
|
187
163
|
expect(
|
|
188
|
-
|
|
189
|
-
shouldInjectNowAndPkb: true,
|
|
164
|
+
shouldExposePersonalMemory({
|
|
190
165
|
sourceChannel: undefined,
|
|
191
166
|
isTrustedActor: false,
|
|
192
167
|
}),
|
|
@@ -204,8 +179,7 @@ describe("shouldLoadMemoryV2Static", () => {
|
|
|
204
179
|
test("allows guardian-trusted remote channels (user's own phone/Slack)", () => {
|
|
205
180
|
for (const channel of REMOTE_CHANNELS) {
|
|
206
181
|
expect(
|
|
207
|
-
|
|
208
|
-
shouldInjectNowAndPkb: true,
|
|
182
|
+
shouldExposePersonalMemory({
|
|
209
183
|
sourceChannel: channel,
|
|
210
184
|
isTrustedActor: true,
|
|
211
185
|
}),
|
|
@@ -216,8 +190,7 @@ describe("shouldLoadMemoryV2Static", () => {
|
|
|
216
190
|
test("blocks non-guardian remote-channel actors (the leak this gate exists to prevent)", () => {
|
|
217
191
|
for (const channel of REMOTE_CHANNELS) {
|
|
218
192
|
expect(
|
|
219
|
-
|
|
220
|
-
shouldInjectNowAndPkb: true,
|
|
193
|
+
shouldExposePersonalMemory({
|
|
221
194
|
sourceChannel: channel,
|
|
222
195
|
isTrustedActor: false,
|
|
223
196
|
}),
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Tests for `assistant/src/memory/v2/sweep-job.ts`.
|
|
3
3
|
*
|
|
4
|
-
* Coverage matrix
|
|
5
|
-
* -
|
|
6
|
-
* -
|
|
7
|
-
* -
|
|
4
|
+
* Coverage matrix:
|
|
5
|
+
* - v2 disabled in config → no provider/DB calls, returns 0 (early bail).
|
|
6
|
+
* - sweep_enabled off → no provider call, returns 0.
|
|
7
|
+
* - v2 on + no recent messages → no provider call, returns 0.
|
|
8
|
+
* - v2 on + recent messages → provider invoked with rendered prompt;
|
|
8
9
|
* each entry is appended to `memory/buffer.md` AND today's archive.
|
|
9
10
|
* - Tool-call response shape mismatch → returns 0 without writes.
|
|
10
11
|
* - Empty entries are skipped (the model can't pad the buffer).
|
|
@@ -24,7 +25,6 @@ import { tmpdir } from "node:os";
|
|
|
24
25
|
import { join } from "node:path";
|
|
25
26
|
import {
|
|
26
27
|
afterAll,
|
|
27
|
-
afterEach,
|
|
28
28
|
beforeAll,
|
|
29
29
|
beforeEach,
|
|
30
30
|
describe,
|
|
@@ -62,6 +62,23 @@ mock.module("../../../providers/provider-send-message.js", () => ({
|
|
|
62
62
|
response.content.find((b): b is ToolUseContent => b.type === "tool_use"),
|
|
63
63
|
}));
|
|
64
64
|
|
|
65
|
+
// emitNotificationSignal spy — captures every notification the sweep emits
|
|
66
|
+
// so the failure-path test can assert on `activity.failed` shape and dedupe.
|
|
67
|
+
const emitCalls: Array<Record<string, unknown>> = [];
|
|
68
|
+
|
|
69
|
+
mock.module("../../../notifications/emit-signal.js", () => ({
|
|
70
|
+
emitNotificationSignal: async (params: Record<string, unknown>) => {
|
|
71
|
+
emitCalls.push(params);
|
|
72
|
+
return {
|
|
73
|
+
signalId: "sig-1",
|
|
74
|
+
deduplicated: false,
|
|
75
|
+
dispatched: true,
|
|
76
|
+
reason: "ok",
|
|
77
|
+
deliveryResults: [],
|
|
78
|
+
};
|
|
79
|
+
},
|
|
80
|
+
}));
|
|
81
|
+
|
|
65
82
|
// Workspace setup — temp dir per test run, pinned via VELLUM_WORKSPACE_DIR
|
|
66
83
|
// so `getWorkspaceDir()` resolves to the tmpdir.
|
|
67
84
|
let tmpWorkspace: string;
|
|
@@ -85,23 +102,20 @@ afterAll(() => {
|
|
|
85
102
|
const { resetDb, getDb } = await import("../../db-connection.js");
|
|
86
103
|
const { initializeDb } = await import("../../db-init.js");
|
|
87
104
|
const { messages, conversations } = await import("../../schema.js");
|
|
88
|
-
const { _setOverridesForTesting } =
|
|
89
|
-
await import("../../../config/assistant-feature-flags.js");
|
|
90
105
|
const { memoryV2SweepJob } = await import("../sweep-job.js");
|
|
91
106
|
|
|
92
|
-
//
|
|
93
|
-
//
|
|
94
|
-
// the handler a minimal stand-in instead of materializing the full default
|
|
107
|
+
// The handler reads `config.memory.v2.enabled` and `sweep_enabled`, so we
|
|
108
|
+
// hand it a minimal stand-in instead of materializing the full default
|
|
95
109
|
// config — which would otherwise pull in heavy schemas this test doesn't
|
|
96
|
-
// exercise.
|
|
97
|
-
// `flag on` cases need the field set; the `flag off` case bails before
|
|
98
|
-
// the check and uses the bare empty stand-in.
|
|
110
|
+
// exercise.
|
|
99
111
|
const CONFIG = {
|
|
100
|
-
memory: { v2: { sweep_enabled: true } },
|
|
112
|
+
memory: { v2: { enabled: true, sweep_enabled: true } },
|
|
113
|
+
} as Parameters<typeof memoryV2SweepJob>[1];
|
|
114
|
+
const CONFIG_V2_OFF = {
|
|
115
|
+
memory: { v2: { enabled: false, sweep_enabled: true } },
|
|
101
116
|
} as Parameters<typeof memoryV2SweepJob>[1];
|
|
102
|
-
const CONFIG_FLAG_OFF = {} as Parameters<typeof memoryV2SweepJob>[1];
|
|
103
117
|
const CONFIG_SWEEP_OFF = {
|
|
104
|
-
memory: { v2: { sweep_enabled: false } },
|
|
118
|
+
memory: { v2: { enabled: true, sweep_enabled: false } },
|
|
105
119
|
} as Parameters<typeof memoryV2SweepJob>[1];
|
|
106
120
|
|
|
107
121
|
function makeJob(): Parameters<typeof memoryV2SweepJob>[0] {
|
|
@@ -169,6 +183,7 @@ function extractFirstUserText(msgs: { content: unknown }[]): string {
|
|
|
169
183
|
function seedMessages(
|
|
170
184
|
conversationId: string,
|
|
171
185
|
rows: Array<{ role: string; content: string; offsetMs: number }>,
|
|
186
|
+
conversationType: "standard" | "background" | "scheduled" = "standard",
|
|
172
187
|
): void {
|
|
173
188
|
const db = getDb();
|
|
174
189
|
const now = Date.now();
|
|
@@ -178,6 +193,7 @@ function seedMessages(
|
|
|
178
193
|
title: null,
|
|
179
194
|
createdAt: now - 60_000,
|
|
180
195
|
updatedAt: now,
|
|
196
|
+
conversationType,
|
|
181
197
|
})
|
|
182
198
|
.run();
|
|
183
199
|
for (let i = 0; i < rows.length; i++) {
|
|
@@ -203,20 +219,16 @@ beforeEach(() => {
|
|
|
203
219
|
mkdirSync(join(tmpWorkspace, "memory"), { recursive: true });
|
|
204
220
|
providerCalls.length = 0;
|
|
205
221
|
providerStub = null;
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
afterEach(() => {
|
|
209
|
-
_setOverridesForTesting({});
|
|
222
|
+
emitCalls.length = 0;
|
|
210
223
|
});
|
|
211
224
|
|
|
212
225
|
// ---------------------------------------------------------------------------
|
|
213
226
|
|
|
214
|
-
describe("memoryV2SweepJob —
|
|
215
|
-
test("returns 0 without invoking the provider when
|
|
216
|
-
_setOverridesForTesting({ "memory-v2-enabled": false });
|
|
227
|
+
describe("memoryV2SweepJob — v2 disabled", () => {
|
|
228
|
+
test("returns 0 without invoking the provider when memory.v2.enabled is false", async () => {
|
|
217
229
|
providerStub = makeEntriesProvider(["should-not-be-written"]);
|
|
218
230
|
|
|
219
|
-
const written = await memoryV2SweepJob(makeJob(),
|
|
231
|
+
const written = await memoryV2SweepJob(makeJob(), CONFIG_V2_OFF);
|
|
220
232
|
|
|
221
233
|
expect(written).toBe(0);
|
|
222
234
|
expect(providerCalls).toHaveLength(0);
|
|
@@ -224,9 +236,8 @@ describe("memoryV2SweepJob — flag off", () => {
|
|
|
224
236
|
});
|
|
225
237
|
});
|
|
226
238
|
|
|
227
|
-
describe("memoryV2SweepJob —
|
|
239
|
+
describe("memoryV2SweepJob — sweep_enabled off", () => {
|
|
228
240
|
test("returns 0 without invoking the provider when sweep_enabled is false", async () => {
|
|
229
|
-
_setOverridesForTesting({ "memory-v2-enabled": true });
|
|
230
241
|
// No message seeding required — the sweep_enabled bail short-circuits
|
|
231
242
|
// before any DB or workspace reads.
|
|
232
243
|
providerStub = makeEntriesProvider(["should-not-be-written"]);
|
|
@@ -239,11 +250,7 @@ describe("memoryV2SweepJob — flag on, sweep_enabled off", () => {
|
|
|
239
250
|
});
|
|
240
251
|
});
|
|
241
252
|
|
|
242
|
-
describe("memoryV2SweepJob —
|
|
243
|
-
beforeEach(() => {
|
|
244
|
-
_setOverridesForTesting({ "memory-v2-enabled": true });
|
|
245
|
-
});
|
|
246
|
-
|
|
253
|
+
describe("memoryV2SweepJob — no recent messages", () => {
|
|
247
254
|
test("returns 0 when no messages exist in the recent window", async () => {
|
|
248
255
|
providerStub = makeEntriesProvider(["should-not-be-written"]);
|
|
249
256
|
|
|
@@ -273,9 +280,8 @@ describe("memoryV2SweepJob — flag on, no recent messages", () => {
|
|
|
273
280
|
// DB intact long enough for the SQL inserts here to clash.
|
|
274
281
|
let convCounter = 0;
|
|
275
282
|
|
|
276
|
-
describe("memoryV2SweepJob —
|
|
283
|
+
describe("memoryV2SweepJob — recent messages", () => {
|
|
277
284
|
beforeEach(() => {
|
|
278
|
-
_setOverridesForTesting({ "memory-v2-enabled": true });
|
|
279
285
|
seedMessages(`conv-${++convCounter}`, [
|
|
280
286
|
{
|
|
281
287
|
role: "user",
|
|
@@ -431,6 +437,81 @@ describe("memoryV2SweepJob — flag on, recent messages", () => {
|
|
|
431
437
|
|
|
432
438
|
expect(written).toBe(0);
|
|
433
439
|
});
|
|
440
|
+
|
|
441
|
+
test("emits an activity.failed notification when provider.sendMessage throws", async () => {
|
|
442
|
+
// Simulate a transient provider failure once we're past the early
|
|
443
|
+
// bail checks. The sweep must (a) preserve the existing silent-failure
|
|
444
|
+
// contract by returning 0, and (b) surface the failure via the
|
|
445
|
+
// centralized notifications pipeline so the user sees it instead of
|
|
446
|
+
// the failure being silently swallowed.
|
|
447
|
+
providerStub = {
|
|
448
|
+
name: "stub",
|
|
449
|
+
sendMessage: async () => {
|
|
450
|
+
throw new Error("simulated provider failure");
|
|
451
|
+
},
|
|
452
|
+
};
|
|
453
|
+
|
|
454
|
+
const written = await memoryV2SweepJob(makeJob(), CONFIG);
|
|
455
|
+
|
|
456
|
+
expect(written).toBe(0);
|
|
457
|
+
expect(emitCalls).toHaveLength(1);
|
|
458
|
+
const emitted = emitCalls[0]!;
|
|
459
|
+
expect(emitted.sourceEventName).toBe("activity.failed");
|
|
460
|
+
expect(emitted.sourceChannel).toBe("scheduler");
|
|
461
|
+
const day = new Date().toISOString().slice(0, 10);
|
|
462
|
+
expect(emitted.dedupeKey).toBe(`activity-failed:memory.v2.sweep:${day}`);
|
|
463
|
+
const contextPayload = emitted.contextPayload as Record<string, unknown>;
|
|
464
|
+
expect(contextPayload.jobName).toBe("memory.v2.sweep");
|
|
465
|
+
expect(contextPayload.errorKind).toBe("exception");
|
|
466
|
+
expect(contextPayload.errorMessage).toContain("simulated provider failure");
|
|
467
|
+
});
|
|
468
|
+
});
|
|
469
|
+
|
|
470
|
+
describe("memoryV2SweepJob — background/scheduled conversation filter", () => {
|
|
471
|
+
test("excludes background/scheduled conversation content from sweep input", async () => {
|
|
472
|
+
seedMessages(
|
|
473
|
+
`conv-bg-${++convCounter}`,
|
|
474
|
+
[
|
|
475
|
+
{
|
|
476
|
+
role: "assistant",
|
|
477
|
+
content:
|
|
478
|
+
"[heartbeat] internal automation chatter that should not leak",
|
|
479
|
+
offsetMs: -60_000,
|
|
480
|
+
},
|
|
481
|
+
],
|
|
482
|
+
"background",
|
|
483
|
+
);
|
|
484
|
+
seedMessages(
|
|
485
|
+
`conv-sched-${++convCounter}`,
|
|
486
|
+
[
|
|
487
|
+
{
|
|
488
|
+
role: "assistant",
|
|
489
|
+
content:
|
|
490
|
+
"[scheduled] scheduled-job chatter that should not leak either",
|
|
491
|
+
offsetMs: -45_000,
|
|
492
|
+
},
|
|
493
|
+
],
|
|
494
|
+
"scheduled",
|
|
495
|
+
);
|
|
496
|
+
seedMessages(`conv-user-${++convCounter}`, [
|
|
497
|
+
{
|
|
498
|
+
role: "user",
|
|
499
|
+
content: "Bob mentioned he prefers dark mode.",
|
|
500
|
+
offsetMs: -30_000,
|
|
501
|
+
},
|
|
502
|
+
]);
|
|
503
|
+
|
|
504
|
+
providerStub = makeEntriesProvider(["Bob prefers dark mode."]);
|
|
505
|
+
|
|
506
|
+
const written = await memoryV2SweepJob(makeJob(), CONFIG);
|
|
507
|
+
|
|
508
|
+
expect(written).toBe(1);
|
|
509
|
+
expect(providerCalls).toHaveLength(1);
|
|
510
|
+
const [{ userText }] = providerCalls;
|
|
511
|
+
expect(userText).toContain("Bob mentioned he prefers dark mode.");
|
|
512
|
+
expect(userText).not.toContain("internal automation chatter");
|
|
513
|
+
expect(userText).not.toContain("scheduled-job chatter");
|
|
514
|
+
});
|
|
434
515
|
});
|
|
435
516
|
|
|
436
517
|
function todaysArchiveBasename(now: Date = new Date()): string {
|