@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.
Files changed (991) hide show
  1. package/AGENTS.md +11 -0
  2. package/ARCHITECTURE.md +2 -7
  3. package/Dockerfile +80 -5
  4. package/README.md +2 -2
  5. package/bun.lock +11 -1
  6. package/docker-entrypoint.sh +21 -0
  7. package/docker-init-apt-root.sh +94 -0
  8. package/docker-kata-apt-env.sh +39 -0
  9. package/docs/plugins.md +88 -47
  10. package/docs/skills.md +9 -7
  11. package/eslint-rules/__tests__/cli-no-daemon-internals.test.ts +420 -0
  12. package/eslint-rules/cli-no-daemon-internals.js +283 -0
  13. package/eslint.config.mjs +12 -0
  14. package/examples/plugins/echo/README.md +27 -27
  15. package/examples/plugins/echo/package.json +3 -0
  16. package/examples/plugins/echo/register.ts +31 -31
  17. package/knip.json +2 -1
  18. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -1
  19. package/node_modules/@vellumai/slack-text/src/index.test.ts +114 -14
  20. package/node_modules/@vellumai/slack-text/src/index.ts +82 -18
  21. package/openapi.yaml +4462 -991
  22. package/package.json +5 -1
  23. package/scripts/generate-openapi.ts +135 -14
  24. package/scripts/sync-llm-catalog.ts +165 -0
  25. package/scripts/sync-web-search-catalog.ts +129 -0
  26. package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +169 -0
  27. package/src/__tests__/agent-image-optimize.test.ts +11 -3
  28. package/src/__tests__/agent-loop-override-profile.test.ts +26 -1
  29. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +131 -0
  30. package/src/__tests__/anthropic-provider.test.ts +137 -2
  31. package/src/__tests__/app-builder-tool-scripts.test.ts +9 -3
  32. package/src/__tests__/app-control-flow.test.ts +7 -0
  33. package/src/__tests__/app-executors.test.ts +220 -4
  34. package/src/__tests__/assistant-events-sse-shed.test.ts +232 -0
  35. package/src/__tests__/auto-analysis-end-to-end.test.ts +35 -0
  36. package/src/__tests__/avatar-identity-sync.test.ts +87 -0
  37. package/src/__tests__/background-workers-disk-pressure.test.ts +11 -22
  38. package/src/__tests__/btw-routes.test.ts +1 -0
  39. package/src/__tests__/bundled-asset.test.ts +6 -6
  40. package/src/__tests__/call-site-routing-provider.test.ts +172 -45
  41. package/src/__tests__/cancel-resolves-conversation-key.test.ts +44 -3
  42. package/src/__tests__/channel-availability-routes.test.ts +206 -0
  43. package/src/__tests__/channel-delivery-store.test.ts +289 -1
  44. package/src/__tests__/channel-policy.test.ts +12 -0
  45. package/src/__tests__/checker.test.ts +89 -0
  46. package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -1
  47. package/src/__tests__/clawhub.test.ts +75 -16
  48. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +35 -7
  49. package/src/__tests__/compact-event-conversation-id-guard.test.ts +33 -5
  50. package/src/__tests__/compaction-strip-metadata-clear.test.ts +26 -1
  51. package/src/__tests__/compactor-tail-resolution.test.ts +41 -0
  52. package/src/__tests__/config-loader-backfill.test.ts +526 -102
  53. package/src/__tests__/config-loader-corrupt.test.ts +68 -0
  54. package/src/__tests__/config-loader-platform-defaults.test.ts +77 -23
  55. package/src/__tests__/config-schema-cmd.test.ts +63 -29
  56. package/src/__tests__/config-schema.test.ts +35 -3
  57. package/src/__tests__/config-set-platform-guard.test.ts +75 -152
  58. package/src/__tests__/config-set-route.test.ts +278 -0
  59. package/src/__tests__/config-sounds-sync.test.ts +97 -0
  60. package/src/__tests__/config-watcher-skill-reseed.test.ts +453 -0
  61. package/src/__tests__/config-watcher.test.ts +6 -0
  62. package/src/__tests__/contacts-tools.test.ts +51 -199
  63. package/src/__tests__/context-search-agent-protocol.test.ts +21 -2
  64. package/src/__tests__/context-search-agent-runner.test.ts +22 -138
  65. package/src/__tests__/context-search-conversations-source.test.ts +159 -18
  66. package/src/__tests__/context-search-fanout.test.ts +20 -157
  67. package/src/__tests__/context-search-memory-v2-source.test.ts +3 -4
  68. package/src/__tests__/context-search-types.test.ts +7 -2
  69. package/src/__tests__/context-search-workspace-source.test.ts +7 -0
  70. package/src/__tests__/context-token-estimator.test.ts +1 -0
  71. package/src/__tests__/conversation-abort-tool-results.test.ts +4 -1
  72. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -0
  73. package/src/__tests__/conversation-agent-loop-overflow.test.ts +93 -92
  74. package/src/__tests__/conversation-agent-loop.test.ts +2 -0
  75. package/src/__tests__/conversation-crud-inference-profile.test.ts +100 -0
  76. package/src/__tests__/conversation-error.test.ts +80 -3
  77. package/src/__tests__/conversation-fork-crud.test.ts +323 -1
  78. package/src/__tests__/conversation-inference-profile-route.test.ts +54 -18
  79. package/src/__tests__/conversation-init.benchmark.test.ts +1 -0
  80. package/src/__tests__/conversation-lifecycle.test.ts +297 -0
  81. package/src/__tests__/conversation-message-sync-tags.test.ts +97 -0
  82. package/src/__tests__/conversation-pairing.test.ts +54 -0
  83. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +100 -1
  84. package/src/__tests__/conversation-process-callsite.test.ts +25 -2
  85. package/src/__tests__/conversation-provider-retry-repair.test.ts +5 -1
  86. package/src/__tests__/conversation-queue.test.ts +4 -1
  87. package/src/__tests__/conversation-runtime-assembly.test.ts +80 -13
  88. package/src/__tests__/conversation-slash-commands.test.ts +194 -2
  89. package/src/__tests__/conversation-slash-queue.test.ts +59 -1
  90. package/src/__tests__/conversation-slash-unknown.test.ts +4 -1
  91. package/src/__tests__/conversation-surfaces-app-control.test.ts +323 -3
  92. package/src/__tests__/conversation-surfaces-table-action.test.ts +360 -0
  93. package/src/__tests__/conversation-sync-tags.test.ts +235 -0
  94. package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
  95. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
  96. package/src/__tests__/credential-security-invariants.test.ts +8 -8
  97. package/src/__tests__/daemon-credential-client.test.ts +56 -1
  98. package/src/__tests__/db-activation-state-fk-cascade.test.ts +132 -0
  99. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +37 -0
  100. package/src/__tests__/db-memory-graph-event-date-repair.test.ts +43 -20
  101. package/src/__tests__/db-proxy-transaction.test.ts +206 -0
  102. package/src/__tests__/db-slack-external-content-normalization.test.ts +301 -0
  103. package/src/__tests__/delete-managed-skill-tool.test.ts +55 -13
  104. package/src/__tests__/disk-pressure-tools.test.ts +1 -0
  105. package/src/__tests__/dm-backfill.test.ts +121 -10
  106. package/src/__tests__/document-tool-security.test.ts +258 -0
  107. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -1
  108. package/src/__tests__/edit-propagation.test.ts +33 -0
  109. package/src/__tests__/empty-response-pipeline.test.ts +0 -4
  110. package/src/__tests__/external-plugin-loader.test.ts +482 -0
  111. package/src/__tests__/filing-service.test.ts +163 -3
  112. package/src/__tests__/fixtures/mock-chrome-extension.ts +5 -0
  113. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  114. package/src/__tests__/get-skill-detail-audit.test.ts +0 -4
  115. package/src/__tests__/graph-extraction-event-date.test.ts +34 -0
  116. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +42 -69
  117. package/src/__tests__/heartbeat-disk-pressure.test.ts +21 -8
  118. package/src/__tests__/heartbeat-service.test.ts +50 -233
  119. package/src/__tests__/helpers/tar-fixtures.ts +39 -0
  120. package/src/__tests__/helpers/wait-for.ts +21 -0
  121. package/src/__tests__/history-repair-pipeline.test.ts +0 -3
  122. package/src/__tests__/history-repair.test.ts +162 -0
  123. package/src/__tests__/host-app-control-proxy.test.ts +365 -1
  124. package/src/__tests__/host-app-control-routes.test.ts +247 -1
  125. package/src/__tests__/host-browser-proxy.test.ts +416 -20
  126. package/src/__tests__/host-browser-routes.test.ts +325 -33
  127. package/src/__tests__/host-proxy-preactivation.test.ts +211 -0
  128. package/src/__tests__/image-credentials.test.ts +1 -1
  129. package/src/__tests__/inbound-slack-persistence.test.ts +2 -0
  130. package/src/__tests__/inference-no-mode-boot-e2e.test.ts +246 -0
  131. package/src/__tests__/inference-profile-reaper.test.ts +156 -0
  132. package/src/__tests__/inference-profile-session-handler.test.ts +410 -0
  133. package/src/__tests__/inference-profile-session-ipc.test.ts +248 -0
  134. package/src/__tests__/injector-chain.test.ts +10 -8
  135. package/src/__tests__/inline-skill-load-permissions.test.ts +6 -1
  136. package/src/__tests__/install-skill-routing.test.ts +157 -39
  137. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +107 -3
  138. package/src/__tests__/list-messages-page-latest.test.ts +55 -0
  139. package/src/__tests__/llm-call-pipeline.test.ts +0 -3
  140. package/src/__tests__/llm-callsite-catalog.test.ts +20 -1
  141. package/src/__tests__/llm-catalog-parity.test.ts +190 -2
  142. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +222 -0
  143. package/src/__tests__/llm-request-log-source-factory.test.ts +100 -0
  144. package/src/__tests__/llm-resolver.test.ts +46 -0
  145. package/src/__tests__/llm-usage-store.test.ts +114 -0
  146. package/src/__tests__/managed-profile-guard.test.ts +145 -14
  147. package/src/__tests__/managed-skill-lifecycle.test.ts +109 -18
  148. package/src/__tests__/managed-store.test.ts +84 -192
  149. package/src/__tests__/mcp-auth-routes.test.ts +1 -0
  150. package/src/__tests__/mcp-cli.test.ts +182 -220
  151. package/src/__tests__/mcp-health-check.test.ts +56 -27
  152. package/src/__tests__/media-generate-image.test.ts +1 -1
  153. package/src/__tests__/memory-jobs-worker-lanes.test.ts +18 -11
  154. package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -2
  155. package/src/__tests__/message-complete-display-id.test.ts +175 -0
  156. package/src/__tests__/messages-after-tiebreaker.test.ts +122 -0
  157. package/src/__tests__/notification-platform-adapter.test.ts +229 -0
  158. package/src/__tests__/oauth-cli.test.ts +38 -2009
  159. package/src/__tests__/oauth-commands-routes.test.ts +863 -0
  160. package/src/__tests__/oauth-connect-routes.test.ts +174 -11
  161. package/src/__tests__/oauth-provider-profiles.test.ts +9 -0
  162. package/src/__tests__/oauth-providers-routes.test.ts +14 -10
  163. package/src/__tests__/openai-provider.test.ts +24 -0
  164. package/src/__tests__/openai-responses-cutover-guard.test.ts +48 -19
  165. package/src/__tests__/openai-responses-provider.test.ts +17 -0
  166. package/src/__tests__/overflow-reduce-pipeline.test.ts +0 -2
  167. package/src/__tests__/persistence-pipeline.test.ts +0 -2
  168. package/src/__tests__/{managed-proxy-context.test.ts → platform-proxy-context.test.ts} +1 -1
  169. package/src/__tests__/platform.test.ts +2 -0
  170. package/src/__tests__/plugin-api-shim.test.ts +125 -0
  171. package/src/__tests__/plugin-bootstrap.test.ts +41 -38
  172. package/src/__tests__/plugin-external-api.test.ts +68 -0
  173. package/src/__tests__/plugin-registry.test.ts +0 -77
  174. package/src/__tests__/plugin-route-contribution.test.ts +31 -4
  175. package/src/__tests__/plugin-skill-contribution.test.ts +0 -2
  176. package/src/__tests__/plugin-tool-contribution.test.ts +47 -18
  177. package/src/__tests__/plugin-types.test.ts +15 -23
  178. package/src/__tests__/process-message-background-slack.test.ts +53 -0
  179. package/src/__tests__/process-message-display-content.test.ts +421 -0
  180. package/src/__tests__/profile-entry-status.test.ts +43 -0
  181. package/src/__tests__/provider-catalog-visibility.test.ts +142 -0
  182. package/src/__tests__/provider-error-scenarios.test.ts +111 -0
  183. package/src/__tests__/{provider-managed-proxy-integration.test.ts → provider-platform-proxy-integration.test.ts} +20 -12
  184. package/src/__tests__/provider-registry-ollama.test.ts +12 -4
  185. package/src/__tests__/provider-send-message-override-profile.test.ts +10 -4
  186. package/src/__tests__/relay-server.test.ts +118 -0
  187. package/src/__tests__/retry-thinking-tool-choice.test.ts +15 -0
  188. package/src/__tests__/scaffold-managed-skill-tool.test.ts +65 -13
  189. package/src/__tests__/schedule-retry.test.ts +56 -4
  190. package/src/__tests__/schedule-routes.test.ts +151 -0
  191. package/src/__tests__/schedule-store.test.ts +94 -0
  192. package/src/__tests__/scheduler-disk-pressure.test.ts +0 -4
  193. package/src/__tests__/scheduler-recurrence.test.ts +87 -34
  194. package/src/__tests__/scheduler-reuse-conversation.test.ts +208 -5
  195. package/src/__tests__/scheduler-wake.test.ts +0 -63
  196. package/src/__tests__/schema-transforms.test.ts +20 -0
  197. package/src/__tests__/search-skills-unified.test.ts +0 -5
  198. package/src/__tests__/secret-allowlist.test.ts +1 -0
  199. package/src/__tests__/{secret-routes-managed-proxy.test.ts → secret-routes-platform-proxy.test.ts} +12 -4
  200. package/src/__tests__/server-history-render.test.ts +43 -0
  201. package/src/__tests__/shell-credential-ref.test.ts +95 -3
  202. package/src/__tests__/shell-tool-proxy-mode.test.ts +14 -0
  203. package/src/__tests__/skill-load-feature-flag.test.ts +1 -12
  204. package/src/__tests__/skill-load-tool.test.ts +29 -93
  205. package/src/__tests__/skill-memory.test.ts +23 -3
  206. package/src/__tests__/skills-file-content-endpoint.test.ts +9 -38
  207. package/src/__tests__/skills-files-catalog-fallback.test.ts +0 -3
  208. package/src/__tests__/skills-install-extract.test.ts +49 -38
  209. package/src/__tests__/skills-install-staging.test.ts +159 -0
  210. package/src/__tests__/skills-uninstall.test.ts +9 -41
  211. package/src/__tests__/skills.test.ts +51 -58
  212. package/src/__tests__/slack-channel-config.test.ts +9 -0
  213. package/src/__tests__/subagent-call-site-routing.test.ts +78 -16
  214. package/src/__tests__/subagent-tool-filtering.test.ts +50 -0
  215. package/src/__tests__/suggestion-routes.test.ts +3 -3
  216. package/src/__tests__/sync-message-contract.test.ts +63 -0
  217. package/src/__tests__/system-prompt.test.ts +737 -63
  218. package/src/__tests__/task-scheduler.test.ts +88 -23
  219. package/src/__tests__/terminal-tools.test.ts +28 -1
  220. package/src/__tests__/thread-backfill.test.ts +557 -27
  221. package/src/__tests__/title-generate-pipeline.test.ts +0 -13
  222. package/src/__tests__/token-estimate-pipeline.test.ts +0 -3
  223. package/src/__tests__/tool-error-pipeline.test.ts +0 -3
  224. package/src/__tests__/tool-execute-pipeline.test.ts +0 -5
  225. package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
  226. package/src/__tests__/tool-executor.test.ts +16 -4
  227. package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -12
  228. package/src/__tests__/turn-events-store.test.ts +256 -0
  229. package/src/__tests__/twilio-routes.test.ts +4 -0
  230. package/src/__tests__/update-bulletin-job.test.ts +96 -193
  231. package/src/__tests__/usage-cli.test.ts +11 -73
  232. package/src/__tests__/user-plugin-loader.test.ts +143 -5
  233. package/src/__tests__/vercel-config.test.ts +168 -0
  234. package/src/__tests__/voice-session-bridge.test.ts +198 -0
  235. package/src/__tests__/web-search-catalog-parity.test.ts +108 -0
  236. package/src/__tests__/web-search.test.ts +303 -2
  237. package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +1 -21
  238. package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +170 -0
  239. package/src/__tests__/workspace-migration-069-seed-onboarding-threads.test.ts +53 -20
  240. package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +241 -0
  241. package/src/__tests__/workspace-migration-073-repair-recall-callsite-empty-profile.test.ts +153 -0
  242. package/src/__tests__/workspace-migration-076-drop-services-inference-mode.test.ts +211 -0
  243. package/src/__tests__/workspace-migration-077-seed-memory-router-callsite.test.ts +174 -0
  244. package/src/__tests__/workspace-migration-079-home-feed-notification-only.test.ts +323 -0
  245. package/src/__tests__/workspace-migration-080-restrict-vercel-api-token-metadata.test.ts +299 -0
  246. package/src/__tests__/workspace-migration-081-backfill-bash-allowed-tools.test.ts +410 -0
  247. package/src/__tests__/workspace-migration-082-backfill-managed-profile-labels.test.ts +268 -0
  248. package/src/__tests__/workspace-migration-085-memory-v2-bm25-b-reembed-disabled-v2-pages.test.ts +220 -0
  249. package/src/__tests__/workspace-migration-086-revert-stale-gemini-mis-rewrites.test.ts +269 -0
  250. package/src/__tests__/workspace-migration-remove-legacy-skills-index.test.ts +309 -0
  251. package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +3 -3
  252. package/src/__tests__/workspace-migrations-runner.test.ts +111 -3
  253. package/src/__tests__/workspace-release-notes-feature-flag-guard.test.ts +115 -0
  254. package/src/acp/__tests__/helpers/which-stub.ts +4 -2
  255. package/src/acp/resolve-agent.test.ts +25 -0
  256. package/src/acp/resolve-agent.ts +13 -2
  257. package/src/acp/session-manager.ts +14 -0
  258. package/src/agent/image-optimize.ts +13 -5
  259. package/src/approvals/guardian-request-resolvers.ts +32 -87
  260. package/src/calls/relay-server.ts +35 -0
  261. package/src/calls/relay-setup-router.ts +36 -0
  262. package/src/calls/types.ts +1 -0
  263. package/src/calls/voice-session-bridge.ts +74 -36
  264. package/src/channels/config.ts +14 -1
  265. package/src/channels/types.ts +109 -0
  266. package/src/cli/AGENTS.md +164 -4
  267. package/src/cli/__tests__/notifications.test.ts +54 -0
  268. package/src/cli/__tests__/unknown-command.test.ts +24 -0
  269. package/src/cli/commands/__tests__/avatar.test.ts +540 -0
  270. package/src/cli/commands/__tests__/backup.test.ts +236 -776
  271. package/src/cli/commands/__tests__/cache.test.ts +1 -1
  272. package/src/cli/commands/__tests__/changelog.test.ts +578 -0
  273. package/src/cli/commands/__tests__/channel-verification-sessions.test.ts +503 -0
  274. package/src/cli/commands/__tests__/conversations-import.test.ts +515 -0
  275. package/src/cli/commands/__tests__/domain-register.test.ts +140 -167
  276. package/src/cli/commands/__tests__/domain-status.test.ts +137 -76
  277. package/src/cli/commands/__tests__/email-attachment.test.ts +314 -337
  278. package/src/cli/commands/__tests__/email-core.test.ts +579 -0
  279. package/src/cli/commands/__tests__/image-generation.test.ts +87 -824
  280. package/src/cli/commands/__tests__/inference-send.test.ts +30 -266
  281. package/src/cli/commands/__tests__/inference-session.test.ts +423 -0
  282. package/src/cli/commands/__tests__/memory-v2.test.ts +81 -110
  283. package/src/cli/commands/__tests__/schedules.test.ts +491 -0
  284. package/src/cli/commands/__tests__/skills.test.ts +563 -0
  285. package/src/cli/commands/__tests__/status.test.ts +249 -0
  286. package/src/cli/commands/__tests__/stt.test.ts +320 -0
  287. package/src/cli/commands/__tests__/tts-synthesize.test.ts +4 -603
  288. package/src/cli/commands/__tests__/tts.test.ts +321 -0
  289. package/src/cli/commands/__tests__/webhooks.test.ts +86 -511
  290. package/src/cli/commands/attachment.ts +8 -3
  291. package/src/cli/commands/audit.ts +95 -64
  292. package/src/cli/commands/auth.ts +61 -58
  293. package/src/cli/commands/avatar.ts +276 -390
  294. package/src/cli/commands/backup.ts +409 -505
  295. package/src/cli/commands/bash.ts +9 -5
  296. package/src/cli/commands/browser.ts +28 -9
  297. package/src/cli/commands/cache.ts +9 -4
  298. package/src/cli/commands/changelog.ts +478 -0
  299. package/src/cli/commands/channel-verification-sessions.ts +238 -317
  300. package/src/cli/commands/clients.ts +8 -3
  301. package/src/cli/commands/completions.ts +9 -9
  302. package/src/cli/commands/config.ts +102 -72
  303. package/src/cli/commands/contacts.ts +575 -696
  304. package/src/cli/commands/conversations-defer.ts +17 -69
  305. package/src/cli/commands/conversations-import.ts +90 -253
  306. package/src/cli/commands/conversations.ts +429 -434
  307. package/src/cli/commands/credential-execution.ts +9 -6
  308. package/src/cli/commands/credentials.ts +456 -736
  309. package/src/cli/commands/default-action.ts +10 -53
  310. package/src/cli/commands/domain.ts +128 -206
  311. package/src/cli/commands/email.ts +606 -794
  312. package/src/cli/commands/gateway.ts +8 -1
  313. package/src/cli/commands/image-generation.ts +157 -205
  314. package/src/cli/commands/inference-providers.ts +352 -0
  315. package/src/cli/commands/inference-session.ts +415 -0
  316. package/src/cli/commands/inference.ts +87 -65
  317. package/src/cli/commands/keys.ts +8 -3
  318. package/src/cli/commands/mcp.ts +103 -287
  319. package/src/cli/commands/memory-v2.ts +162 -516
  320. package/src/cli/commands/notifications.ts +342 -304
  321. package/src/cli/commands/oauth/apps.ts +292 -261
  322. package/src/cli/commands/oauth/connect.ts +176 -297
  323. package/src/cli/commands/oauth/disconnect.ts +16 -215
  324. package/src/cli/commands/oauth/index.ts +49 -45
  325. package/src/cli/commands/oauth/mode.ts +43 -199
  326. package/src/cli/commands/oauth/ping.ts +17 -125
  327. package/src/cli/commands/oauth/providers.ts +732 -921
  328. package/src/cli/commands/oauth/request.ts +60 -350
  329. package/src/cli/commands/oauth/shared.ts +11 -121
  330. package/src/cli/commands/oauth/status.ts +31 -121
  331. package/src/cli/commands/oauth/token.ts +13 -55
  332. package/src/cli/commands/pending.ts +19 -10
  333. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +133 -183
  334. package/src/cli/commands/platform/__tests__/connect.test.ts +66 -181
  335. package/src/cli/commands/platform/__tests__/disconnect.test.ts +71 -227
  336. package/src/cli/commands/platform/__tests__/status.test.ts +169 -287
  337. package/src/cli/commands/platform/connect.ts +16 -80
  338. package/src/cli/commands/platform/disconnect.ts +14 -112
  339. package/src/cli/commands/platform/index.ts +177 -246
  340. package/src/cli/commands/plugins.ts +185 -0
  341. package/src/cli/commands/routes.ts +153 -336
  342. package/src/cli/commands/schedules.ts +391 -0
  343. package/src/cli/commands/sequence.ts +316 -360
  344. package/src/cli/commands/skills.ts +449 -671
  345. package/src/cli/commands/status.ts +58 -37
  346. package/src/cli/commands/stt.ts +94 -262
  347. package/src/cli/commands/task.ts +14 -40
  348. package/src/cli/commands/telemetry.ts +40 -0
  349. package/src/cli/commands/trust.ts +8 -3
  350. package/src/cli/commands/tts.ts +162 -167
  351. package/src/cli/commands/ui.ts +35 -42
  352. package/src/cli/commands/usage.ts +188 -126
  353. package/src/cli/commands/watchers.ts +8 -3
  354. package/src/cli/commands/webhooks.ts +99 -193
  355. package/src/cli/lib/__tests__/cli-colors.test.ts +48 -0
  356. package/src/cli/lib/__tests__/confirm-prompt.test.ts +159 -0
  357. package/src/cli/lib/__tests__/install-from-github.test.ts +355 -0
  358. package/src/cli/lib/__tests__/list-installed-plugins.test.ts +154 -0
  359. package/src/cli/lib/__tests__/register-command.test.ts +85 -0
  360. package/src/cli/lib/__tests__/uninstall-plugin.test.ts +124 -0
  361. package/src/cli/lib/__tests__/unknown-command.test.ts +106 -0
  362. package/src/cli/lib/cli-colors.ts +12 -0
  363. package/src/cli/lib/confirm-prompt.ts +79 -0
  364. package/src/cli/lib/daemon-credential-client.ts +4 -5
  365. package/src/cli/lib/install-from-github.ts +304 -0
  366. package/src/cli/lib/list-installed-plugins.ts +137 -0
  367. package/src/cli/lib/nested-value.ts +44 -0
  368. package/src/cli/lib/open-browser.ts +36 -0
  369. package/src/cli/lib/register-command.ts +19 -0
  370. package/src/cli/lib/time-ago.ts +34 -0
  371. package/src/cli/lib/uninstall-plugin.ts +82 -0
  372. package/src/cli/lib/unknown-command.ts +111 -0
  373. package/src/cli/program.ts +40 -6
  374. package/src/cli/utils/__tests__/conversation-id.test.ts +66 -0
  375. package/src/cli/utils/__tests__/parse-duration.test.ts +49 -0
  376. package/src/cli/utils/conversation-id.ts +30 -0
  377. package/src/cli/utils/parse-duration.ts +41 -0
  378. package/src/config/acp-defaults.test.ts +5 -1
  379. package/src/config/acp-defaults.ts +11 -4
  380. package/src/config/bundled-skills/acp/TOOLS.json +2 -2
  381. package/src/config/bundled-skills/app-builder/SKILL.md +23 -21
  382. package/src/config/bundled-skills/app-builder/TOOLS.json +7 -0
  383. package/src/config/bundled-skills/app-control/TOOLS.json +32 -0
  384. package/src/config/bundled-skills/computer-use/TOOLS.json +15 -52
  385. package/src/config/bundled-skills/contacts/SKILL.md +12 -45
  386. package/src/config/bundled-skills/contacts/TOOLS.json +0 -57
  387. package/src/config/bundled-skills/document/SKILL.md +23 -3
  388. package/src/config/bundled-skills/document/TOOLS.json +53 -0
  389. package/src/config/bundled-skills/document/tools/document-delete.ts +12 -0
  390. package/src/config/bundled-skills/document/tools/document-list.ts +12 -0
  391. package/src/config/bundled-skills/document/tools/document-read.ts +12 -0
  392. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +0 -12
  393. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +0 -58
  394. package/src/config/bundled-skills/skill-management/SKILL.md +2 -2
  395. package/src/config/bundled-skills/skill-management/TOOLS.json +7 -7
  396. package/src/config/bundled-tool-registry.ts +6 -2
  397. package/src/config/feature-flag-registry.json +57 -1
  398. package/src/config/llm-resolver.ts +16 -1
  399. package/src/config/loader.ts +140 -52
  400. package/src/config/raw-config-utils.ts +2 -30
  401. package/src/config/schema.ts +8 -7
  402. package/src/config/schemas/__tests__/llm-request-logs.test.ts +36 -0
  403. package/src/config/schemas/__tests__/memory-v2.test.ts +49 -0
  404. package/src/config/schemas/call-site-catalog.ts +29 -7
  405. package/src/config/schemas/channels.ts +8 -0
  406. package/src/config/schemas/compaction.ts +28 -0
  407. package/src/config/schemas/heartbeat.ts +9 -0
  408. package/src/config/schemas/llm-request-logs.ts +81 -0
  409. package/src/config/schemas/llm.ts +55 -2
  410. package/src/config/schemas/memory-retrieval.ts +18 -0
  411. package/src/config/schemas/memory-retrospective.ts +48 -0
  412. package/src/config/schemas/memory-v2.ts +32 -1
  413. package/src/config/schemas/memory.ts +4 -0
  414. package/src/config/schemas/services.ts +15 -12
  415. package/src/config/schemas/tools.ts +14 -0
  416. package/src/config/seed-inference-profiles.ts +195 -134
  417. package/src/config/skills.ts +3 -96
  418. package/src/contacts/contact-store.ts +0 -61
  419. package/src/context/compactor.ts +1047 -0
  420. package/src/context/token-estimator.ts +2 -2
  421. package/src/context/window-manager.ts +197 -1334
  422. package/src/credential-execution/managed-catalog.ts +37 -0
  423. package/src/credential-health/credential-health-service.ts +280 -19
  424. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +113 -0
  425. package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +138 -0
  426. package/src/daemon/__tests__/conversation-tool-setup.test.ts +183 -4
  427. package/src/daemon/__tests__/daemon-skill-host.test.ts +10 -4
  428. package/src/daemon/approval-generators.ts +26 -30
  429. package/src/daemon/config-watcher.ts +94 -29
  430. package/src/daemon/conversation-agent-loop-handlers.ts +24 -0
  431. package/src/daemon/conversation-agent-loop.ts +293 -103
  432. package/src/daemon/conversation-error.ts +188 -33
  433. package/src/daemon/conversation-lifecycle.ts +80 -26
  434. package/src/daemon/conversation-messaging.ts +25 -6
  435. package/src/daemon/conversation-process.ts +85 -31
  436. package/src/daemon/conversation-runtime-assembly.ts +30 -6
  437. package/src/daemon/conversation-slash.ts +184 -25
  438. package/src/daemon/conversation-store.ts +24 -10
  439. package/src/daemon/conversation-surfaces.ts +76 -12
  440. package/src/daemon/conversation-tool-setup.ts +63 -21
  441. package/src/daemon/conversation.ts +81 -10
  442. package/src/daemon/external-plugins-bootstrap.ts +231 -185
  443. package/src/daemon/first-greeting.ts +22 -2
  444. package/src/daemon/guardian-action-generators.ts +7 -22
  445. package/src/daemon/handlers/config-model.ts +13 -130
  446. package/src/daemon/handlers/config-slack-channel.ts +25 -10
  447. package/src/daemon/handlers/config-vercel.ts +3 -1
  448. package/src/daemon/handlers/shared.ts +14 -5
  449. package/src/daemon/handlers/skills.ts +166 -84
  450. package/src/daemon/history-repair.ts +61 -7
  451. package/src/daemon/host-app-control-proxy.ts +129 -29
  452. package/src/daemon/host-bash-proxy.ts +85 -158
  453. package/src/daemon/host-browser-proxy.ts +96 -35
  454. package/src/daemon/host-proxy-base.ts +13 -1
  455. package/src/daemon/host-proxy-preactivation.ts +25 -1
  456. package/src/daemon/identity-helpers.ts +19 -0
  457. package/src/daemon/lifecycle.ts +79 -70
  458. package/src/daemon/meet-host-supervisor.ts +20 -19
  459. package/src/daemon/memory-v2-startup.ts +58 -2
  460. package/src/daemon/message-protocol.ts +7 -0
  461. package/src/daemon/message-types/bookmarks.ts +18 -0
  462. package/src/daemon/message-types/conversations.ts +37 -9
  463. package/src/daemon/message-types/messages.ts +70 -1
  464. package/src/daemon/message-types/subagents.ts +1 -0
  465. package/src/daemon/message-types/sync.ts +61 -0
  466. package/src/daemon/pkb-reminder-builder.test.ts +54 -13
  467. package/src/daemon/pkb-reminder-builder.ts +21 -7
  468. package/src/daemon/plugin-source-watcher.ts +146 -0
  469. package/src/daemon/process-message.ts +77 -26
  470. package/src/daemon/server.ts +34 -20
  471. package/src/daemon/shutdown-handlers.ts +0 -2
  472. package/src/daemon/skill-memory-refresh.ts +29 -0
  473. package/src/daemon/tool-setup-types.ts +9 -0
  474. package/src/daemon/tool-side-effects.ts +6 -4
  475. package/src/daemon/wake-target-adapter.ts +11 -0
  476. package/src/documents/document-store.ts +221 -3
  477. package/src/embedded/plugin-api.ts +40 -0
  478. package/src/export/transcript-formatter.ts +61 -2
  479. package/src/filing/filing-service.ts +79 -53
  480. package/src/heartbeat/__tests__/heartbeat-service.test.ts +444 -0
  481. package/src/heartbeat/heartbeat-run-store.ts +3 -1
  482. package/src/heartbeat/heartbeat-service.ts +189 -127
  483. package/src/home/__tests__/feed-types.test.ts +99 -127
  484. package/src/home/__tests__/feed-writer.test.ts +77 -278
  485. package/src/home/__tests__/post-connect-feed.test.ts +9 -12
  486. package/src/home/feed-types.ts +41 -73
  487. package/src/home/feed-writer.ts +25 -156
  488. package/src/home/post-connect-feed.ts +2 -3
  489. package/src/index.ts +18 -1
  490. package/src/ipc/__tests__/cli-ipc.test.ts +2 -0
  491. package/src/ipc/__tests__/email-ipc.test.ts +506 -0
  492. package/src/ipc/__tests__/exit-helper.test.ts +104 -0
  493. package/src/ipc/__tests__/streaming-client.test.ts +237 -0
  494. package/src/ipc/__tests__/streaming-framing.test.ts +142 -0
  495. package/src/ipc/assistant-server.ts +55 -6
  496. package/src/ipc/cli-client.ts +370 -50
  497. package/src/ipc/routes/db-proxy-transaction.ts +151 -0
  498. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +60 -0
  499. package/src/ipc/skill-routes/events.ts +30 -3
  500. package/src/live-voice/__tests__/live-voice-session-manager.test.ts +46 -0
  501. package/src/live-voice/__tests__/live-voice-stt.test.ts +57 -0
  502. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +1 -0
  503. package/src/live-voice/live-voice-session-manager.ts +11 -4
  504. package/src/live-voice/live-voice-session.ts +14 -6
  505. package/src/mcp/client.ts +20 -4
  506. package/src/media/image-credentials.ts +3 -3
  507. package/src/memory/__tests__/bookmark-crud.test.ts +264 -0
  508. package/src/memory/__tests__/bookmark-schema.test.ts +181 -0
  509. package/src/memory/__tests__/conversation-queries.test.ts +263 -0
  510. package/src/memory/__tests__/conversation-types.test.ts +36 -0
  511. package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +130 -0
  512. package/src/memory/__tests__/jobs-worker-v2-graph-trigger-embed.test.ts +113 -0
  513. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +177 -0
  514. package/src/memory/__tests__/memory-retrospective-job.test.ts +328 -0
  515. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +318 -0
  516. package/src/memory/__tests__/memory-retrospective-trigger-check.test.ts +90 -0
  517. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +69 -0
  518. package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -0
  519. package/src/memory/__tests__/message-content.test.ts +35 -0
  520. package/src/memory/bookmark-crud.ts +211 -0
  521. package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +31 -9
  522. package/src/memory/context-search/agent-protocol.ts +5 -1
  523. package/src/memory/context-search/agent-runner.ts +60 -85
  524. package/src/memory/context-search/limits.ts +1 -4
  525. package/src/memory/context-search/search.ts +23 -113
  526. package/src/memory/context-search/sources/conversations.ts +80 -8
  527. package/src/memory/context-search/sources/memory-v2.ts +39 -14
  528. package/src/memory/context-search/sources/memory.ts +7 -0
  529. package/src/memory/context-search/sources/workspace.ts +17 -10
  530. package/src/memory/context-search/types.ts +1 -1
  531. package/src/memory/conversation-bootstrap.ts +11 -0
  532. package/src/memory/conversation-crud.ts +368 -22
  533. package/src/memory/conversation-queries.ts +116 -12
  534. package/src/memory/conversation-title-service.ts +1 -0
  535. package/src/memory/conversation-types.ts +16 -0
  536. package/src/memory/db-init.ts +20 -0
  537. package/src/memory/delivery-crud.ts +152 -5
  538. package/src/memory/embedding-backend.ts +6 -5
  539. package/src/memory/embedding-runtime-manager.ts +1 -2
  540. package/src/memory/external-conversation-store.ts +66 -5
  541. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +66 -9
  542. package/src/memory/graph/__tests__/remember-description.test.ts +55 -0
  543. package/src/memory/graph/conversation-graph-memory.ts +92 -5
  544. package/src/memory/graph/extraction.ts +4 -0
  545. package/src/memory/graph/graph-memory-state-store.ts +16 -3
  546. package/src/memory/graph/tool-handlers.ts +17 -7
  547. package/src/memory/graph/tools.ts +45 -6
  548. package/src/memory/indexer.ts +51 -29
  549. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +86 -15
  550. package/src/memory/jobs/embed-concept-page.ts +65 -20
  551. package/src/memory/jobs-store.ts +51 -1
  552. package/src/memory/jobs-worker.ts +57 -3
  553. package/src/memory/llm-request-log-source-clickhouse.ts +324 -0
  554. package/src/memory/llm-request-log-source-local.ts +26 -0
  555. package/src/memory/llm-request-log-source.ts +64 -0
  556. package/src/memory/llm-request-log-store.ts +1 -1
  557. package/src/memory/llm-usage-store.ts +125 -5
  558. package/src/memory/memory-retrospective-constants.ts +13 -0
  559. package/src/memory/memory-retrospective-enqueue.ts +114 -0
  560. package/src/memory/memory-retrospective-job.ts +351 -0
  561. package/src/memory/memory-retrospective-startup-cleanup.ts +175 -0
  562. package/src/memory/memory-retrospective-state.ts +162 -0
  563. package/src/memory/memory-retrospective-trigger-check.ts +91 -0
  564. package/src/memory/memory-v2-activation-log-store.ts +49 -5
  565. package/src/memory/memory-v2-concept-frequency.ts +4 -0
  566. package/src/memory/message-content.ts +38 -1
  567. package/src/memory/migrations/109-external-conversation-bindings.ts +15 -4
  568. package/src/memory/migrations/227-add-conversation-inference-profile.ts +6 -1
  569. package/src/memory/migrations/228-rename-inference-profile-snake-case.ts +20 -7
  570. package/src/memory/migrations/229-delete-private-conversations.test.ts +107 -1
  571. package/src/memory/migrations/229-delete-private-conversations.ts +19 -0
  572. package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +16 -2
  573. package/src/memory/migrations/240-conversation-inference-profile-session.ts +25 -0
  574. package/src/memory/migrations/241-activation-state-fk-cascade.ts +50 -0
  575. package/src/memory/migrations/242-message-bookmarks.ts +38 -0
  576. package/src/memory/migrations/243-provider-connections.ts +68 -0
  577. package/src/memory/migrations/244-provider-connection-status-label.ts +23 -0
  578. package/src/memory/migrations/245-memory-retrospective-state.ts +36 -0
  579. package/src/memory/migrations/246-backfill-provider-connection-label.ts +81 -0
  580. package/src/memory/migrations/247-external-conversation-binding-thread-id.ts +78 -0
  581. package/src/memory/migrations/248-create-onboarding-events.ts +21 -0
  582. package/src/memory/migrations/249-normalize-slack-external-content.ts +240 -0
  583. package/src/memory/migrations/__tests__/244-provider-connection-status-label.test.ts +84 -0
  584. package/src/memory/migrations/__tests__/245-memory-retrospective-state.test.ts +125 -0
  585. package/src/memory/migrations/__tests__/246-backfill-provider-connection-label.test.ts +192 -0
  586. package/src/memory/migrations/index.ts +13 -0
  587. package/src/memory/migrations/registry.ts +8 -0
  588. package/src/memory/onboarding-events-store.ts +106 -0
  589. package/src/memory/published-pages-store.ts +16 -0
  590. package/src/memory/schema/bookmarks.ts +36 -0
  591. package/src/memory/schema/calls.ts +1 -0
  592. package/src/memory/schema/conversations.ts +2 -0
  593. package/src/memory/schema/index.ts +2 -0
  594. package/src/memory/schema/inference.ts +27 -0
  595. package/src/memory/schema/infrastructure.ts +12 -0
  596. package/src/memory/schema/memory-core.ts +9 -0
  597. package/src/memory/search/semantic.ts +1 -4
  598. package/src/memory/turn-events-store.ts +127 -2
  599. package/src/memory/v2/__tests__/__snapshots__/prompts-router.test.ts.snap +27 -0
  600. package/src/memory/v2/__tests__/activation-store.test.ts +5 -5
  601. package/src/memory/v2/__tests__/activation.test.ts +11 -12
  602. package/src/memory/v2/__tests__/backfill-jobs.test.ts +38 -21
  603. package/src/memory/v2/__tests__/consolidation-job.test.ts +123 -135
  604. package/src/memory/v2/__tests__/edge-index.test.ts +1 -1
  605. package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +111 -0
  606. package/src/memory/v2/__tests__/injection.test.ts +726 -18
  607. package/src/memory/v2/__tests__/migration.test.ts +94 -3
  608. package/src/memory/v2/__tests__/page-index.test.ts +360 -0
  609. package/src/memory/v2/__tests__/page-store.test.ts +14 -1
  610. package/src/memory/v2/__tests__/prompts-router.test.ts +309 -0
  611. package/src/memory/v2/__tests__/qdrant.test.ts +138 -3
  612. package/src/memory/v2/__tests__/reranker.test.ts +4 -4
  613. package/src/memory/v2/__tests__/router.test.ts +531 -0
  614. package/src/memory/v2/__tests__/sim.test.ts +45 -1
  615. package/src/memory/v2/__tests__/skill-store.test.ts +445 -11
  616. package/src/memory/v2/__tests__/static-context.test.ts +7 -22
  617. package/src/memory/v2/__tests__/sweep-job.test.ts +95 -0
  618. package/src/memory/v2/activation-store.ts +34 -5
  619. package/src/memory/v2/activation.ts +40 -27
  620. package/src/memory/v2/backfill-jobs.ts +17 -84
  621. package/src/memory/v2/consolidation-job.ts +85 -78
  622. package/src/memory/v2/frontmatter-sweep.ts +91 -0
  623. package/src/memory/v2/injection.ts +466 -109
  624. package/src/memory/v2/migration.ts +147 -20
  625. package/src/memory/v2/page-index.ts +221 -0
  626. package/src/memory/v2/page-store.ts +3 -0
  627. package/src/memory/v2/prompts/consolidation.ts +9 -7
  628. package/src/memory/v2/prompts/router.ts +195 -0
  629. package/src/memory/v2/prompts/sweep.ts +2 -2
  630. package/src/memory/v2/qdrant.ts +234 -93
  631. package/src/memory/v2/reranker.ts +14 -7
  632. package/src/memory/v2/router.ts +323 -0
  633. package/src/memory/v2/sim.ts +25 -12
  634. package/src/memory/v2/skill-store.ts +204 -30
  635. package/src/memory/v2/static-context.ts +16 -9
  636. package/src/memory/v2/sweep-job.ts +122 -96
  637. package/src/memory/v2/types.ts +10 -6
  638. package/src/memory/validation.ts +13 -0
  639. package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +45 -5
  640. package/src/messaging/providers/slack/__tests__/download.test.ts +231 -0
  641. package/src/messaging/providers/slack/adapter.ts +43 -5
  642. package/src/messaging/providers/slack/client.ts +27 -0
  643. package/src/messaging/providers/slack/deep-link.ts +65 -0
  644. package/src/messaging/providers/slack/download.ts +104 -0
  645. package/src/messaging/providers/slack/message-metadata.test.ts +32 -0
  646. package/src/messaging/providers/slack/message-metadata.ts +27 -0
  647. package/src/messaging/providers/slack/render-transcript.test.ts +134 -0
  648. package/src/messaging/providers/slack/render-transcript.ts +69 -5
  649. package/src/messaging/providers/slack/types.ts +20 -1
  650. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +182 -0
  651. package/src/notifications/__tests__/home-feed-side-effect.test.ts +199 -0
  652. package/src/notifications/__tests__/signal-registry.test.ts +17 -0
  653. package/src/notifications/adapters/platform.ts +171 -0
  654. package/src/notifications/conversation-pairing.ts +4 -3
  655. package/src/notifications/copy-composer.ts +15 -0
  656. package/src/notifications/decision-engine.ts +2 -1
  657. package/src/notifications/destination-resolver.ts +21 -0
  658. package/src/notifications/emit-signal.ts +48 -2
  659. package/src/notifications/home-feed-side-effect.ts +165 -0
  660. package/src/notifications/signal.ts +8 -1
  661. package/src/oauth/connection-resolver.ts +8 -4
  662. package/src/oauth/platform-connection.ts +6 -2
  663. package/src/oauth/seed-providers.ts +10 -1
  664. package/src/permissions/checker.ts +14 -0
  665. package/src/permissions/ipc-risk-types.ts +3 -0
  666. package/src/permissions/question-prompter.test.ts +416 -0
  667. package/src/permissions/question-prompter.ts +294 -0
  668. package/src/platform/client.test.ts +1 -1
  669. package/src/platform/client.ts +1 -1
  670. package/src/plugin-api/constants.ts +26 -0
  671. package/src/plugin-api/index.ts +46 -0
  672. package/src/plugin-api/package.json +12 -0
  673. package/src/plugin-api/types.ts +144 -0
  674. package/src/plugins/defaults/circuit-breaker.ts +0 -5
  675. package/src/plugins/defaults/compaction.ts +0 -4
  676. package/src/plugins/defaults/empty-response.ts +0 -2
  677. package/src/plugins/defaults/history-repair.ts +0 -2
  678. package/src/plugins/defaults/injectors.ts +55 -6
  679. package/src/plugins/defaults/llm-call.ts +0 -2
  680. package/src/plugins/defaults/memory-retrieval.ts +0 -1
  681. package/src/plugins/defaults/overflow-reduce.ts +0 -1
  682. package/src/plugins/defaults/persistence.ts +0 -2
  683. package/src/plugins/defaults/title-generate.ts +0 -5
  684. package/src/plugins/defaults/token-estimate.ts +0 -2
  685. package/src/plugins/defaults/tool-error.ts +0 -7
  686. package/src/plugins/defaults/tool-execute.ts +0 -2
  687. package/src/plugins/defaults/tool-result-truncate.ts +0 -4
  688. package/src/plugins/ensure-plugin-api-shim.ts +96 -0
  689. package/src/plugins/external-api.ts +104 -0
  690. package/src/plugins/external-plugin-loader.ts +367 -0
  691. package/src/plugins/feature-gate.ts +22 -0
  692. package/src/plugins/pipeline.ts +37 -0
  693. package/src/plugins/registry.ts +48 -80
  694. package/src/plugins/types.ts +74 -53
  695. package/src/plugins/user-loader.ts +85 -43
  696. package/src/proactive-artifact/aux-message-injector.ts +11 -0
  697. package/src/proactive-artifact/job.test.ts +49 -9
  698. package/src/proactive-artifact/job.ts +4 -0
  699. package/src/proactive-artifact/trigger-state.test.ts +9 -0
  700. package/src/proactive-artifact/trigger-state.ts +4 -0
  701. package/src/prompts/__tests__/system-prompt.test.ts +117 -0
  702. package/src/prompts/__tests__/task-progress-hint-section.test.ts +99 -0
  703. package/src/prompts/normalize-onboarding.ts +27 -0
  704. package/src/prompts/sections.ts +302 -0
  705. package/src/prompts/system-prompt.ts +72 -154
  706. package/src/prompts/templates/BOOTSTRAP.md +17 -1
  707. package/src/prompts/templates/system-sections.ts +173 -0
  708. package/src/prompts/update-bulletin-job.ts +61 -73
  709. package/src/providers/__tests__/dispatch-connection-routing.test.ts +279 -0
  710. package/src/providers/__tests__/inference.test.ts +303 -0
  711. package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
  712. package/src/providers/__tests__/provider-secret-catalog.test.ts +6 -0
  713. package/src/providers/__tests__/retry-callsite.test.ts +14 -32
  714. package/src/providers/__tests__/satellite-connection-routing.test.ts +510 -0
  715. package/src/providers/__tests__/search-provider-catalog.test.ts +80 -0
  716. package/src/providers/anthropic/client.ts +123 -54
  717. package/src/providers/call-site-routing.ts +94 -16
  718. package/src/providers/connection-resolution.ts +170 -0
  719. package/src/providers/inference/__tests__/connections-status-label.test.ts +250 -0
  720. package/src/providers/inference/adapter-factory.ts +210 -0
  721. package/src/providers/inference/auth.ts +112 -0
  722. package/src/providers/inference/backfill.ts +196 -0
  723. package/src/providers/inference/connections.ts +401 -0
  724. package/src/providers/inference/resolve-auth.ts +73 -0
  725. package/src/providers/model-catalog.ts +386 -6
  726. package/src/providers/openai/chat-completions-provider.ts +10 -2
  727. package/src/providers/openai/responses-provider.ts +4 -2
  728. package/src/providers/openrouter/client.ts +7 -0
  729. package/src/providers/{managed-proxy → platform-proxy}/constants.ts +4 -1
  730. package/src/providers/{managed-proxy → platform-proxy}/context.ts +3 -3
  731. package/src/providers/provider-availability.ts +17 -2
  732. package/src/providers/provider-catalog-visibility.ts +36 -0
  733. package/src/providers/provider-env-vars.ts +17 -7
  734. package/src/providers/provider-secret-catalog.ts +49 -30
  735. package/src/providers/provider-send-message.ts +41 -20
  736. package/src/providers/registry.ts +151 -159
  737. package/src/providers/retry.ts +65 -11
  738. package/src/providers/search-provider-catalog.ts +121 -0
  739. package/src/runtime/AGENTS.md +18 -5
  740. package/src/runtime/__tests__/agent-wake.test.ts +152 -0
  741. package/src/runtime/__tests__/background-job-runner.test.ts +357 -0
  742. package/src/runtime/__tests__/pre-first-message-gate.test.ts +82 -0
  743. package/src/runtime/actor-trust-resolver.ts +32 -10
  744. package/src/runtime/agent-wake.ts +64 -7
  745. package/src/runtime/assistant-event-hub.ts +3 -85
  746. package/src/runtime/auth/route-policy.ts +311 -9
  747. package/src/runtime/auth/same-actor.ts +2 -0
  748. package/src/runtime/background-job-runner.ts +339 -0
  749. package/src/runtime/btw-sidechain.ts +3 -0
  750. package/src/runtime/http-router.ts +36 -1
  751. package/src/runtime/http-server.ts +31 -5
  752. package/src/runtime/http-types.ts +21 -0
  753. package/src/runtime/middleware/__tests__/request-logger.test.ts +162 -0
  754. package/src/runtime/middleware/request-logger.ts +62 -1
  755. package/src/runtime/migrations/origin-mode.ts +1 -1
  756. package/src/runtime/pending-interactions.ts +1 -0
  757. package/src/runtime/pre-first-message-gate.ts +83 -0
  758. package/src/runtime/routes/__tests__/backup-routes.test.ts +8 -1
  759. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +268 -0
  760. package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +142 -0
  761. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +319 -0
  762. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +280 -4
  763. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +15 -136
  764. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +736 -0
  765. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +4 -4
  766. package/src/runtime/routes/__tests__/question-routes.test.ts +395 -0
  767. package/src/runtime/routes/__tests__/stt-routes.test.ts +5 -1
  768. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +384 -0
  769. package/src/runtime/routes/__tests__/tts-routes.test.ts +70 -3
  770. package/src/runtime/routes/acp-routes-list.test.ts +143 -0
  771. package/src/runtime/routes/acp-routes.ts +12 -8
  772. package/src/runtime/routes/app-management-routes.ts +228 -3
  773. package/src/runtime/routes/approval-routes.ts +0 -18
  774. package/src/runtime/routes/audit-routes.ts +43 -0
  775. package/src/runtime/routes/auth-routes.ts +72 -0
  776. package/src/runtime/routes/avatar-routes.ts +273 -20
  777. package/src/runtime/routes/backup-routes.ts +406 -2
  778. package/src/runtime/routes/bookmark-routes.ts +156 -0
  779. package/src/runtime/routes/btw-routes.ts +5 -1
  780. package/src/runtime/routes/channel-availability-routes.ts +121 -0
  781. package/src/runtime/routes/channel-verification-routes.ts +2 -1
  782. package/src/runtime/routes/contact-routes.ts +0 -160
  783. package/src/runtime/routes/conversation-cli-routes.ts +233 -0
  784. package/src/runtime/routes/conversation-list-routes.ts +3 -20
  785. package/src/runtime/routes/conversation-management-routes.ts +47 -85
  786. package/src/runtime/routes/conversation-query-routes.ts +350 -97
  787. package/src/runtime/routes/conversation-routes.ts +121 -21
  788. package/src/runtime/routes/conversations-import-routes.ts +229 -0
  789. package/src/runtime/routes/credential-routes.ts +540 -0
  790. package/src/runtime/routes/debug-routes.ts +2 -2
  791. package/src/runtime/routes/document-pdf-renderer.ts +5 -1
  792. package/src/runtime/routes/documents-routes.ts +25 -86
  793. package/src/runtime/routes/domain-routes.ts +167 -0
  794. package/src/runtime/routes/email-routes.ts +603 -0
  795. package/src/runtime/routes/errors.ts +2 -2
  796. package/src/runtime/routes/events-routes.ts +192 -0
  797. package/src/runtime/routes/group-routes.ts +5 -0
  798. package/src/runtime/routes/home-feed-routes.ts +6 -78
  799. package/src/runtime/routes/host-app-control-routes.ts +44 -2
  800. package/src/runtime/routes/host-browser-routes.ts +103 -22
  801. package/src/runtime/routes/http-adapter.ts +2 -0
  802. package/src/runtime/routes/identity-routes.ts +5 -0
  803. package/src/runtime/routes/image-generation-routes.ts +99 -0
  804. package/src/runtime/routes/inbound-conversation.ts +28 -8
  805. package/src/runtime/routes/inbound-message-handler.ts +236 -41
  806. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +248 -1
  807. package/src/runtime/routes/inbound-stages/background-dispatch.ts +118 -7
  808. package/src/runtime/routes/inbound-stages/edit-intercept.ts +17 -4
  809. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +156 -0
  810. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +22 -4
  811. package/src/runtime/routes/index.ts +42 -0
  812. package/src/runtime/routes/inference-profile-session-handler.ts +285 -0
  813. package/src/runtime/routes/inference-profile-session-reaper.ts +84 -0
  814. package/src/runtime/routes/inference-profile-session-routes.ts +146 -0
  815. package/src/runtime/routes/inference-provider-connection-routes.ts +361 -0
  816. package/src/runtime/routes/inference-send-routes.ts +115 -0
  817. package/src/runtime/routes/integrations/slack/share.ts +4 -52
  818. package/src/runtime/routes/integrations/slack/token.ts +43 -0
  819. package/src/runtime/routes/integrations/twilio.ts +7 -13
  820. package/src/runtime/routes/mcp-auth-routes.ts +283 -9
  821. package/src/runtime/routes/memory-v2-routes.ts +13 -398
  822. package/src/runtime/routes/notification-routes.ts +3 -1
  823. package/src/runtime/routes/oauth-apps.ts +112 -7
  824. package/src/runtime/routes/oauth-commands-routes.ts +1097 -0
  825. package/src/runtime/routes/oauth-connect-routes.ts +67 -5
  826. package/src/runtime/routes/oauth-lifecycle-routes.ts +43 -0
  827. package/src/runtime/routes/oauth-providers.ts +298 -8
  828. package/src/runtime/routes/platform-routes.ts +336 -0
  829. package/src/runtime/routes/playground/inject-failures.ts +2 -1
  830. package/src/runtime/routes/playground/reset-circuit.ts +2 -1
  831. package/src/runtime/routes/playground/state.ts +2 -1
  832. package/src/runtime/routes/publish-routes.ts +221 -0
  833. package/src/runtime/routes/question-routes.ts +259 -0
  834. package/src/runtime/routes/rename-conversation-routes.ts +2 -33
  835. package/src/runtime/routes/schedule-routes.ts +79 -0
  836. package/src/runtime/routes/sequence-routes.ts +291 -0
  837. package/src/runtime/routes/settings-routes.ts +2 -10
  838. package/src/runtime/routes/skills-routes.ts +31 -1
  839. package/src/runtime/routes/stt-routes.ts +240 -3
  840. package/src/runtime/routes/subagents-routes.ts +57 -18
  841. package/src/runtime/routes/surface-action-routes.ts +43 -7
  842. package/src/runtime/routes/telemetry-routes.ts +27 -0
  843. package/src/runtime/routes/tts-routes.ts +93 -1
  844. package/src/runtime/routes/types.ts +32 -0
  845. package/src/runtime/routes/user-routes-cli.ts +243 -0
  846. package/src/runtime/routes/webhook-routes.ts +165 -0
  847. package/src/runtime/routes/workspace-routes.test.ts +43 -0
  848. package/src/runtime/routes/workspace-routes.ts +28 -0
  849. package/src/runtime/services/conversation-serializer.ts +39 -7
  850. package/src/runtime/sync/resource-sync-events.ts +117 -0
  851. package/src/runtime/sync/sync-publisher.test.ts +105 -0
  852. package/src/runtime/sync/sync-publisher.ts +21 -0
  853. package/src/schedule/schedule-store.ts +27 -2
  854. package/src/schedule/scheduler.ts +208 -123
  855. package/src/security/__tests__/provider-key-env-fallback.test.ts +12 -6
  856. package/src/security/__tests__/untrusted-content.test.ts +86 -0
  857. package/src/security/secret-patterns.ts +3 -0
  858. package/src/security/untrusted-content.ts +93 -8
  859. package/src/sequence/engine.ts +38 -40
  860. package/src/skills/catalog-files.ts +1 -1
  861. package/src/skills/catalog-install.ts +233 -116
  862. package/src/skills/clawhub.ts +70 -13
  863. package/src/skills/managed-store.ts +4 -119
  864. package/src/skills/skillssh-registry.ts +27 -48
  865. package/src/subagent/manager.ts +28 -15
  866. package/src/telemetry/types.ts +113 -1
  867. package/src/telemetry/usage-telemetry-reporter.test.ts +312 -5
  868. package/src/telemetry/usage-telemetry-reporter.ts +113 -7
  869. package/src/tools/apps/executors.ts +58 -7
  870. package/src/tools/ask-question/ask-question-tool.test.ts +509 -0
  871. package/src/tools/ask-question/ask-question-tool.ts +304 -0
  872. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +206 -0
  873. package/src/tools/browser/browser-execution.ts +29 -14
  874. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +174 -0
  875. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +16 -13
  876. package/src/tools/browser/cdp-client/extension-cdp-client.ts +24 -1
  877. package/src/tools/browser/cdp-client/factory.ts +66 -5
  878. package/src/tools/browser/runtime-check.ts +77 -0
  879. package/src/tools/computer-use/definitions.ts +3 -3
  880. package/src/tools/credentials/vault.ts +1 -1
  881. package/src/tools/document/document-tool.ts +124 -1
  882. package/src/tools/filesystem/edit.ts +1 -1
  883. package/src/tools/filesystem/list.ts +1 -1
  884. package/src/tools/filesystem/read.ts +1 -1
  885. package/src/tools/filesystem/write.ts +5 -2
  886. package/src/tools/host-filesystem/transfer.ts +1 -1
  887. package/src/tools/host-terminal/host-shell.ts +1 -1
  888. package/src/tools/memory/register.test.ts +3 -3
  889. package/src/tools/memory/register.ts +9 -1
  890. package/src/tools/network/__tests__/web-search.test.ts +156 -0
  891. package/src/tools/network/web-search.ts +280 -37
  892. package/src/tools/permission-checker.ts +14 -6
  893. package/src/tools/registry.ts +17 -7
  894. package/src/tools/schedule/create.ts +2 -2
  895. package/src/tools/schema-transforms.ts +7 -2
  896. package/src/tools/side-effects.ts +1 -0
  897. package/src/tools/skills/delete-managed.ts +4 -4
  898. package/src/tools/skills/execute.ts +1 -1
  899. package/src/tools/skills/scaffold-managed.ts +3 -2
  900. package/src/tools/subagent/notify-parent.ts +1 -1
  901. package/src/tools/subagent/spawn.ts +3 -3
  902. package/src/tools/system/request-permission.ts +2 -2
  903. package/src/tools/terminal/safe-env.ts +60 -1
  904. package/src/tools/terminal/shell.ts +44 -0
  905. package/src/tools/tool-manifest.ts +2 -0
  906. package/src/tools/types.ts +72 -21
  907. package/src/tools/ui-surface/definitions.ts +6 -5
  908. package/src/tts/__tests__/provider-adapters.test.ts +76 -2
  909. package/src/tts/providers/elevenlabs-provider.ts +75 -1
  910. package/src/types/onboarding-context.ts +2 -0
  911. package/src/usage/attribution.ts +3 -2
  912. package/src/util/errors.ts +17 -0
  913. package/src/util/platform.ts +10 -0
  914. package/src/util/pricing.ts +86 -160
  915. package/src/watcher/__tests__/engine.test.ts +323 -0
  916. package/src/watcher/constants.ts +7 -0
  917. package/src/watcher/engine.ts +94 -90
  918. package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +6 -9
  919. package/src/workspace/migrations/054-seed-recall-callsite.ts +10 -1
  920. package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +94 -5
  921. package/src/workspace/migrations/069-seed-onboarding-threads.ts +8 -2
  922. package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +117 -0
  923. package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +95 -0
  924. package/src/workspace/migrations/074-drop-deprecated-secret-detection-keys.ts +117 -0
  925. package/src/workspace/migrations/075-memory-v2-bm25-b-default-reembed.ts +61 -0
  926. package/src/workspace/migrations/076-drop-services-inference-mode.ts +62 -0
  927. package/src/workspace/migrations/077-seed-memory-router-callsite.ts +89 -0
  928. package/src/workspace/migrations/078-release-notes-tavily-web-search.ts +66 -0
  929. package/src/workspace/migrations/079-home-feed-notification-only.ts +197 -0
  930. package/src/workspace/migrations/080-restrict-vercel-api-token-metadata.ts +182 -0
  931. package/src/workspace/migrations/081-backfill-bash-allowed-tools-for-injection-credentials.ts +160 -0
  932. package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +154 -0
  933. package/src/workspace/migrations/083-system-prompt-prefix-to-file.ts +191 -0
  934. package/src/workspace/migrations/084-remove-legacy-skills-index.ts +276 -0
  935. package/src/workspace/migrations/085-memory-v2-bm25-b-reembed-disabled-v2-pages.ts +137 -0
  936. package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +198 -0
  937. package/src/workspace/migrations/registry.ts +30 -0
  938. package/src/workspace/migrations/runner.ts +46 -5
  939. package/src/workspace/migrations/types.ts +17 -3
  940. package/src/workspace/provider-commit-message-generator.ts +3 -2
  941. package/examples/plugins/echo/bun.lock +0 -25
  942. package/src/__tests__/context-search-pkb-source.test.ts +0 -498
  943. package/src/__tests__/context-window-manager.test.ts +0 -2093
  944. package/src/__tests__/credentials-cli.test.ts +0 -1225
  945. package/src/__tests__/memory-admin-recall.test.ts +0 -213
  946. package/src/approvals/__tests__/guardian-feed-event.test.ts +0 -303
  947. package/src/cli/commands/__tests__/email-download.test.ts +0 -260
  948. package/src/cli/commands/__tests__/email-list.test.ts +0 -216
  949. package/src/cli/commands/__tests__/email-register.test.ts +0 -186
  950. package/src/cli/commands/__tests__/email-send.test.ts +0 -416
  951. package/src/cli/commands/__tests__/email-status.test.ts +0 -185
  952. package/src/cli/commands/__tests__/email-unregister.test.ts +0 -168
  953. package/src/cli/commands/__tests__/routes.test.ts +0 -562
  954. package/src/cli/commands/__tests__/stt-transcribe.test.ts +0 -454
  955. package/src/cli/commands/autonomy.ts +0 -365
  956. package/src/cli/commands/memory.ts +0 -424
  957. package/src/cli/commands/oauth/__tests__/connect.test.ts +0 -947
  958. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +0 -686
  959. package/src/cli/commands/oauth/__tests__/mode.test.ts +0 -632
  960. package/src/cli/commands/oauth/__tests__/ping.test.ts +0 -631
  961. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +0 -573
  962. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +0 -330
  963. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +0 -521
  964. package/src/cli/commands/oauth/__tests__/status.test.ts +0 -551
  965. package/src/cli/commands/oauth/__tests__/token.test.ts +0 -420
  966. package/src/cli/lib/daemon-avatar-client.ts +0 -37
  967. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -87
  968. package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +0 -207
  969. package/src/context/__tests__/compact-prompt.test.ts +0 -63
  970. package/src/context/prompts/compact.md +0 -26
  971. package/src/daemon/__tests__/conversation-feed-event.test.ts +0 -304
  972. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +0 -233
  973. package/src/home/__tests__/assistant-feed-authoring.test.ts +0 -156
  974. package/src/home/__tests__/emit-feed-event.test.ts +0 -169
  975. package/src/home/__tests__/feed-population-integration.test.ts +0 -312
  976. package/src/home/__tests__/feed-scheduler.test.ts +0 -222
  977. package/src/home/__tests__/phase5-exit-criteria.test.ts +0 -229
  978. package/src/home/__tests__/platform-gmail-digest.test.ts +0 -222
  979. package/src/home/__tests__/rollup-producer.test.ts +0 -507
  980. package/src/home/assistant-feed-authoring.ts +0 -135
  981. package/src/home/emit-feed-event.ts +0 -169
  982. package/src/home/feed-scheduler.ts +0 -281
  983. package/src/home/platform-gmail-digest.ts +0 -163
  984. package/src/home/rewrite-command-preview.ts +0 -66
  985. package/src/home/rewrite-feed-title.ts +0 -58
  986. package/src/home/rollup-producer.ts +0 -426
  987. package/src/memory/admin.ts +0 -326
  988. package/src/memory/context-search/sources/pkb.ts +0 -476
  989. package/src/memory/graph/compaction.ts +0 -299
  990. package/src/prompts/__tests__/build-cli-reference-section.test.ts +0 -37
  991. /package/src/cli/{commands → lib}/cache-fs.ts +0 -0
@@ -40,6 +40,7 @@ import {
40
40
  import { hydrate, save } from "./activation-store.js";
41
41
  import { getEdgeIndex } from "./edge-index.js";
42
42
  import { readPage, renderPageContent } from "./page-store.js";
43
+ import { runRouter } from "./router.js";
43
44
  import { getSkillCapability, isSkillSlug } from "./skill-store.js";
44
45
  import type { ActivationState, EverInjectedEntry } from "./types.js";
45
46
 
@@ -58,6 +59,16 @@ const log = getLogger("memory-v2-injection");
58
59
  */
59
60
  export type InjectMemoryV2Mode = "context-load" | "per-turn";
60
61
 
62
+ /**
63
+ * Internal mode union for `finalizeInjection`. Extends the public
64
+ * `InjectMemoryV2Mode` with `"router"` (router-driven success path) and
65
+ * `"errored"` (caller-supplied failure path or the helper's own
66
+ * try/catch promotion). The public surface intentionally only carries
67
+ * the caller-facing modes — these two are persistence/telemetry concerns
68
+ * that don't belong on `InjectMemoryV2BlockParams`.
69
+ */
70
+ type FinalizeInjectionMode = InjectMemoryV2Mode | "router" | "errored";
71
+
61
72
  export interface InjectMemoryV2BlockParams {
62
73
  /** SQLite database handle for activation_state hydrate/save. */
63
74
  database: DrizzleDb;
@@ -94,8 +105,12 @@ export interface InjectMemoryV2BlockResult {
94
105
  */
95
106
  block: string | null;
96
107
  /**
97
- * Slugs that were freshly attached on this turn. Empty when `block` is
98
- * null. Returned for telemetry / debug logging by the call site.
108
+ * Slugs we attempted to attach this turn (top-K minus everInjected).
109
+ * Always populated even when `block` is `null` phantom slugs whose
110
+ * backing page is missing on disk land here and are recorded in
111
+ * `everInjected` so we don't infinite-retry next turn. Callers using
112
+ * this for "we injected N slugs" telemetry should cross-reference
113
+ * `block !== null` (or the activation log's `page_missing` status).
99
114
  */
100
115
  toInject: string[];
101
116
  }
@@ -129,12 +144,41 @@ export async function injectMemoryV2Block(
129
144
  } = params;
130
145
 
131
146
  const workspaceDir = getWorkspaceDir();
147
+ const mode: InjectMemoryV2Mode = params.mode ?? "per-turn";
132
148
 
133
149
  // (1) Hydrate. Missing rows are normal at conversation start — proceed
134
150
  // with an effective empty prior state so the first turn can still inject.
135
151
  throwIfAborted(signal);
136
152
  const priorState = await hydrate(database, conversationId);
137
153
 
154
+ // Flag-gated router dispatch: when the LLM router is enabled, route the
155
+ // page selection through `runRouter` and reuse `finalizeInjection` for
156
+ // persistence, render, and telemetry. The activation pipeline below
157
+ // remains the default (flag-off) behavior — every code path past this
158
+ // branch only runs when the router is disabled.
159
+ //
160
+ // Runs on both `per-turn` and `context-load`. The `everInjected` dedupe
161
+ // concern from earlier doesn't apply post-compaction because
162
+ // `evictCompactedTurnsV2` in `ConversationGraphMemory.onCompacted`
163
+ // empties the list before this code runs. Router abstention on
164
+ // context-load means no v2 pages restored that turn, which is preferable
165
+ // to letting the activation graph pick something arbitrary.
166
+ if (config.memory.v2.router.enabled) {
167
+ return injectViaRouter({
168
+ workspaceDir,
169
+ database,
170
+ conversationId,
171
+ currentTurn,
172
+ userMessage,
173
+ assistantMessage,
174
+ nowText,
175
+ messageId,
176
+ config,
177
+ priorState,
178
+ signal,
179
+ });
180
+ }
181
+
138
182
  // (2) Topology. `getEdgeIndex` walks concept-page frontmatter and caches
139
183
  // the result module-locally; an empty workspace yields an empty index.
140
184
  throwIfAborted(signal);
@@ -178,7 +222,6 @@ export async function injectMemoryV2Block(
178
222
  // prior cached attachments don't exist or have been thrown away. The user
179
223
  // message gets a complete top-K dump alongside the static
180
224
  // essentials/threads/recent block, then per-turn turns just add deltas.
181
- const mode = params.mode ?? "per-turn";
182
225
  const priorEverInjected: readonly EverInjectedEntry[] =
183
226
  priorState?.everInjected ?? [];
184
227
  const { topNow, toInject } = selectInjections({
@@ -192,11 +235,116 @@ export async function injectMemoryV2Block(
192
235
  // even on a "no new injection" turn, prior-state activations decay via the
193
236
  // candidate-set carry-forward and need to be rewritten so `epsilon`-trimmed
194
237
  // slugs drop out of consideration next turn.
195
- const nextState: Record<string, number> = {};
238
+ const nextStateMap: Record<string, number> = {};
196
239
  for (const [slug, value] of finalActivation) {
197
- if (value > epsilon) nextState[slug] = value;
240
+ if (value > epsilon) nextStateMap[slug] = value;
198
241
  }
199
242
 
243
+ // Build the rich per-candidate telemetry rows up front (status assigned
244
+ // later by `finalizeInjection` once we know what actually rendered).
245
+ const telemetryRows: MemoryV2ConceptRowRecord[] = [...candidates].map(
246
+ (slug) => {
247
+ const breakdown = ownBreakdown.get(slug);
248
+ const inPrior = fromPrior.has(slug);
249
+ const inAnn = fromAnn.has(slug);
250
+ return {
251
+ slug,
252
+ finalActivation: finalActivation.get(slug) ?? 0,
253
+ ownActivation: ownActivation.get(slug) ?? 0,
254
+ priorActivation: breakdown?.priorContribution ?? 0,
255
+ simUser: breakdown?.simUser ?? 0,
256
+ simAssistant: breakdown?.simAssistant ?? 0,
257
+ simNow: breakdown?.simNow ?? 0,
258
+ simUserRerankBoost: breakdown?.simUserRerankBoost ?? 0,
259
+ simAssistantRerankBoost: breakdown?.simAssistantRerankBoost ?? 0,
260
+ inRerankPool: breakdown?.inRerankPool ?? false,
261
+ spreadContribution: spreadContribution.get(slug) ?? 0,
262
+ source:
263
+ inPrior && inAnn ? "both" : inPrior ? "prior_state" : "ann_top50",
264
+ status: "not_injected",
265
+ };
266
+ },
267
+ );
268
+
269
+ return finalizeInjection({
270
+ workspaceDir,
271
+ database,
272
+ conversationId,
273
+ mode,
274
+ currentTurn,
275
+ messageId,
276
+ priorEverInjected,
277
+ slugsToRender,
278
+ telemetryRows,
279
+ config,
280
+ nextStateMap,
281
+ });
282
+ }
283
+
284
+ /**
285
+ * Tail of `injectMemoryV2Block` extracted as a private helper so the
286
+ * router branch (PR 10) can reuse the same persistence + render +
287
+ * telemetry-finalization pipeline. Performs:
288
+ *
289
+ * 1. Build `nextEverInjected` from `slugsToRender`, filtering out skill
290
+ * slugs whose capability cache entry is missing so future turns
291
+ * re-attempt attachment once the cache is populated.
292
+ * 2. Persist the next activation_state row.
293
+ * 3. Render the injection block.
294
+ * 4. Finalize per-row `status` (`injected | in_context | not_injected |
295
+ * page_missing | corrupt`) on the caller-provided telemetry rows
296
+ * using the render result.
297
+ * 5. Sort rows by `finalActivation` descending and flush the activation
298
+ * log — even when an error is thrown partway through, so silent
299
+ * failures remain observable.
300
+ * 6. Return the rendered block plus `toInject = newlyInjected`.
301
+ *
302
+ * The caller pre-builds `telemetryRows` with all per-candidate breakdown
303
+ * fields filled in (router-mode callers can pass zeros where the
304
+ * breakdown doesn't apply) and a placeholder `status: "not_injected"`
305
+ * which this helper overwrites. `nextStateMap` is the activation
306
+ * pipeline's sparse next-state; router-mode callers pass an empty map.
307
+ */
308
+ async function finalizeInjection(args: {
309
+ workspaceDir: string;
310
+ database: DrizzleDb;
311
+ conversationId: string;
312
+ mode: FinalizeInjectionMode;
313
+ currentTurn: number;
314
+ messageId: string;
315
+ priorEverInjected: readonly EverInjectedEntry[];
316
+ slugsToRender: string[];
317
+ telemetryRows: MemoryV2ConceptRowRecord[];
318
+ config: AssistantConfig;
319
+ nextStateMap: Record<string, number>;
320
+ /**
321
+ * When true, errors thrown inside the helper (save / render / status
322
+ * finalization) are logged and swallowed instead of re-thrown. Used by
323
+ * the router-failure path, which is already a best-effort cleanup: a
324
+ * transient SQLite write here must not abort the turn on top of the
325
+ * router failure that already happened. Defaults to throwing.
326
+ */
327
+ bestEffort?: boolean;
328
+ }): Promise<InjectMemoryV2BlockResult> {
329
+ const {
330
+ workspaceDir,
331
+ database,
332
+ conversationId,
333
+ currentTurn,
334
+ messageId,
335
+ priorEverInjected,
336
+ slugsToRender,
337
+ telemetryRows,
338
+ config,
339
+ nextStateMap,
340
+ } = args;
341
+
342
+ // `mode` is `let` because the trailing try/finally promotes it to "errored"
343
+ // when the render/telemetry path throws — we still want a log row written
344
+ // (with whatever rows we managed to build) so silent failures are
345
+ // observable in the database.
346
+ let mode: FinalizeInjectionMode = args.mode;
347
+
200
348
  // Mark every rendered slug as ever-injected so future per-turn deltas don't
201
349
  // re-attach the same content. On context-load this is the full top-K (we
202
350
  // just rendered all of them); on per-turn it's just the newly added slugs.
@@ -206,9 +354,21 @@ export async function injectMemoryV2Block(
206
354
  // like concept slugs — once attached on a turn, the cached attachment lives
207
355
  // on that user message and the agent keeps seeing it across subsequent turns
208
356
  // until compaction evicts the turn.
357
+ //
358
+ // Skill slugs whose in-process cache entry is missing (e.g. startup race
359
+ // between the skill seed and the first turn, or stale Qdrant index pointing
360
+ // at an uninstalled skill) are excluded from `everInjected` so future
361
+ // per-turn runs re-attempt attachment once the cache is populated. Without
362
+ // this, the slug would be marked injected even though `renderInjectionBlock`
363
+ // silently dropped it.
364
+ const missingSkillSlugs = new Set(
365
+ slugsToRender.filter(
366
+ (slug) => isSkillSlug(slug) && !getSkillCapability(slug),
367
+ ),
368
+ );
209
369
  const everInjectedSet = new Set(priorEverInjected.map((entry) => entry.slug));
210
370
  const newlyInjected = slugsToRender.filter(
211
- (slug) => !everInjectedSet.has(slug),
371
+ (slug) => !everInjectedSet.has(slug) && !missingSkillSlugs.has(slug),
212
372
  );
213
373
  const nextEverInjected: EverInjectedEntry[] = [
214
374
  ...priorEverInjected,
@@ -217,62 +377,76 @@ export async function injectMemoryV2Block(
217
377
 
218
378
  const nextActivationState: ActivationState = {
219
379
  messageId,
220
- state: nextState,
380
+ state: nextStateMap,
221
381
  everInjected: nextEverInjected,
222
382
  currentTurn,
223
383
  updatedAt: Date.now(),
224
384
  };
225
385
 
226
- await save(database, conversationId, nextActivationState);
386
+ // `block` and `conceptRowsForLog` are declared outside the try so the
387
+ // finally block can flush activation telemetry even if rendering, status
388
+ // finalization, or the activation-state save throws partway through.
389
+ // Without this, a Zod failure on a single concept page (e.g. unrecognized
390
+ // frontmatter key) silently dropped the entire turn's activation log row,
391
+ // masking the underlying data-corruption bug.
392
+ //
393
+ // `conceptRowsForLog` only receives the caller-provided `telemetryRows`
394
+ // *after* status finalization succeeds — matching the prior behavior where
395
+ // an early `save()` / `renderInjectionBlock()` throw produced an empty
396
+ // `concepts` array on the log row.
397
+ let block: string | null = null;
398
+ let conceptRowsForLog: MemoryV2ConceptRowRecord[] = [];
399
+ let caughtErr: unknown = undefined;
227
400
 
228
- // Render before recording telemetry so the activation log can mark slugs
229
- // whose backing file is gone — those are no-op renders that would otherwise
230
- // be indistinguishable from successful "injected" rows in the log.
231
- // `renderInjectionBlock` itself short-circuits on empty inputs.
232
- const { block, missingSlugs } = await renderInjectionBlock(
233
- workspaceDir,
234
- slugsToRender,
235
- );
236
- const missingSlugSet = new Set(missingSlugs);
237
- if (missingSlugs.length > 0) {
238
- log.warn(
239
- {
240
- conversationId,
241
- turn: currentTurn,
242
- missingSlugs,
243
- renderedCount: slugsToRender.length - missingSlugs.length,
244
- },
245
- "Memory v2 injection skipped slugs whose page was missing on disk — Qdrant index may be stale; consider reembed",
246
- );
247
- }
401
+ try {
402
+ await save(database, conversationId, nextActivationState);
403
+
404
+ // Render before recording telemetry so the activation log can mark slugs
405
+ // whose backing file is gone or failed to load — those are no-op renders
406
+ // that would otherwise be indistinguishable from successful "injected"
407
+ // rows in the log. `renderInjectionBlock` itself short-circuits on empty
408
+ // inputs and emits per-slug `log.warn` for each corrupt page.
409
+ const rendered = await renderInjectionBlock(workspaceDir, slugsToRender);
410
+ block = rendered.block;
411
+ const { missingSlugs, corruptSlugs } = rendered;
412
+ const missingSlugSet = new Set(missingSlugs);
413
+ const corruptSlugSet = new Set(corruptSlugs);
414
+ if (missingSlugs.length > 0) {
415
+ log.warn(
416
+ {
417
+ conversationId,
418
+ turn: currentTurn,
419
+ missingSlugs,
420
+ renderedCount:
421
+ slugsToRender.length - missingSlugs.length - corruptSlugs.length,
422
+ },
423
+ "Memory v2 injection skipped slugs whose page was missing on disk — Qdrant index may be stale; consider reembed",
424
+ );
425
+ }
248
426
 
249
- // Record per-turn activation telemetry. Failures are warn-logged and never
250
- // block memory injection.
251
- const toInjectSet = new Set(toInject);
252
- const renderedSet = new Set(slugsToRender);
253
- const conceptRows: MemoryV2ConceptRowRecord[] = [...candidates].map(
254
- (slug) => {
255
- const breakdown = ownBreakdown.get(slug);
256
- const inPrior = fromPrior.has(slug);
257
- const inAnn = fromAnn.has(slug);
258
- // Status reflects what was rendered for *this* turn:
259
- // - context-load: cache was wiped (turn 1 / post-compaction), so
260
- // `slugsToRender = topNow` and every rendered slug is freshly
261
- // injected on this turn. `in_context` is unreachable because there
262
- // is no prior cached attachment for the inspector to point at.
263
- // - per-turn: cached attachments from prior turns are still on the
264
- // user message, so prior-everInjected slugs are `in_context` and
265
- // the delta (`toInject`) is `injected`.
266
- // `page_missing` overrides any "would-have-been-injected" status when
267
- // `readPage` returned null for the slug — telemetry surfaces stale
268
- // ANN/edge entries instead of silently masquerading as a successful
269
- // injection.
427
+ // Finalize per-row status onto the caller-provided telemetry rows.
428
+ // - context-load: cache was wiped (turn 1 / post-compaction), so
429
+ // `slugsToRender = topNow` and every rendered slug is freshly
430
+ // injected on this turn. `in_context` is unreachable because there
431
+ // is no prior cached attachment for the inspector to point at.
432
+ // - per-turn: cached attachments from prior turns are still on the
433
+ // user message, so prior-everInjected slugs are `in_context` and
434
+ // the delta (`slugsToRender`, which equals `toInject` in this mode)
435
+ // is `injected`.
436
+ // `page_missing` and `corrupt` override any "would-have-been-injected"
437
+ // status when `readPage` returned null or threw telemetry surfaces
438
+ // stale ANN/edge entries and malformed pages instead of silently
439
+ // masquerading as successful injections. `corrupt` takes priority over
440
+ // `page_missing` since they're mutually exclusive per slug.
441
+ const renderedSet = new Set(slugsToRender);
442
+ for (const row of telemetryRows) {
443
+ const slug = row.slug;
270
444
  let status: MemoryV2ConceptRowRecord["status"];
271
445
  if (mode === "context-load") {
272
446
  status = renderedSet.has(slug) ? "injected" : "not_injected";
273
447
  } else if (everInjectedSet.has(slug)) {
274
448
  status = "in_context";
275
- } else if (toInjectSet.has(slug)) {
449
+ } else if (renderedSet.has(slug)) {
276
450
  status = "injected";
277
451
  } else {
278
452
  status = "not_injected";
@@ -280,52 +454,206 @@ export async function injectMemoryV2Block(
280
454
  if (status === "injected" && missingSlugSet.has(slug)) {
281
455
  status = "page_missing";
282
456
  }
283
- return {
284
- slug,
285
- finalActivation: finalActivation.get(slug) ?? 0,
286
- ownActivation: ownActivation.get(slug) ?? 0,
287
- priorActivation: breakdown?.priorContribution ?? 0,
288
- simUser: breakdown?.simUser ?? 0,
289
- simAssistant: breakdown?.simAssistant ?? 0,
290
- simNow: breakdown?.simNow ?? 0,
291
- simUserRerankBoost: breakdown?.simUserRerankBoost ?? 0,
292
- simAssistantRerankBoost: breakdown?.simAssistantRerankBoost ?? 0,
293
- inRerankPool: breakdown?.inRerankPool ?? false,
294
- spreadContribution: spreadContribution.get(slug) ?? 0,
295
- source:
296
- inPrior && inAnn ? "both" : inPrior ? "prior_state" : "ann_top50",
297
- status,
298
- };
299
- },
300
- );
301
- conceptRows.sort((a, b) => b.finalActivation - a.finalActivation);
302
-
303
- const v2Cfg = config.memory.v2;
304
- try {
305
- recordMemoryV2ActivationLog({
306
- conversationId,
307
- turn: currentTurn,
308
- mode,
309
- concepts: conceptRows,
310
- config: {
311
- d: v2Cfg.d,
312
- c_user: v2Cfg.c_user,
313
- c_assistant: v2Cfg.c_assistant,
314
- c_now: v2Cfg.c_now,
315
- k: v2Cfg.k,
316
- hops: v2Cfg.hops,
317
- top_k: v2Cfg.top_k,
318
- epsilon: v2Cfg.epsilon,
319
- },
320
- });
457
+ if (corruptSlugSet.has(slug)) {
458
+ status = "corrupt";
459
+ }
460
+ row.status = status;
461
+ }
462
+ telemetryRows.sort((a, b) => b.finalActivation - a.finalActivation);
463
+ conceptRowsForLog = telemetryRows;
321
464
  } catch (err) {
465
+ // Stash the error and let `finally` flush a best-effort telemetry row
466
+ // before we re-throw to the caller. `mode = "errored"` flags the row
467
+ // for observability dashboards / inspector queries. On the best-effort
468
+ // path the error is logged and swallowed so the trailing return stands.
469
+ caughtErr = err;
470
+ mode = "errored";
471
+ if (args.bestEffort) {
472
+ log.warn(
473
+ { err, conversationId, turn: currentTurn },
474
+ "Memory v2 finalizeInjection error on best-effort path — swallowing",
475
+ );
476
+ }
477
+ } finally {
478
+ try {
479
+ recordMemoryV2ActivationLog({
480
+ conversationId,
481
+ turn: currentTurn,
482
+ mode,
483
+ concepts: conceptRowsForLog,
484
+ config: configSnapshot(config),
485
+ });
486
+ } catch (telemetryErr) {
487
+ log.warn(
488
+ { err: telemetryErr, conversationId, turn: currentTurn },
489
+ "Failed to record memory v2 activation telemetry — continuing",
490
+ );
491
+ }
492
+ }
493
+
494
+ if (caughtErr !== undefined && !args.bestEffort) throw caughtErr;
495
+ return { block, toInject: newlyInjected };
496
+ }
497
+
498
+ /**
499
+ * Router-mode dispatch path. Replaces the spreading-activation pipeline with
500
+ * a single LLM call that picks the per-turn concept-page set. On success we
501
+ * reuse `finalizeInjection` so the persistence/render/telemetry contract
502
+ * stays identical to the activation path; on `runRouter` failure we still
503
+ * advance `activation_state` (so `currentTurn` and `messageId` move forward)
504
+ * and emit a `mode: "errored"` telemetry row so the failure is observable.
505
+ *
506
+ * Failure rows are tagged `errored`, not `router`, because router-mode rows
507
+ * are reserved for successful selections — keeping the two visually distinct
508
+ * in inspector queries. `nextStateMap` is always empty in router mode: the
509
+ * router does not compute spreading-activation scores, so there is no sparse
510
+ * activation map to persist.
511
+ */
512
+ async function injectViaRouter(args: {
513
+ workspaceDir: string;
514
+ database: DrizzleDb;
515
+ conversationId: string;
516
+ currentTurn: number;
517
+ userMessage: string;
518
+ assistantMessage: string;
519
+ nowText: string;
520
+ messageId: string;
521
+ config: AssistantConfig;
522
+ priorState: ActivationState | null;
523
+ signal?: AbortSignal;
524
+ }): Promise<InjectMemoryV2BlockResult> {
525
+ const {
526
+ workspaceDir,
527
+ database,
528
+ conversationId,
529
+ currentTurn,
530
+ userMessage,
531
+ assistantMessage,
532
+ nowText,
533
+ messageId,
534
+ config,
535
+ priorState,
536
+ signal,
537
+ } = args;
538
+
539
+ const priorEverInjected: readonly EverInjectedEntry[] =
540
+ priorState?.everInjected ?? [];
541
+
542
+ const routerResult = await runRouter({
543
+ workspaceDir,
544
+ userMessage,
545
+ assistantMessage,
546
+ nowText,
547
+ priorEverInjected,
548
+ config,
549
+ ...(signal ? { signal } : {}),
550
+ });
551
+
552
+ if (routerResult.failureReason !== null) {
322
553
  log.warn(
323
- { err, conversationId, turn: currentTurn },
324
- "Failed to record memory v2 activation telemetry continuing",
554
+ { failureReason: routerResult.failureReason },
555
+ "memory v2 router failure; skipping injection",
325
556
  );
557
+ // Delegate the failure path to `finalizeInjection` with empty inputs
558
+ // and `mode: "errored"`. The helper persists a stub activation_state
559
+ // (preserving `priorEverInjected` so future turns still subtract
560
+ // previously-attached slugs) and writes the telemetry row through the
561
+ // same code path as the success branch — no inline duplication of
562
+ // `save` + `recordMemoryV2ActivationLog`. `bestEffort: true` matches
563
+ // the pre-refactor inline behavior of logging and continuing if the
564
+ // stub-state `save()` throws — we don't want a transient SQLite write
565
+ // to abort the turn on top of the router failure that already happened.
566
+ return finalizeInjection({
567
+ workspaceDir,
568
+ database,
569
+ conversationId,
570
+ mode: "errored",
571
+ currentTurn,
572
+ messageId,
573
+ priorEverInjected,
574
+ slugsToRender: [],
575
+ telemetryRows: [],
576
+ config,
577
+ nextStateMap: {},
578
+ bestEffort: true,
579
+ });
326
580
  }
327
581
 
328
- return { block, toInject: newlyInjected };
582
+ // Dedupe router-picked slugs against `priorEverInjected` BEFORE rendering.
583
+ // The router prompt explicitly invites the model to re-pick already-injected
584
+ // pages "to re-anchor"; if we passed those through, `renderInjectionBlock`
585
+ // would re-emit the slug into a fresh `<memory>` block while the prior
586
+ // turn's cached attachment is still on the prior user message — duplicate
587
+ // content. Activation per-turn mode does not have this issue because
588
+ // `selectInjections()` returns `toInject = topNow - everInjected`.
589
+ //
590
+ // Telemetry rows for prior-everInjected slugs are still emitted below,
591
+ // but tagged `source: "carry_over"` (not `"router"`) so inspector queries
592
+ // can attribute selections correctly.
593
+ const everInjectedSet = new Set(priorEverInjected.map((e) => e.slug));
594
+ const slugsToRender = routerResult.selectedSlugs.filter(
595
+ (s) => !everInjectedSet.has(s),
596
+ );
597
+
598
+ // Build minimal telemetry rows for the union of router-selected slugs and
599
+ // prior `everInjected` slugs. Router-mode rows zero out every activation
600
+ // value (no spreading activation runs). Slugs the router picked this turn
601
+ // get `source: "router"`; prior-everInjected slugs the router did NOT
602
+ // re-pick get `source: "carry_over"`. The `status` placeholder is
603
+ // overwritten by `finalizeInjection`.
604
+ const routerPicked = new Set(routerResult.selectedSlugs);
605
+ const telemetrySlugs = new Set<string>(routerPicked);
606
+ for (const entry of priorEverInjected) telemetrySlugs.add(entry.slug);
607
+ const telemetryRows: MemoryV2ConceptRowRecord[] = [...telemetrySlugs].map(
608
+ (slug) => ({
609
+ slug,
610
+ finalActivation: 0,
611
+ ownActivation: 0,
612
+ priorActivation: 0,
613
+ simUser: 0,
614
+ simAssistant: 0,
615
+ simNow: 0,
616
+ simUserRerankBoost: 0,
617
+ simAssistantRerankBoost: 0,
618
+ inRerankPool: false,
619
+ spreadContribution: 0,
620
+ source: routerPicked.has(slug) ? "router" : "carry_over",
621
+ status: "not_injected",
622
+ }),
623
+ );
624
+
625
+ return finalizeInjection({
626
+ workspaceDir,
627
+ database,
628
+ conversationId,
629
+ mode: "router",
630
+ currentTurn,
631
+ messageId,
632
+ priorEverInjected,
633
+ slugsToRender,
634
+ telemetryRows,
635
+ config,
636
+ nextStateMap: {},
637
+ });
638
+ }
639
+
640
+ /**
641
+ * Snapshot the v2 config tunables in the shape `recordMemoryV2ActivationLog`
642
+ * persists. Pulled out so the router-failure path does not duplicate the
643
+ * field list inline.
644
+ */
645
+ function configSnapshot(config: AssistantConfig) {
646
+ const v2Cfg = config.memory.v2;
647
+ return {
648
+ d: v2Cfg.d,
649
+ c_user: v2Cfg.c_user,
650
+ c_assistant: v2Cfg.c_assistant,
651
+ c_now: v2Cfg.c_now,
652
+ k: v2Cfg.k,
653
+ hops: v2Cfg.hops,
654
+ top_k: v2Cfg.top_k,
655
+ epsilon: v2Cfg.epsilon,
656
+ };
329
657
  }
330
658
 
331
659
  function throwIfAborted(signal: AbortSignal | undefined): void {
@@ -358,14 +686,24 @@ interface RenderInjectionBlockResult {
358
686
  * edge-index entries that pointed at pages no longer on disk.
359
687
  */
360
688
  missingSlugs: string[];
689
+ /**
690
+ * Slugs whose `readPage` call threw (e.g. invalid frontmatter that fails
691
+ * Zod validation, unreadable file). These are reported separately from
692
+ * `missingSlugs` because they're a different failure mode — the file
693
+ * exists but is malformed, not absent — and surfaced so the caller can
694
+ * mark them in the activation log (`status: "corrupt"`). Per-page errors
695
+ * are isolated: one bad page no longer rejects the whole batch.
696
+ */
697
+ corruptSlugs: string[];
361
698
  }
362
699
 
363
700
  /**
364
- * Leading instruction line emitted at the top of every non-empty injection
365
- * block. Tells the agent that what follows are page summaries and that it
366
- * should read the underlying file when a summary looks relevant. Pages
367
- * without a `summary` field render in full instead the agent treats
368
- * those as inline content and doesn't need to follow up.
701
+ * Leading instruction line emitted at the top of an injection block when at
702
+ * least one section was rendered from a page's `summary` field. Tells the
703
+ * agent the truncated entries are summaries and to read the underlying file
704
+ * if relevant. Suppressed when every section is a full-page fallback
705
+ * claiming "these are summaries" over already-complete content would mislead
706
+ * the agent into wasted reads.
369
707
  */
370
708
  const INJECTION_HEADER =
371
709
  "**CRITICAL:** These are page summaries. Read the page file if it looks relevant.";
@@ -380,11 +718,15 @@ const INJECTION_HEADER =
380
718
  * trailing `### Skills You Can Use` subsection; everything else is read
381
719
  * from disk via `readPage` and rendered as a concept-page section.
382
720
  *
383
- * Concept pages are read in parallel via `readPage`. Pages whose file has
384
- * gone missing between selection and render (e.g. consolidation deleted
385
- * them, folder reorg renamed the slug) are dropped from the rendered
386
- * block but reported back via `missingSlugs` so callers can surface the
387
- * divergence.
721
+ * Concept pages are read in parallel via `Promise.allSettled`. Per-page
722
+ * errors are isolated: a `readPage` rejection (e.g. invalid frontmatter
723
+ * failing Zod validation) collects the slug into `corruptSlugs` and the
724
+ * remaining pages still render normally. Pages whose file has gone missing
725
+ * between selection and render (e.g. consolidation deleted them, folder
726
+ * reorg renamed the slug) are dropped from the rendered block but reported
727
+ * back via `missingSlugs`. The two buckets are kept separate so callers can
728
+ * distinguish "file vanished" (stale index) from "file is malformed"
729
+ * (data-corruption / programmer error).
388
730
  *
389
731
  * Skill slugs whose entry the cache no longer knows (e.g. uninstalled
390
732
  * mid-run) are silently dropped, mirroring the missing-pages behavior but
@@ -424,16 +766,26 @@ async function renderInjectionBlock(
424
766
  const conceptSlugs = slugs.filter((s) => !isSkillSlug(s));
425
767
  const skillSlugs = slugs.filter((s) => isSkillSlug(s));
426
768
 
427
- const pages = await Promise.all(
428
- conceptSlugs.map(async (slug) => {
429
- const page = await readPage(workspaceDir, slug);
430
- return { slug, page };
431
- }),
769
+ const settled = await Promise.allSettled(
770
+ conceptSlugs.map((slug) => readPage(workspaceDir, slug)),
432
771
  );
433
772
 
434
773
  const sections: string[] = [];
435
774
  const missingSlugs: string[] = [];
436
- for (const { slug, page } of pages) {
775
+ const corruptSlugs: string[] = [];
776
+ let anySummarySection = false;
777
+ for (let i = 0; i < settled.length; i++) {
778
+ const slug = conceptSlugs[i]!;
779
+ const result = settled[i]!;
780
+ if (result.status === "rejected") {
781
+ corruptSlugs.push(slug);
782
+ log.warn(
783
+ { slug, err: result.reason },
784
+ "Memory v2 injection skipped slug whose page failed to load — frontmatter may be malformed",
785
+ );
786
+ continue;
787
+ }
788
+ const page = result.value;
437
789
  if (!page) {
438
790
  missingSlugs.push(slug);
439
791
  continue;
@@ -442,6 +794,7 @@ async function renderInjectionBlock(
442
794
  const path = `memory/concepts/${slug}.md`;
443
795
  if (summary && summary.length > 0) {
444
796
  sections.push(`# ${path}\n${summary}`);
797
+ anySummarySection = true;
445
798
  continue;
446
799
  }
447
800
  // Fallback: page predates the `summary` field (or the field was set to
@@ -462,10 +815,14 @@ async function renderInjectionBlock(
462
815
  sections.push(`### Skills You Can Use\n${skillLines.join("\n")}`);
463
816
  }
464
817
 
465
- if (sections.length === 0) return { block: null, missingSlugs };
818
+ if (sections.length === 0) {
819
+ return { block: null, missingSlugs, corruptSlugs };
820
+ }
466
821
 
822
+ const body = sections.join("\n\n");
467
823
  return {
468
- block: `${INJECTION_HEADER}\n\n${sections.join("\n\n")}`,
824
+ block: anySummarySection ? `${INJECTION_HEADER}\n\n${body}` : body,
469
825
  missingSlugs,
826
+ corruptSlugs,
470
827
  };
471
828
  }