@vellumai/assistant 0.7.3 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (778) hide show
  1. package/AGENTS.md +11 -0
  2. package/ARCHITECTURE.md +29 -28
  3. package/Dockerfile +6 -4
  4. package/README.md +2 -2
  5. package/__tests__/permissions/gateway-threshold-reader.test.ts +236 -9
  6. package/bun.lock +3 -0
  7. package/docker-entrypoint.sh +16 -0
  8. package/eslint-rules/__tests__/cli-no-daemon-internals.test.ts +420 -0
  9. package/eslint-rules/cli-no-daemon-internals.js +283 -0
  10. package/eslint.config.mjs +12 -0
  11. package/knip.json +3 -1
  12. package/node_modules/@vellumai/ipc-server-utils/bun.lock +24 -0
  13. package/node_modules/@vellumai/ipc-server-utils/package.json +18 -0
  14. package/node_modules/@vellumai/ipc-server-utils/src/index.ts +6 -0
  15. package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.test.ts +430 -0
  16. package/node_modules/@vellumai/ipc-server-utils/src/socket-watchdog.ts +221 -0
  17. package/node_modules/@vellumai/ipc-server-utils/tsconfig.json +20 -0
  18. package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -1
  19. package/openapi.yaml +4126 -959
  20. package/package.json +5 -1
  21. package/scripts/generate-openapi.ts +52 -4
  22. package/scripts/sync-llm-catalog.ts +165 -0
  23. package/scripts/sync-web-search-catalog.ts +107 -0
  24. package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +169 -0
  25. package/src/__tests__/agent-loop-override-profile.test.ts +26 -1
  26. package/src/__tests__/annotate-risk-options.test.ts +291 -0
  27. package/src/__tests__/anthropic-provider.test.ts +92 -2
  28. package/src/__tests__/app-control-flow.test.ts +7 -0
  29. package/src/__tests__/approval-cascade.test.ts +8 -16
  30. package/src/__tests__/approval-routes-http.test.ts +6 -0
  31. package/src/__tests__/assistant-events-sse-shed.test.ts +232 -0
  32. package/src/__tests__/auto-analysis-end-to-end.test.ts +12 -25
  33. package/src/__tests__/avatar-identity-sync.test.ts +87 -0
  34. package/src/__tests__/background-workers-disk-pressure.test.ts +11 -22
  35. package/src/__tests__/btw-routes.test.ts +1 -0
  36. package/src/__tests__/call-constants.test.ts +10 -1
  37. package/src/__tests__/call-controller.test.ts +127 -0
  38. package/src/__tests__/call-site-routing-provider.test.ts +172 -45
  39. package/src/__tests__/cancel-resolves-conversation-key.test.ts +44 -3
  40. package/src/__tests__/channel-policy.test.ts +12 -0
  41. package/src/__tests__/checker.test.ts +89 -0
  42. package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +88 -30
  43. package/src/__tests__/compact-event-conversation-id-guard.test.ts +33 -5
  44. package/src/__tests__/compaction-strip-metadata-clear.test.ts +26 -1
  45. package/src/__tests__/config-loader-backfill.test.ts +526 -102
  46. package/src/__tests__/config-loader-corrupt.test.ts +68 -0
  47. package/src/__tests__/config-loader-platform-defaults.test.ts +345 -8
  48. package/src/__tests__/config-schema-cmd.test.ts +63 -29
  49. package/src/__tests__/config-schema.test.ts +14 -3
  50. package/src/__tests__/config-set-platform-guard.test.ts +75 -152
  51. package/src/__tests__/config-set-route.test.ts +198 -0
  52. package/src/__tests__/config-watcher.test.ts +6 -0
  53. package/src/__tests__/contacts-tools.test.ts +51 -199
  54. package/src/__tests__/context-search-agent-protocol.test.ts +21 -2
  55. package/src/__tests__/context-search-agent-runner.test.ts +22 -138
  56. package/src/__tests__/context-search-conversations-source.test.ts +42 -16
  57. package/src/__tests__/context-search-fanout.test.ts +20 -157
  58. package/src/__tests__/context-search-memory-source.test.ts +3 -26
  59. package/src/__tests__/context-search-memory-v2-source.test.ts +3 -3
  60. package/src/__tests__/context-search-types.test.ts +7 -2
  61. package/src/__tests__/context-window-manager.test.ts +389 -1
  62. package/src/__tests__/conversation-abort-tool-results.test.ts +1 -6
  63. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +1 -1
  64. package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -1
  65. package/src/__tests__/conversation-agent-loop.test.ts +3 -3
  66. package/src/__tests__/conversation-confirmation-signals.test.ts +5 -13
  67. package/src/__tests__/conversation-crud-inference-profile.test.ts +100 -0
  68. package/src/__tests__/conversation-error.test.ts +38 -0
  69. package/src/__tests__/conversation-fork-crud.test.ts +241 -1
  70. package/src/__tests__/conversation-inference-profile-route.test.ts +14 -14
  71. package/src/__tests__/conversation-init.benchmark.test.ts +2 -1
  72. package/src/__tests__/conversation-lifecycle.test.ts +124 -0
  73. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +100 -1
  74. package/src/__tests__/conversation-process-callsite.test.ts +22 -7
  75. package/src/__tests__/conversation-provider-retry-repair.test.ts +1 -6
  76. package/src/__tests__/conversation-runtime-assembly.test.ts +19 -10
  77. package/src/__tests__/conversation-slash-commands.test.ts +194 -2
  78. package/src/__tests__/conversation-slash-unknown.test.ts +1 -6
  79. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +170 -9
  80. package/src/__tests__/conversation-surfaces-app-control.test.ts +323 -3
  81. package/src/__tests__/conversation-surfaces-data-persist.test.ts +73 -1
  82. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +59 -0
  83. package/src/__tests__/conversation-workspace-injection.test.ts +1 -7
  84. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +1 -7
  85. package/src/__tests__/credential-security-invariants.test.ts +5 -6
  86. package/src/__tests__/daemon-credential-client.test.ts +56 -1
  87. package/src/__tests__/db-activation-state-fk-cascade.test.ts +132 -0
  88. package/src/__tests__/db-conversation-inference-profile-migration.test.ts +37 -0
  89. package/src/__tests__/db-memory-graph-event-date-repair.test.ts +43 -20
  90. package/src/__tests__/db-proxy-transaction.test.ts +206 -0
  91. package/src/__tests__/external-plugin-loader.test.ts +458 -0
  92. package/src/__tests__/filing-service.test.ts +25 -22
  93. package/src/__tests__/fixtures/mock-chrome-extension.ts +5 -0
  94. package/src/__tests__/gateway-only-guard.test.ts +0 -1
  95. package/src/__tests__/graph-extraction-event-date.test.ts +34 -0
  96. package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +10 -34
  97. package/src/__tests__/heartbeat-disk-pressure.test.ts +21 -8
  98. package/src/__tests__/heartbeat-service.test.ts +50 -233
  99. package/src/__tests__/history-repair.test.ts +89 -0
  100. package/src/__tests__/host-app-control-proxy.test.ts +109 -1
  101. package/src/__tests__/host-app-control-routes.test.ts +247 -1
  102. package/src/__tests__/host-browser-proxy.test.ts +416 -20
  103. package/src/__tests__/host-browser-routes.test.ts +325 -33
  104. package/src/__tests__/host-proxy-preactivation.test.ts +211 -0
  105. package/src/__tests__/inference-no-mode-boot-e2e.test.ts +246 -0
  106. package/src/__tests__/inference-profile-reaper.test.ts +154 -0
  107. package/src/__tests__/inference-profile-session-handler.test.ts +398 -0
  108. package/src/__tests__/inference-profile-session-ipc.test.ts +236 -0
  109. package/src/__tests__/injector-chain.test.ts +24 -16
  110. package/src/__tests__/injector-pkb-v2-silenced.test.ts +10 -7
  111. package/src/__tests__/inline-skill-load-permissions.test.ts +6 -1
  112. package/src/__tests__/install-skill-routing.test.ts +2 -2
  113. package/src/__tests__/lifecycle-memory-v2-seed.test.ts +169 -67
  114. package/src/__tests__/llm-callsite-catalog.test.ts +20 -1
  115. package/src/__tests__/llm-catalog-parity.test.ts +146 -0
  116. package/src/__tests__/llm-request-log-source-clickhouse.test.ts +188 -0
  117. package/src/__tests__/llm-request-log-source-factory.test.ts +124 -0
  118. package/src/__tests__/llm-resolver.test.ts +46 -0
  119. package/src/__tests__/managed-profile-guard.test.ts +131 -2
  120. package/src/__tests__/mcp-auth-routes.test.ts +1 -0
  121. package/src/__tests__/mcp-cli.test.ts +182 -220
  122. package/src/__tests__/mcp-health-check.test.ts +56 -27
  123. package/src/__tests__/memory-jobs-worker-lanes.test.ts +18 -11
  124. package/src/__tests__/message-complete-display-id.test.ts +175 -0
  125. package/src/__tests__/notification-decision-fallback.test.ts +91 -0
  126. package/src/__tests__/notification-decision-strategy.test.ts +22 -0
  127. package/src/__tests__/notification-platform-adapter.test.ts +229 -0
  128. package/src/__tests__/oauth-cli.test.ts +38 -1888
  129. package/src/__tests__/oauth-commands-routes.test.ts +711 -0
  130. package/src/__tests__/oauth-connect-routes.test.ts +174 -11
  131. package/src/__tests__/oauth-providers-routes.test.ts +14 -10
  132. package/src/__tests__/openai-responses-cutover-guard.test.ts +33 -12
  133. package/src/__tests__/openai-responses-provider.test.ts +17 -0
  134. package/src/__tests__/plugin-bootstrap.test.ts +31 -2
  135. package/src/__tests__/plugin-route-contribution.test.ts +31 -3
  136. package/src/__tests__/plugin-tool-contribution.test.ts +31 -3
  137. package/src/__tests__/plugin-types.test.ts +13 -11
  138. package/src/__tests__/process-message-background-slack.test.ts +46 -0
  139. package/src/__tests__/profile-entry-status.test.ts +43 -0
  140. package/src/__tests__/provider-managed-proxy-integration.test.ts +12 -4
  141. package/src/__tests__/provider-registry-ollama.test.ts +12 -4
  142. package/src/__tests__/provider-send-message-override-profile.test.ts +10 -4
  143. package/src/__tests__/relay-server.test.ts +164 -2
  144. package/src/__tests__/retry-thinking-tool-choice.test.ts +15 -0
  145. package/src/__tests__/schedule-retry.test.ts +56 -4
  146. package/src/__tests__/schedule-routes.test.ts +104 -0
  147. package/src/__tests__/scheduler-disk-pressure.test.ts +0 -4
  148. package/src/__tests__/scheduler-recurrence.test.ts +87 -34
  149. package/src/__tests__/scheduler-reuse-conversation.test.ts +161 -5
  150. package/src/__tests__/scheduler-wake.test.ts +0 -63
  151. package/src/__tests__/secret-allowlist.test.ts +1 -0
  152. package/src/__tests__/secret-prompt-log-hygiene.test.ts +7 -5
  153. package/src/__tests__/secret-prompter-channel-fallback.test.ts +7 -5
  154. package/src/__tests__/secret-response-routing.test.ts +7 -5
  155. package/src/__tests__/secret-routes-managed-proxy.test.ts +12 -4
  156. package/src/__tests__/server-history-render.test.ts +82 -0
  157. package/src/__tests__/shell-credential-ref.test.ts +95 -3
  158. package/src/__tests__/shell-tool-proxy-mode.test.ts +14 -0
  159. package/src/__tests__/skill-include-graph.test.ts +31 -0
  160. package/src/__tests__/skill-load-feature-flag.test.ts +1 -0
  161. package/src/__tests__/skill-load-tool.test.ts +42 -16
  162. package/src/__tests__/skills.test.ts +39 -0
  163. package/src/__tests__/subagent-call-site-routing.test.ts +78 -16
  164. package/src/__tests__/suggestion-routes.test.ts +3 -3
  165. package/src/__tests__/sync-message-contract.test.ts +63 -0
  166. package/src/__tests__/task-scheduler.test.ts +88 -23
  167. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -42
  168. package/src/__tests__/tool-executor.test.ts +155 -0
  169. package/src/__tests__/update-bulletin-job.test.ts +96 -193
  170. package/src/__tests__/usage-cli.test.ts +11 -73
  171. package/src/__tests__/user-plugin-loader.test.ts +145 -0
  172. package/src/__tests__/vercel-config.test.ts +168 -0
  173. package/src/__tests__/voice-session-bridge.test.ts +3 -0
  174. package/src/__tests__/web-search-catalog-parity.test.ts +86 -0
  175. package/src/__tests__/web-search.test.ts +303 -2
  176. package/src/__tests__/workspace-migration-039-drop-legacy-llm-keys.test.ts +1 -21
  177. package/src/__tests__/workspace-migration-057-repair-stale-gemini-model-ids.test.ts +58 -0
  178. package/src/__tests__/workspace-migration-069-seed-onboarding-threads.test.ts +153 -0
  179. package/src/__tests__/workspace-migration-071-remove-safe-storage-release-note.test.ts +206 -0
  180. package/src/__tests__/workspace-migration-072-seed-reply-suggestion-callsite.test.ts +191 -0
  181. package/src/__tests__/workspace-migration-076-drop-services-inference-mode.test.ts +211 -0
  182. package/src/__tests__/workspace-migration-077-seed-memory-router-callsite.test.ts +174 -0
  183. package/src/__tests__/workspace-migration-079-home-feed-notification-only.test.ts +323 -0
  184. package/src/__tests__/workspace-migration-080-restrict-vercel-api-token-metadata.test.ts +299 -0
  185. package/src/__tests__/workspace-migration-081-backfill-bash-allowed-tools.test.ts +410 -0
  186. package/src/__tests__/workspace-migration-082-backfill-managed-profile-labels.test.ts +268 -0
  187. package/src/__tests__/workspace-migration-safe-storage-limits-release.test.ts +15 -27
  188. package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +3 -3
  189. package/src/__tests__/workspace-release-notes-feature-flag-guard.test.ts +115 -0
  190. package/src/acp/__tests__/helpers/which-stub.ts +4 -2
  191. package/src/acp/resolve-agent.test.ts +25 -0
  192. package/src/acp/resolve-agent.ts +13 -2
  193. package/src/acp/session-manager.ts +14 -0
  194. package/src/agent/loop.ts +11 -0
  195. package/src/approvals/guardian-decision-primitive.ts +0 -13
  196. package/src/approvals/guardian-request-resolvers.ts +19 -102
  197. package/src/calls/call-constants.ts +5 -8
  198. package/src/calls/call-controller.ts +130 -67
  199. package/src/calls/relay-server.ts +42 -1
  200. package/src/calls/relay-setup-router.ts +36 -0
  201. package/src/calls/types.ts +1 -0
  202. package/src/calls/voice-session-bridge.ts +24 -5
  203. package/src/channels/config.ts +14 -1
  204. package/src/channels/types.ts +1 -0
  205. package/src/cli/AGENTS.md +164 -4
  206. package/src/cli/__tests__/notifications.test.ts +54 -0
  207. package/src/cli/commands/__tests__/avatar.test.ts +540 -0
  208. package/src/cli/commands/__tests__/backup.test.ts +236 -776
  209. package/src/cli/commands/__tests__/cache.test.ts +1 -1
  210. package/src/cli/commands/__tests__/changelog.test.ts +593 -0
  211. package/src/cli/commands/__tests__/channel-verification-sessions.test.ts +503 -0
  212. package/src/cli/commands/__tests__/conversations-import.test.ts +515 -0
  213. package/src/cli/commands/__tests__/domain-register.test.ts +140 -167
  214. package/src/cli/commands/__tests__/domain-status.test.ts +137 -76
  215. package/src/cli/commands/__tests__/email-attachment.test.ts +314 -337
  216. package/src/cli/commands/__tests__/email-core.test.ts +579 -0
  217. package/src/cli/commands/__tests__/image-generation.test.ts +87 -824
  218. package/src/cli/commands/__tests__/inference-send.test.ts +30 -266
  219. package/src/cli/commands/__tests__/inference-session.test.ts +423 -0
  220. package/src/cli/commands/__tests__/memory-v2.test.ts +81 -110
  221. package/src/cli/commands/__tests__/skills.test.ts +563 -0
  222. package/src/cli/commands/__tests__/status.test.ts +249 -0
  223. package/src/cli/commands/__tests__/stt.test.ts +320 -0
  224. package/src/cli/commands/__tests__/tts-synthesize.test.ts +4 -603
  225. package/src/cli/commands/__tests__/tts.test.ts +321 -0
  226. package/src/cli/commands/__tests__/webhooks.test.ts +86 -511
  227. package/src/cli/commands/attachment.ts +8 -3
  228. package/src/cli/commands/audit.ts +95 -64
  229. package/src/cli/commands/auth.ts +61 -58
  230. package/src/cli/commands/avatar.ts +276 -390
  231. package/src/cli/commands/backup.ts +409 -505
  232. package/src/cli/commands/bash.ts +9 -5
  233. package/src/cli/commands/browser.ts +28 -9
  234. package/src/cli/commands/cache.ts +9 -4
  235. package/src/cli/commands/changelog.ts +414 -0
  236. package/src/cli/commands/channel-verification-sessions.ts +238 -317
  237. package/src/cli/commands/clients.ts +8 -3
  238. package/src/cli/commands/completions.ts +9 -9
  239. package/src/cli/commands/config.ts +102 -72
  240. package/src/cli/commands/contacts.ts +575 -696
  241. package/src/cli/commands/conversations-defer.ts +17 -69
  242. package/src/cli/commands/conversations-import.ts +90 -253
  243. package/src/cli/commands/conversations.ts +346 -436
  244. package/src/cli/commands/credential-execution.ts +9 -6
  245. package/src/cli/commands/credentials.ts +456 -736
  246. package/src/cli/commands/domain.ts +128 -206
  247. package/src/cli/commands/email.ts +606 -794
  248. package/src/cli/commands/gateway.ts +8 -1
  249. package/src/cli/commands/image-generation.ts +157 -205
  250. package/src/cli/commands/inference-providers.ts +352 -0
  251. package/src/cli/commands/inference-session.ts +415 -0
  252. package/src/cli/commands/inference.ts +87 -65
  253. package/src/cli/commands/keys.ts +8 -3
  254. package/src/cli/commands/mcp.ts +103 -287
  255. package/src/cli/commands/memory-v2.ts +163 -517
  256. package/src/cli/commands/notifications.ts +33 -7
  257. package/src/cli/commands/oauth/apps.ts +292 -261
  258. package/src/cli/commands/oauth/connect.ts +182 -345
  259. package/src/cli/commands/oauth/disconnect.ts +16 -215
  260. package/src/cli/commands/oauth/index.ts +49 -45
  261. package/src/cli/commands/oauth/mode.ts +43 -199
  262. package/src/cli/commands/oauth/ping.ts +17 -125
  263. package/src/cli/commands/oauth/providers.ts +732 -921
  264. package/src/cli/commands/oauth/request.ts +60 -350
  265. package/src/cli/commands/oauth/shared.ts +11 -121
  266. package/src/cli/commands/oauth/status.ts +31 -121
  267. package/src/cli/commands/oauth/token.ts +13 -55
  268. package/src/cli/commands/pending.ts +19 -10
  269. package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +133 -183
  270. package/src/cli/commands/platform/__tests__/connect.test.ts +66 -181
  271. package/src/cli/commands/platform/__tests__/disconnect.test.ts +71 -227
  272. package/src/cli/commands/platform/__tests__/status.test.ts +169 -287
  273. package/src/cli/commands/platform/connect.ts +16 -80
  274. package/src/cli/commands/platform/disconnect.ts +14 -112
  275. package/src/cli/commands/platform/index.ts +177 -246
  276. package/src/cli/commands/routes.ts +153 -336
  277. package/src/cli/commands/sequence.ts +316 -360
  278. package/src/cli/commands/skills.ts +449 -671
  279. package/src/cli/commands/status.ts +58 -37
  280. package/src/cli/commands/stt.ts +94 -262
  281. package/src/cli/commands/task.ts +14 -40
  282. package/src/cli/commands/trust.ts +8 -3
  283. package/src/cli/commands/tts.ts +162 -167
  284. package/src/cli/commands/ui.ts +35 -42
  285. package/src/cli/commands/usage.ts +188 -126
  286. package/src/cli/commands/watchers.ts +8 -3
  287. package/src/cli/commands/webhooks.ts +99 -193
  288. package/src/cli/lib/__tests__/register-command.test.ts +85 -0
  289. package/src/cli/lib/daemon-credential-client.ts +4 -5
  290. package/src/cli/lib/nested-value.ts +44 -0
  291. package/src/cli/lib/open-browser.ts +36 -0
  292. package/src/cli/lib/register-command.ts +19 -0
  293. package/src/cli/lib/time-ago.ts +34 -0
  294. package/src/cli/program.ts +2 -4
  295. package/src/cli/utils/__tests__/conversation-id.test.ts +66 -0
  296. package/src/cli/utils/__tests__/parse-duration.test.ts +49 -0
  297. package/src/cli/utils/conversation-id.ts +30 -0
  298. package/src/cli/utils/parse-duration.ts +41 -0
  299. package/src/config/acp-defaults.test.ts +5 -1
  300. package/src/config/acp-defaults.ts +11 -4
  301. package/src/config/bundled-skills/acp/TOOLS.json +2 -2
  302. package/src/config/bundled-skills/app-builder/SKILL.md +1 -3
  303. package/src/config/bundled-skills/app-control/TOOLS.json +32 -0
  304. package/src/config/bundled-skills/contacts/SKILL.md +12 -45
  305. package/src/config/bundled-skills/contacts/TOOLS.json +0 -57
  306. package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +0 -12
  307. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +0 -58
  308. package/src/config/bundled-tool-registry.ts +0 -2
  309. package/src/config/feature-flag-registry.json +17 -17
  310. package/src/config/llm-resolver.ts +16 -1
  311. package/src/config/loader.ts +148 -33
  312. package/src/config/raw-config-utils.ts +2 -30
  313. package/src/config/schema.ts +4 -0
  314. package/src/config/schemas/__tests__/memory-v2.test.ts +49 -0
  315. package/src/config/schemas/call-site-catalog.ts +29 -7
  316. package/src/config/schemas/llm-request-logs.ts +57 -0
  317. package/src/config/schemas/llm.ts +52 -2
  318. package/src/config/schemas/memory-retrospective.ts +48 -0
  319. package/src/config/schemas/memory-v2.ts +33 -2
  320. package/src/config/schemas/memory.ts +4 -0
  321. package/src/config/schemas/services.ts +15 -12
  322. package/src/config/seed-inference-profiles.ts +195 -134
  323. package/src/contacts/contact-store.ts +0 -61
  324. package/src/context/window-manager.ts +191 -5
  325. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +111 -0
  326. package/src/daemon/__tests__/conversation-tool-setup.test.ts +109 -4
  327. package/src/daemon/__tests__/daemon-skill-host.test.ts +10 -4
  328. package/src/daemon/approval-generators.ts +23 -29
  329. package/src/daemon/config-watcher.ts +2 -0
  330. package/src/daemon/conversation-agent-loop-handlers.ts +56 -0
  331. package/src/daemon/conversation-agent-loop.ts +140 -107
  332. package/src/daemon/conversation-error.ts +21 -0
  333. package/src/daemon/conversation-lifecycle.ts +68 -13
  334. package/src/daemon/conversation-process.ts +36 -19
  335. package/src/daemon/conversation-runtime-assembly.ts +14 -5
  336. package/src/daemon/conversation-slash.ts +175 -23
  337. package/src/daemon/conversation-store.ts +17 -10
  338. package/src/daemon/conversation-surfaces.ts +92 -26
  339. package/src/daemon/conversation-tool-setup.ts +33 -19
  340. package/src/daemon/conversation.ts +49 -10
  341. package/src/daemon/external-plugins-bootstrap.ts +18 -8
  342. package/src/daemon/guardian-action-generators.ts +7 -22
  343. package/src/daemon/handlers/config-model.ts +8 -126
  344. package/src/daemon/handlers/config-slack-channel.ts +10 -7
  345. package/src/daemon/handlers/config-vercel.ts +3 -1
  346. package/src/daemon/handlers/shared.ts +26 -0
  347. package/src/daemon/handlers/skills.ts +84 -5
  348. package/src/daemon/history-repair.ts +33 -6
  349. package/src/daemon/host-app-control-proxy.ts +44 -19
  350. package/src/daemon/host-bash-proxy.ts +85 -158
  351. package/src/daemon/host-browser-proxy.ts +97 -36
  352. package/src/daemon/host-cu-proxy.ts +1 -1
  353. package/src/daemon/host-file-proxy.ts +1 -1
  354. package/src/daemon/host-proxy-base.ts +13 -1
  355. package/src/daemon/host-proxy-preactivation.ts +25 -1
  356. package/src/daemon/host-transfer-proxy.ts +2 -2
  357. package/src/daemon/identity-helpers.ts +19 -0
  358. package/src/daemon/lifecycle.ts +128 -114
  359. package/src/daemon/meet-host-supervisor.ts +15 -15
  360. package/src/daemon/memory-v2-startup.ts +62 -14
  361. package/src/daemon/message-protocol.ts +6 -0
  362. package/src/daemon/message-types/bookmarks.ts +18 -0
  363. package/src/daemon/message-types/conversations.ts +12 -9
  364. package/src/daemon/message-types/messages.ts +28 -2
  365. package/src/daemon/message-types/sync.ts +60 -0
  366. package/src/daemon/pkb-reminder-builder.test.ts +54 -13
  367. package/src/daemon/pkb-reminder-builder.ts +21 -7
  368. package/src/daemon/process-message.ts +56 -23
  369. package/src/daemon/server.ts +23 -18
  370. package/src/daemon/shutdown-handlers.ts +0 -2
  371. package/src/daemon/tool-setup-types.ts +9 -0
  372. package/src/daemon/tool-side-effects.ts +6 -4
  373. package/src/daemon/wake-target-adapter.ts +11 -0
  374. package/src/documents/document-store.ts +35 -1
  375. package/src/export/transcript-formatter.ts +61 -2
  376. package/src/filing/filing-service.ts +42 -56
  377. package/src/heartbeat/__tests__/heartbeat-service.test.ts +359 -0
  378. package/src/heartbeat/heartbeat-run-store.ts +2 -1
  379. package/src/heartbeat/heartbeat-service.ts +149 -128
  380. package/src/home/__tests__/feed-types.test.ts +63 -131
  381. package/src/home/__tests__/feed-writer.test.ts +77 -278
  382. package/src/home/__tests__/post-connect-feed.test.ts +9 -12
  383. package/src/home/feed-types.ts +19 -73
  384. package/src/home/feed-writer.ts +25 -156
  385. package/src/home/post-connect-feed.ts +1 -3
  386. package/src/ipc/__tests__/cli-ipc.test.ts +2 -0
  387. package/src/ipc/__tests__/email-ipc.test.ts +506 -0
  388. package/src/ipc/__tests__/exit-helper.test.ts +104 -0
  389. package/src/ipc/__tests__/streaming-client.test.ts +237 -0
  390. package/src/ipc/__tests__/streaming-framing.test.ts +142 -0
  391. package/src/ipc/assistant-server.ts +148 -42
  392. package/src/ipc/cli-client.ts +370 -50
  393. package/src/ipc/routes/db-proxy-transaction.ts +151 -0
  394. package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +60 -0
  395. package/src/ipc/skill-routes/events.ts +30 -3
  396. package/src/ipc/skill-server.ts +99 -42
  397. package/src/live-voice/__tests__/live-voice-session-manager.test.ts +46 -0
  398. package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +1 -0
  399. package/src/live-voice/live-voice-session-manager.ts +11 -4
  400. package/src/live-voice/live-voice-session.ts +14 -6
  401. package/src/memory/__tests__/bookmark-crud.test.ts +258 -0
  402. package/src/memory/__tests__/bookmark-schema.test.ts +181 -0
  403. package/src/memory/__tests__/conversation-types.test.ts +36 -0
  404. package/src/memory/__tests__/find-most-recent-retrospective-for.test.ts +130 -0
  405. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +10 -57
  406. package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +177 -0
  407. package/src/memory/__tests__/memory-retrospective-job.test.ts +328 -0
  408. package/src/memory/__tests__/memory-retrospective-startup-cleanup.test.ts +213 -0
  409. package/src/memory/__tests__/memory-retrospective-trigger-check.test.ts +90 -0
  410. package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +69 -0
  411. package/src/memory/__tests__/memory-v2-concept-frequency.test.ts +3 -0
  412. package/src/memory/bookmark-crud.ts +179 -0
  413. package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +31 -9
  414. package/src/memory/context-search/agent-protocol.ts +5 -1
  415. package/src/memory/context-search/agent-runner.ts +60 -85
  416. package/src/memory/context-search/limits.ts +1 -4
  417. package/src/memory/context-search/search.ts +23 -113
  418. package/src/memory/context-search/sources/conversations.ts +18 -6
  419. package/src/memory/context-search/sources/memory-v2.ts +40 -31
  420. package/src/memory/context-search/sources/memory.ts +9 -2
  421. package/src/memory/context-search/sources/workspace.ts +13 -10
  422. package/src/memory/context-search/types.ts +1 -1
  423. package/src/memory/conversation-bootstrap.ts +11 -0
  424. package/src/memory/conversation-crud.ts +312 -10
  425. package/src/memory/conversation-queries.ts +9 -5
  426. package/src/memory/conversation-title-service.ts +1 -0
  427. package/src/memory/conversation-types.ts +16 -0
  428. package/src/memory/db-init.ts +14 -0
  429. package/src/memory/embedding-backend.ts +2 -1
  430. package/src/memory/embedding-runtime-manager.ts +1 -2
  431. package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +104 -61
  432. package/src/memory/graph/__tests__/handle-remember-v2.test.ts +11 -26
  433. package/src/memory/graph/__tests__/remember-description.test.ts +55 -0
  434. package/src/memory/graph/conversation-graph-memory.ts +108 -14
  435. package/src/memory/graph/extraction.ts +4 -0
  436. package/src/memory/graph/graph-memory-state-store.ts +16 -3
  437. package/src/memory/graph/graph-search.test.ts +6 -5
  438. package/src/memory/graph/graph-search.ts +3 -4
  439. package/src/memory/graph/retriever.test.ts +12 -7
  440. package/src/memory/graph/retriever.ts +4 -5
  441. package/src/memory/graph/tool-handlers.ts +20 -11
  442. package/src/memory/graph/tools.ts +48 -9
  443. package/src/memory/indexer.ts +18 -2
  444. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +120 -6
  445. package/src/memory/jobs/embed-concept-page.ts +261 -89
  446. package/src/memory/jobs-store.ts +51 -1
  447. package/src/memory/jobs-worker.ts +60 -7
  448. package/src/memory/llm-request-log-source-clickhouse.ts +317 -0
  449. package/src/memory/llm-request-log-source-local.ts +26 -0
  450. package/src/memory/llm-request-log-source.ts +97 -0
  451. package/src/memory/llm-request-log-store.ts +1 -1
  452. package/src/memory/memory-retrospective-constants.ts +13 -0
  453. package/src/memory/memory-retrospective-enqueue.ts +114 -0
  454. package/src/memory/memory-retrospective-job.ts +351 -0
  455. package/src/memory/memory-retrospective-startup-cleanup.ts +108 -0
  456. package/src/memory/memory-retrospective-state.ts +162 -0
  457. package/src/memory/memory-retrospective-trigger-check.ts +91 -0
  458. package/src/memory/memory-v2-activation-log-store.ts +49 -5
  459. package/src/memory/memory-v2-concept-frequency.ts +4 -0
  460. package/src/memory/message-content.ts +38 -1
  461. package/src/memory/migrations/227-add-conversation-inference-profile.ts +6 -1
  462. package/src/memory/migrations/228-rename-inference-profile-snake-case.ts +20 -7
  463. package/src/memory/migrations/229-delete-private-conversations.test.ts +70 -1
  464. package/src/memory/migrations/229-delete-private-conversations.ts +12 -0
  465. package/src/memory/migrations/231-repair-memory-graph-event-dates.ts +16 -2
  466. package/src/memory/migrations/240-conversation-inference-profile-session.ts +25 -0
  467. package/src/memory/migrations/241-activation-state-fk-cascade.ts +50 -0
  468. package/src/memory/migrations/242-message-bookmarks.ts +38 -0
  469. package/src/memory/migrations/243-provider-connections.ts +68 -0
  470. package/src/memory/migrations/244-provider-connection-status-label.ts +23 -0
  471. package/src/memory/migrations/245-memory-retrospective-state.ts +36 -0
  472. package/src/memory/migrations/246-backfill-provider-connection-label.ts +81 -0
  473. package/src/memory/migrations/__tests__/244-provider-connection-status-label.test.ts +84 -0
  474. package/src/memory/migrations/__tests__/245-memory-retrospective-state.test.ts +125 -0
  475. package/src/memory/migrations/__tests__/246-backfill-provider-connection-label.test.ts +192 -0
  476. package/src/memory/migrations/index.ts +7 -0
  477. package/src/memory/pkb/pkb-search.test.ts +6 -5
  478. package/src/memory/pkb/pkb-search.ts +4 -5
  479. package/src/memory/published-pages-store.ts +16 -0
  480. package/src/memory/qdrant-client.ts +3 -0
  481. package/src/memory/schema/bookmarks.ts +38 -0
  482. package/src/memory/schema/conversations.ts +2 -0
  483. package/src/memory/schema/index.ts +2 -0
  484. package/src/memory/schema/inference.ts +29 -0
  485. package/src/memory/schema/memory-core.ts +9 -0
  486. package/src/memory/search/semantic.ts +5 -9
  487. package/src/memory/v2/__tests__/__snapshots__/prompts-router.test.ts.snap +27 -0
  488. package/src/memory/v2/__tests__/activation-store.test.ts +5 -5
  489. package/src/memory/v2/__tests__/activation.test.ts +46 -9
  490. package/src/memory/v2/__tests__/backfill-jobs.test.ts +38 -21
  491. package/src/memory/v2/__tests__/consolidation-job.test.ts +140 -163
  492. package/src/memory/v2/__tests__/edge-index.test.ts +1 -1
  493. package/src/memory/v2/__tests__/frontmatter-sweep.test.ts +111 -0
  494. package/src/memory/v2/__tests__/injection.test.ts +768 -33
  495. package/src/memory/v2/__tests__/migration.test.ts +7 -3
  496. package/src/memory/v2/__tests__/page-index.test.ts +277 -0
  497. package/src/memory/v2/__tests__/page-store.test.ts +14 -1
  498. package/src/memory/v2/__tests__/prompts-router.test.ts +257 -0
  499. package/src/memory/v2/__tests__/qdrant.test.ts +382 -9
  500. package/src/memory/v2/__tests__/reranker.test.ts +4 -4
  501. package/src/memory/v2/__tests__/router.test.ts +516 -0
  502. package/src/memory/v2/__tests__/sim.test.ts +163 -8
  503. package/src/memory/v2/__tests__/skill-store.test.ts +58 -3
  504. package/src/memory/v2/__tests__/static-context.test.ts +8 -35
  505. package/src/memory/v2/__tests__/sweep-job.test.ts +114 -33
  506. package/src/memory/v2/activation-store.ts +34 -5
  507. package/src/memory/v2/activation.ts +40 -27
  508. package/src/memory/v2/backfill-jobs.ts +17 -84
  509. package/src/memory/v2/consolidation-job.ts +92 -86
  510. package/src/memory/v2/frontmatter-sweep.ts +91 -0
  511. package/src/memory/v2/injection.ts +466 -115
  512. package/src/memory/v2/migration.ts +117 -20
  513. package/src/memory/v2/page-index.ts +191 -0
  514. package/src/memory/v2/page-store.ts +42 -0
  515. package/src/memory/v2/prompts/consolidation.ts +14 -7
  516. package/src/memory/v2/prompts/router.ts +192 -0
  517. package/src/memory/v2/qdrant.ts +307 -133
  518. package/src/memory/v2/reranker.ts +14 -7
  519. package/src/memory/v2/router.ts +322 -0
  520. package/src/memory/v2/sim.ts +88 -34
  521. package/src/memory/v2/skill-store.ts +118 -29
  522. package/src/memory/v2/static-context.ts +20 -17
  523. package/src/memory/v2/sweep-job.ts +127 -102
  524. package/src/memory/v2/types.ts +16 -5
  525. package/src/memory/validation.ts +13 -0
  526. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +182 -0
  527. package/src/notifications/__tests__/home-feed-side-effect.test.ts +199 -0
  528. package/src/notifications/__tests__/signal-registry.test.ts +17 -0
  529. package/src/notifications/adapters/platform.ts +171 -0
  530. package/src/notifications/conversation-pairing.ts +2 -2
  531. package/src/notifications/copy-composer.ts +61 -12
  532. package/src/notifications/decision-engine.ts +46 -0
  533. package/src/notifications/destination-resolver.ts +21 -0
  534. package/src/notifications/emit-signal.ts +28 -1
  535. package/src/notifications/home-feed-side-effect.ts +111 -0
  536. package/src/notifications/signal.ts +5 -0
  537. package/src/permissions/checker.ts +12 -0
  538. package/src/permissions/gateway-threshold-reader.ts +116 -8
  539. package/src/permissions/ipc-risk-types.ts +2 -0
  540. package/src/permissions/prompter.ts +86 -96
  541. package/src/permissions/secret-prompter.ts +31 -31
  542. package/src/plugin-api/index.ts +13 -0
  543. package/src/plugin-api/package.json +12 -0
  544. package/src/plugin-api/types.ts +62 -0
  545. package/src/plugins/defaults/injectors.ts +20 -5
  546. package/src/plugins/external-plugin-loader.ts +294 -0
  547. package/src/plugins/types.ts +46 -30
  548. package/src/plugins/user-loader.ts +64 -41
  549. package/src/proactive-artifact/job.test.ts +63 -8
  550. package/src/proactive-artifact/job.ts +20 -2
  551. package/src/proactive-artifact/message-copy.ts +18 -1
  552. package/src/proactive-artifact/trigger-state.test.ts +9 -0
  553. package/src/proactive-artifact/trigger-state.ts +4 -0
  554. package/src/prompts/__tests__/system-prompt.test.ts +105 -0
  555. package/src/prompts/system-prompt.ts +22 -1
  556. package/src/prompts/templates/SOUL.md +13 -28
  557. package/src/prompts/update-bulletin-job.ts +61 -73
  558. package/src/providers/__tests__/dispatch-connection-routing.test.ts +279 -0
  559. package/src/providers/__tests__/inference.test.ts +288 -0
  560. package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
  561. package/src/providers/__tests__/provider-secret-catalog.test.ts +6 -0
  562. package/src/providers/__tests__/retry-callsite.test.ts +14 -32
  563. package/src/providers/__tests__/satellite-connection-routing.test.ts +510 -0
  564. package/src/providers/__tests__/search-provider-catalog.test.ts +80 -0
  565. package/src/providers/anthropic/client.ts +95 -26
  566. package/src/providers/call-site-routing.ts +94 -16
  567. package/src/providers/connection-resolution.ts +163 -0
  568. package/src/providers/inference/__tests__/connections-status-label.test.ts +250 -0
  569. package/src/providers/inference/adapter-factory.ts +173 -0
  570. package/src/providers/inference/auth.ts +112 -0
  571. package/src/providers/inference/backfill.ts +196 -0
  572. package/src/providers/inference/connections.ts +356 -0
  573. package/src/providers/inference/resolve-auth.ts +65 -0
  574. package/src/providers/model-catalog.ts +104 -6
  575. package/src/providers/openai/responses-provider.ts +4 -2
  576. package/src/providers/provider-env-vars.ts +17 -7
  577. package/src/providers/provider-secret-catalog.ts +49 -30
  578. package/src/providers/provider-send-message.ts +41 -20
  579. package/src/providers/registry.ts +143 -159
  580. package/src/providers/retry.ts +18 -10
  581. package/src/providers/search-provider-catalog.ts +121 -0
  582. package/src/runtime/AGENTS.md +18 -5
  583. package/src/runtime/__tests__/background-job-runner.test.ts +357 -0
  584. package/src/runtime/__tests__/pre-first-message-gate.test.ts +82 -0
  585. package/src/runtime/actor-trust-resolver.ts +32 -10
  586. package/src/runtime/agent-wake.ts +35 -6
  587. package/src/runtime/assistant-event-hub.ts +3 -85
  588. package/src/runtime/auth/route-policy.ts +304 -8
  589. package/src/runtime/auth/same-actor.ts +2 -0
  590. package/src/runtime/background-job-runner.ts +339 -0
  591. package/src/runtime/btw-sidechain.ts +1 -0
  592. package/src/runtime/channel-approvals.ts +3 -2
  593. package/src/runtime/guardian-reply-router.ts +0 -10
  594. package/src/runtime/http-router.ts +36 -1
  595. package/src/runtime/http-server.ts +31 -5
  596. package/src/runtime/http-types.ts +2 -0
  597. package/src/runtime/middleware/__tests__/request-logger.test.ts +162 -0
  598. package/src/runtime/middleware/request-logger.ts +62 -1
  599. package/src/runtime/pending-interactions.ts +19 -15
  600. package/src/runtime/pre-first-message-gate.ts +83 -0
  601. package/src/runtime/routes/__tests__/backup-routes.test.ts +8 -1
  602. package/src/runtime/routes/__tests__/bookmark-routes.test.ts +251 -0
  603. package/src/runtime/routes/__tests__/connection-routes-vs-cli-parity.test.ts +142 -0
  604. package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +315 -0
  605. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +189 -0
  606. package/src/runtime/routes/__tests__/home-feed-routes.test.ts +15 -136
  607. package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +736 -0
  608. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +147 -0
  609. package/src/runtime/routes/__tests__/stt-routes.test.ts +5 -1
  610. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +384 -0
  611. package/src/runtime/routes/__tests__/tts-routes.test.ts +6 -2
  612. package/src/runtime/routes/acp-routes.ts +10 -8
  613. package/src/runtime/routes/app-management-routes.ts +228 -3
  614. package/src/runtime/routes/approval-routes.ts +7 -21
  615. package/src/runtime/routes/audit-routes.ts +43 -0
  616. package/src/runtime/routes/auth-routes.ts +72 -0
  617. package/src/runtime/routes/avatar-routes.ts +273 -20
  618. package/src/runtime/routes/backup-routes.ts +406 -2
  619. package/src/runtime/routes/bookmark-routes.ts +154 -0
  620. package/src/runtime/routes/channel-verification-routes.ts +2 -1
  621. package/src/runtime/routes/consolidation-routes.ts +8 -9
  622. package/src/runtime/routes/contact-routes.ts +0 -160
  623. package/src/runtime/routes/conversation-cli-routes.ts +192 -0
  624. package/src/runtime/routes/conversation-management-routes.ts +30 -43
  625. package/src/runtime/routes/conversation-query-routes.ts +373 -82
  626. package/src/runtime/routes/conversation-routes.ts +31 -10
  627. package/src/runtime/routes/conversations-import-routes.ts +229 -0
  628. package/src/runtime/routes/credential-routes.ts +540 -0
  629. package/src/runtime/routes/debug-bash-routes.ts +2 -0
  630. package/src/runtime/routes/debug-routes.ts +2 -2
  631. package/src/runtime/routes/document-pdf-renderer.ts +5 -1
  632. package/src/runtime/routes/domain-routes.ts +167 -0
  633. package/src/runtime/routes/email-routes.ts +603 -0
  634. package/src/runtime/routes/errors.ts +2 -2
  635. package/src/runtime/routes/events-routes.ts +192 -0
  636. package/src/runtime/routes/filing-routes.ts +2 -3
  637. package/src/runtime/routes/home-feed-routes.ts +6 -78
  638. package/src/runtime/routes/host-app-control-routes.ts +44 -2
  639. package/src/runtime/routes/host-browser-routes.ts +103 -22
  640. package/src/runtime/routes/http-adapter.ts +2 -0
  641. package/src/runtime/routes/identity-routes.ts +5 -0
  642. package/src/runtime/routes/image-generation-routes.ts +99 -0
  643. package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +137 -1
  644. package/src/runtime/routes/inbound-stages/background-dispatch.ts +87 -7
  645. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +156 -0
  646. package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +22 -7
  647. package/src/runtime/routes/index.ts +36 -0
  648. package/src/runtime/routes/inference-profile-session-handler.ts +312 -0
  649. package/src/runtime/routes/inference-profile-session-reaper.ts +98 -0
  650. package/src/runtime/routes/inference-profile-session-routes.ts +146 -0
  651. package/src/runtime/routes/inference-provider-connection-routes.ts +317 -0
  652. package/src/runtime/routes/inference-send-routes.ts +115 -0
  653. package/src/runtime/routes/integrations/twilio.ts +1 -0
  654. package/src/runtime/routes/mcp-auth-routes.ts +283 -9
  655. package/src/runtime/routes/memory-item-routes.test.ts +3 -9
  656. package/src/runtime/routes/memory-item-routes.ts +5 -6
  657. package/src/runtime/routes/memory-v2-routes.ts +105 -404
  658. package/src/runtime/routes/notification-routes.ts +2 -0
  659. package/src/runtime/routes/oauth-apps.ts +112 -7
  660. package/src/runtime/routes/oauth-commands-routes.ts +1007 -0
  661. package/src/runtime/routes/oauth-connect-routes.ts +67 -5
  662. package/src/runtime/routes/oauth-providers.ts +298 -8
  663. package/src/runtime/routes/platform-routes.ts +336 -0
  664. package/src/runtime/routes/playground/inject-failures.ts +2 -1
  665. package/src/runtime/routes/playground/reset-circuit.ts +2 -1
  666. package/src/runtime/routes/playground/state.ts +2 -1
  667. package/src/runtime/routes/publish-routes.ts +221 -0
  668. package/src/runtime/routes/schedule-routes.ts +82 -0
  669. package/src/runtime/routes/sequence-routes.ts +291 -0
  670. package/src/runtime/routes/settings-routes.ts +2 -10
  671. package/src/runtime/routes/skills-routes.ts +31 -1
  672. package/src/runtime/routes/stt-routes.ts +240 -3
  673. package/src/runtime/routes/surface-action-routes.ts +43 -7
  674. package/src/runtime/routes/tts-routes.ts +67 -0
  675. package/src/runtime/routes/types.ts +32 -0
  676. package/src/runtime/routes/user-routes-cli.ts +243 -0
  677. package/src/runtime/routes/webhook-routes.ts +165 -0
  678. package/src/runtime/sync/resource-sync-events.ts +25 -0
  679. package/src/runtime/sync/sync-publisher.test.ts +105 -0
  680. package/src/runtime/sync/sync-publisher.ts +21 -0
  681. package/src/schedule/scheduler.ts +200 -123
  682. package/src/security/__tests__/provider-key-env-fallback.test.ts +12 -6
  683. package/src/security/secret-patterns.ts +3 -0
  684. package/src/sequence/engine.ts +38 -40
  685. package/src/skills/include-graph.ts +35 -13
  686. package/src/subagent/manager.ts +20 -15
  687. package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +206 -0
  688. package/src/tools/browser/browser-execution.ts +15 -4
  689. package/src/tools/browser/cdp-client/__tests__/factory.test.ts +174 -0
  690. package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +16 -13
  691. package/src/tools/browser/cdp-client/extension-cdp-client.ts +24 -1
  692. package/src/tools/browser/cdp-client/factory.ts +66 -5
  693. package/src/tools/browser/runtime-check.ts +77 -0
  694. package/src/tools/document/document-tool.ts +20 -0
  695. package/src/tools/executor.ts +18 -2
  696. package/src/tools/memory/register.test.ts +10 -8
  697. package/src/tools/memory/register.ts +9 -1
  698. package/src/tools/network/__tests__/web-search.test.ts +156 -0
  699. package/src/tools/network/web-search.ts +280 -37
  700. package/src/tools/permission-checker.ts +28 -5
  701. package/src/tools/skills/load.ts +24 -20
  702. package/src/tools/subagent/spawn.ts +3 -3
  703. package/src/tools/terminal/shell.ts +44 -0
  704. package/src/tools/tool-name-aliases.ts +19 -0
  705. package/src/tools/types.ts +19 -1
  706. package/src/usage/attribution.ts +3 -2
  707. package/src/util/pricing.ts +86 -160
  708. package/src/watcher/__tests__/engine.test.ts +301 -0
  709. package/src/watcher/constants.ts +7 -0
  710. package/src/watcher/engine.ts +90 -90
  711. package/src/workspace/migrations/046-seed-conversation-starters-callsite.ts +6 -9
  712. package/src/workspace/migrations/054-seed-recall-callsite.ts +10 -1
  713. package/src/workspace/migrations/057-repair-stale-gemini-model-ids.ts +28 -4
  714. package/src/workspace/migrations/067-release-notes-safe-storage-limits.ts +4 -62
  715. package/src/workspace/migrations/069-seed-onboarding-threads.ts +34 -0
  716. package/src/workspace/migrations/070-memory-v2-summary-schema-rebuild.ts +31 -0
  717. package/src/workspace/migrations/071-remove-safe-storage-release-note.ts +111 -0
  718. package/src/workspace/migrations/072-seed-reply-suggestion-callsite.ts +104 -0
  719. package/src/workspace/migrations/073-repair-recall-callsite-empty-profile.ts +93 -0
  720. package/src/workspace/migrations/074-drop-deprecated-secret-detection-keys.ts +117 -0
  721. package/src/workspace/migrations/075-memory-v2-bm25-b-default-reembed.ts +61 -0
  722. package/src/workspace/migrations/076-drop-services-inference-mode.ts +62 -0
  723. package/src/workspace/migrations/077-seed-memory-router-callsite.ts +89 -0
  724. package/src/workspace/migrations/078-release-notes-tavily-web-search.ts +66 -0
  725. package/src/workspace/migrations/079-home-feed-notification-only.ts +197 -0
  726. package/src/workspace/migrations/080-restrict-vercel-api-token-metadata.ts +182 -0
  727. package/src/workspace/migrations/081-backfill-bash-allowed-tools-for-injection-credentials.ts +160 -0
  728. package/src/workspace/migrations/082-backfill-managed-profile-labels.ts +154 -0
  729. package/src/workspace/migrations/registry.ts +28 -0
  730. package/src/workspace/migrations/runner.ts +13 -2
  731. package/src/workspace/migrations/types.ts +13 -3
  732. package/src/workspace/provider-commit-message-generator.ts +3 -2
  733. package/src/__tests__/context-search-pkb-source.test.ts +0 -492
  734. package/src/__tests__/credentials-cli.test.ts +0 -1225
  735. package/src/__tests__/memory-admin-recall.test.ts +0 -213
  736. package/src/approvals/__tests__/guardian-feed-event.test.ts +0 -303
  737. package/src/cli/commands/__tests__/email-download.test.ts +0 -260
  738. package/src/cli/commands/__tests__/email-list.test.ts +0 -216
  739. package/src/cli/commands/__tests__/email-register.test.ts +0 -186
  740. package/src/cli/commands/__tests__/email-send.test.ts +0 -416
  741. package/src/cli/commands/__tests__/email-status.test.ts +0 -185
  742. package/src/cli/commands/__tests__/email-unregister.test.ts +0 -168
  743. package/src/cli/commands/__tests__/routes.test.ts +0 -562
  744. package/src/cli/commands/__tests__/stt-transcribe.test.ts +0 -454
  745. package/src/cli/commands/autonomy.ts +0 -365
  746. package/src/cli/commands/memory.ts +0 -424
  747. package/src/cli/commands/oauth/__tests__/connect.test.ts +0 -1201
  748. package/src/cli/commands/oauth/__tests__/disconnect.test.ts +0 -686
  749. package/src/cli/commands/oauth/__tests__/mode.test.ts +0 -632
  750. package/src/cli/commands/oauth/__tests__/ping.test.ts +0 -631
  751. package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +0 -573
  752. package/src/cli/commands/oauth/__tests__/providers-register.test.ts +0 -330
  753. package/src/cli/commands/oauth/__tests__/providers-update.test.ts +0 -521
  754. package/src/cli/commands/oauth/__tests__/status.test.ts +0 -551
  755. package/src/cli/commands/oauth/__tests__/token.test.ts +0 -420
  756. package/src/cli/lib/daemon-avatar-client.ts +0 -37
  757. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -87
  758. package/src/config/bundled-skills/messaging/tools/__tests__/messaging-feed-events.test.ts +0 -207
  759. package/src/daemon/__tests__/conversation-feed-event.test.ts +0 -304
  760. package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +0 -233
  761. package/src/home/__tests__/assistant-feed-authoring.test.ts +0 -156
  762. package/src/home/__tests__/emit-feed-event.test.ts +0 -169
  763. package/src/home/__tests__/feed-population-integration.test.ts +0 -312
  764. package/src/home/__tests__/feed-scheduler.test.ts +0 -222
  765. package/src/home/__tests__/phase5-exit-criteria.test.ts +0 -229
  766. package/src/home/__tests__/platform-gmail-digest.test.ts +0 -222
  767. package/src/home/__tests__/rollup-producer.test.ts +0 -507
  768. package/src/home/assistant-feed-authoring.ts +0 -135
  769. package/src/home/emit-feed-event.ts +0 -169
  770. package/src/home/feed-scheduler.ts +0 -281
  771. package/src/home/platform-gmail-digest.ts +0 -163
  772. package/src/home/rewrite-command-preview.ts +0 -66
  773. package/src/home/rewrite-feed-title.ts +0 -58
  774. package/src/home/rollup-producer.ts +0 -426
  775. package/src/memory/admin.ts +0 -326
  776. package/src/memory/context-search/sources/pkb.ts +0 -477
  777. package/src/memory/graph/compaction.ts +0 -299
  778. /package/src/cli/{commands → lib}/cache-fs.ts +0 -0
@@ -154,6 +154,88 @@ describe("renderHistoryContent", () => {
154
154
  ]);
155
155
  });
156
156
 
157
+ // ── Persisted risk-option ladders (Phase B of conflation track) ─────────────
158
+
159
+ test("hydrates persisted _risk*Options annotations onto tool calls", () => {
160
+ // Mirrors what `annotatePersistedAssistantMessage` writes to the DB so the
161
+ // rule editor's chip ladder survives chat-history reload. Without these,
162
+ // hydrated chips fall back to the synthesized `*` allowlist (see web's
163
+ // `synthesizeFallbackOption` in RuleEditorModal.tsx).
164
+ const scopeOptions = [
165
+ { pattern: "exact", label: "exact: rm -rf /tmp" },
166
+ { pattern: "by-program", label: "All rm" },
167
+ ];
168
+ const allowlistOptions = [
169
+ { label: "exact", description: "exact match", pattern: "rm -rf /tmp" },
170
+ { label: "All rm", description: "All rm commands", pattern: "rm *" },
171
+ ];
172
+ const directoryScopeOptions = [
173
+ { scope: "/Users/me/code", label: "in code/" },
174
+ { scope: "everywhere", label: "Everywhere" },
175
+ ];
176
+
177
+ const output = renderHistoryContent([
178
+ {
179
+ type: "tool_use",
180
+ id: "tu_1",
181
+ name: "bash",
182
+ input: { command: "rm -rf /tmp" },
183
+ _riskLevel: "high",
184
+ _matchedTrustRuleId: "rule_42",
185
+ _riskScopeOptions: scopeOptions,
186
+ _riskAllowlistOptions: allowlistOptions,
187
+ _riskDirectoryScopeOptions: directoryScopeOptions,
188
+ },
189
+ ]);
190
+
191
+ const [entry] = output.toolCalls;
192
+ expect(entry.riskLevel).toBe("high");
193
+ expect(entry.matchedTrustRuleId).toBe("rule_42");
194
+ expect(entry.riskScopeOptions).toEqual(scopeOptions);
195
+ expect(entry.riskAllowlistOptions).toEqual(allowlistOptions);
196
+ expect(entry.riskDirectoryScopeOptions).toEqual(directoryScopeOptions);
197
+ });
198
+
199
+ test("ignores non-array _risk*Options annotations", () => {
200
+ // Defensive: a malformed persisted block should not throw or coerce.
201
+ const output = renderHistoryContent([
202
+ {
203
+ type: "tool_use",
204
+ id: "tu_1",
205
+ name: "bash",
206
+ input: { command: "ls" },
207
+ _riskLevel: "low",
208
+ _riskScopeOptions: "not an array",
209
+ _riskAllowlistOptions: { not: "an array" },
210
+ _riskDirectoryScopeOptions: 42,
211
+ },
212
+ ]);
213
+
214
+ const [entry] = output.toolCalls;
215
+ expect(entry.riskLevel).toBe("low");
216
+ expect(entry.riskScopeOptions).toBeUndefined();
217
+ expect(entry.riskAllowlistOptions).toBeUndefined();
218
+ expect(entry.riskDirectoryScopeOptions).toBeUndefined();
219
+ });
220
+
221
+ test("omits absent _risk*Options annotations", () => {
222
+ const output = renderHistoryContent([
223
+ {
224
+ type: "tool_use",
225
+ id: "tu_1",
226
+ name: "bash",
227
+ input: { command: "ls" },
228
+ _riskLevel: "low",
229
+ },
230
+ ]);
231
+
232
+ const [entry] = output.toolCalls;
233
+ expect(entry.riskLevel).toBe("low");
234
+ expect(entry.riskScopeOptions).toBeUndefined();
235
+ expect(entry.riskAllowlistOptions).toBeUndefined();
236
+ expect(entry.riskDirectoryScopeOptions).toBeUndefined();
237
+ });
238
+
157
239
  test("handles mixed text and tool blocks", () => {
158
240
  const output = renderHistoryContent([
159
241
  { type: "text", text: "Let me look that up." },
@@ -93,6 +93,7 @@ afterAll(() => {
93
93
  describe("shell tool credential ref resolution", () => {
94
94
  test("service/field ref resolves to UUID and reaches session creation", async () => {
95
95
  const meta = upsertCredentialMetadata("fal", "api_key", {
96
+ allowedTools: ["bash"],
96
97
  injectionTemplates: [
97
98
  {
98
99
  hostPattern: "*.fal.ai",
@@ -120,7 +121,9 @@ describe("shell tool credential ref resolution", () => {
120
121
  });
121
122
 
122
123
  test("UUID ref remains supported", async () => {
123
- const meta = upsertCredentialMetadata("github", "token");
124
+ const meta = upsertCredentialMetadata("github", "token", {
125
+ allowedTools: ["bash"],
126
+ });
124
127
 
125
128
  await shellTool.execute(
126
129
  {
@@ -156,7 +159,9 @@ describe("shell tool credential ref resolution", () => {
156
159
  });
157
160
 
158
161
  test("mixed known+unknown refs fails fast (no partial execution)", async () => {
159
- upsertCredentialMetadata("fal", "api_key");
162
+ upsertCredentialMetadata("fal", "api_key", {
163
+ allowedTools: ["bash"],
164
+ });
160
165
 
161
166
  const result = await shellTool.execute(
162
167
  {
@@ -175,7 +180,9 @@ describe("shell tool credential ref resolution", () => {
175
180
  });
176
181
 
177
182
  test("duplicate refs are deduped", async () => {
178
- const meta = upsertCredentialMetadata("fal", "api_key");
183
+ const meta = upsertCredentialMetadata("fal", "api_key", {
184
+ allowedTools: ["bash"],
185
+ });
179
186
 
180
187
  await shellTool.execute(
181
188
  {
@@ -209,4 +216,89 @@ describe("shell tool credential ref resolution", () => {
209
216
  expect(result.isError).toBeFalsy();
210
217
  expect(mockGetOrStartSession).not.toHaveBeenCalled();
211
218
  });
219
+
220
+ test("credential with allowedTools excluding bash is denied for proxied shell", async () => {
221
+ upsertCredentialMetadata("vercel", "api_token", {
222
+ allowedTools: ["publish_page"],
223
+ injectionTemplates: [
224
+ {
225
+ hostPattern: "api.vercel.com",
226
+ injectionType: "header",
227
+ headerName: "Authorization",
228
+ valuePrefix: "Bearer ",
229
+ },
230
+ ],
231
+ });
232
+
233
+ const result = await shellTool.execute(
234
+ {
235
+ command: "curl https://api.vercel.com/v1/projects",
236
+ activity: "test",
237
+ network_mode: "proxied",
238
+ credential_ids: ["vercel/api_token"],
239
+ },
240
+ ctx,
241
+ );
242
+
243
+ expect(result.isError).toBe(true);
244
+ expect(result.content).toContain("credential tool policy denied");
245
+ expect(result.content).toContain("not bash");
246
+ // Must not call getOrStartSession — policy denial happens before session creation
247
+ expect(mockGetOrStartSession).not.toHaveBeenCalled();
248
+ });
249
+
250
+ test("credential with allowedTools including bash starts proxied session", async () => {
251
+ const meta = upsertCredentialMetadata("deploy_svc", "api_key", {
252
+ allowedTools: ["bash"],
253
+ injectionTemplates: [
254
+ {
255
+ hostPattern: "*.deploy-svc.io",
256
+ injectionType: "header",
257
+ headerName: "Authorization",
258
+ valuePrefix: "Bearer ",
259
+ },
260
+ ],
261
+ });
262
+
263
+ await shellTool.execute(
264
+ {
265
+ command: "echo deploy",
266
+ activity: "test",
267
+ network_mode: "proxied",
268
+ credential_ids: ["deploy_svc/api_key"],
269
+ },
270
+ ctx,
271
+ );
272
+
273
+ // Session should be created with the resolved credential ID
274
+ expect(mockGetOrStartSession).toHaveBeenCalledTimes(1);
275
+ const callArgs = mockGetOrStartSession.mock.calls[0];
276
+ expect(callArgs[1]).toEqual([meta.credentialId]);
277
+ });
278
+
279
+ test("mixed allowed and denied credentials fail the whole command before session creation", async () => {
280
+ upsertCredentialMetadata("allowed_svc", "token", {
281
+ allowedTools: ["bash"],
282
+ });
283
+ upsertCredentialMetadata("denied_svc", "token", {
284
+ allowedTools: ["publish_page"],
285
+ });
286
+
287
+ const result = await shellTool.execute(
288
+ {
289
+ command: "echo mixed",
290
+ activity: "test",
291
+ network_mode: "proxied",
292
+ credential_ids: ["allowed_svc/token", "denied_svc/token"],
293
+ },
294
+ ctx,
295
+ );
296
+
297
+ expect(result.isError).toBe(true);
298
+ expect(result.content).toContain("credential tool policy denied");
299
+ expect(result.content).toContain("denied_svc/token");
300
+ expect(result.content).toContain("not bash");
301
+ // Must not call getOrStartSession — even one denied credential blocks the whole command
302
+ expect(mockGetOrStartSession).not.toHaveBeenCalled();
303
+ });
212
304
  });
@@ -136,6 +136,20 @@ mock.module("../tools/credentials/resolve.js", () => ({
136
136
  resolveCredentialRef: (ref: string) => ({ credentialId: ref }),
137
137
  }));
138
138
 
139
+ mock.module("../tools/credentials/metadata-store.js", () => ({
140
+ getCredentialMetadataById: (id: string) => ({
141
+ service: "test",
142
+ field: id,
143
+ allowedTools: ["bash"],
144
+ allowedDomains: [],
145
+ }),
146
+ }));
147
+
148
+ mock.module("../tools/credentials/tool-policy.js", () => ({
149
+ isToolAllowed: (toolName: string, allowedTools: string[]) =>
150
+ Array.isArray(allowedTools) && allowedTools.includes(toolName),
151
+ }));
152
+
139
153
  mock.module("../tools/network/script-proxy/logging.js", () => ({
140
154
  buildCredentialRefTrace: (
141
155
  rawRefs: string[],
@@ -6,6 +6,7 @@ import {
6
6
  getImmediateChildren,
7
7
  indexCatalogById,
8
8
  traverseIncludes,
9
+ validateIncludeCycles,
9
10
  validateIncludes,
10
11
  } from "../skills/include-graph.js";
11
12
 
@@ -299,6 +300,36 @@ describe("validateIncludes — cycle detection", () => {
299
300
  });
300
301
  });
301
302
 
303
+ describe("validateIncludeCycles", () => {
304
+ test("skips missing children while still detecting available cycles", () => {
305
+ const catalog = [
306
+ makeSkill("root", ["missing", "a"]),
307
+ makeSkill("a", ["b"]),
308
+ makeSkill("b", ["a"]),
309
+ ];
310
+ const index = indexCatalogById(catalog);
311
+
312
+ const result = validateIncludeCycles("root", index);
313
+
314
+ expect(result.ok).toBe(false);
315
+ if (!result.ok && result.error === "cycle") {
316
+ expect(result.cyclePath).toEqual(["a", "b", "a"]);
317
+ }
318
+ });
319
+
320
+ test("returns success when the only invalid edges are missing children", () => {
321
+ const catalog = [makeSkill("root", ["missing"])];
322
+ const index = indexCatalogById(catalog);
323
+
324
+ const result = validateIncludeCycles("root", index);
325
+
326
+ expect(result.ok).toBe(true);
327
+ if (result.ok) {
328
+ expect(result.visited).toEqual(["root"]);
329
+ }
330
+ });
331
+ });
332
+
302
333
  describe("collectAllMissing", () => {
303
334
  test("returns empty set when skill has no includes", () => {
304
335
  const catalog = [makeSkill("root")];
@@ -50,6 +50,7 @@ mock.module("../config/loader.js", () => ({
50
50
  "openrouter",
51
51
  "brave",
52
52
  "perplexity",
53
+ "tavily",
53
54
  ],
54
55
  }));
55
56
 
@@ -266,17 +266,19 @@ describe("skill_load tool", () => {
266
266
  expect(markers.length).toBe(1);
267
267
  });
268
268
 
269
- test("returns error when skill has missing include", async () => {
269
+ test("continues when skill has missing include", async () => {
270
270
  writeSkillWithIncludes("parent", "Parent", "Has missing child", "Body", [
271
271
  "missing-child",
272
272
  ]);
273
273
  writeFileSync(join(TEST_DIR, "skills", "SKILLS.md"), "- parent\n");
274
274
 
275
275
  const result = await executeSkillLoad({ skill: "parent" });
276
- expect(result.isError).toBe(true);
276
+ expect(result.isError).toBe(false);
277
+ expect(result.content).toContain("Skill: Parent");
278
+ expect(result.content).toContain("Suggested Included Skills (not loaded):");
277
279
  expect(result.content).toContain("missing-child");
278
- expect(result.content).toContain("not found");
279
- expect(result.content).not.toContain("<loaded_skill");
280
+ expect(result.content).toContain('<loaded_skill id="parent"');
281
+ expect(result.content).not.toContain('<loaded_skill id="missing-child"');
280
282
  });
281
283
 
282
284
  test("returns error when skill has circular include", async () => {
@@ -317,7 +319,7 @@ describe("skill_load tool", () => {
317
319
  expect(result.content).toContain("<loaded_skill");
318
320
  });
319
321
 
320
- test("failed include validation (missing) emits no loaded_skill marker", async () => {
322
+ test("missing include emits only the parent loaded_skill marker", async () => {
321
323
  const skillDir = join(TEST_DIR, "skills", "marker-missing");
322
324
  mkdirSync(skillDir, { recursive: true });
323
325
  writeFileSync(
@@ -327,9 +329,13 @@ describe("skill_load tool", () => {
327
329
  writeFileSync(join(TEST_DIR, "skills", "SKILLS.md"), "- marker-missing\n");
328
330
 
329
331
  const result = await executeSkillLoad({ skill: "marker-missing" });
330
- expect(result.isError).toBe(true);
331
- expect(result.content).not.toContain("<loaded_skill");
332
- expect(result.content).not.toMatch(/<loaded_skill\s/);
332
+ expect(result.isError).toBe(false);
333
+ expect(result.content).toContain("Suggested Included Skills (not loaded):");
334
+ expect(result.content).toContain("nonexistent");
335
+ const markers = result.content.match(/<loaded_skill/g) || [];
336
+ expect(markers.length).toBe(1);
337
+ expect(result.content).toContain('<loaded_skill id="marker-missing"');
338
+ expect(result.content).not.toContain('<loaded_skill id="nonexistent"');
333
339
  });
334
340
 
335
341
  test("failed include validation (cycle) emits no loaded_skill marker", async () => {
@@ -365,6 +371,26 @@ describe("skill_load tool", () => {
365
371
  expect(result.content).toContain("Skill: No Includes");
366
372
  });
367
373
 
374
+ test("bundled app-builder loads without includes", async () => {
375
+ const result = await executeSkillLoad({ skill: "app-builder" });
376
+
377
+ expect(result.isError).toBe(false);
378
+ expect(result.content).toContain("Skill: App Builder");
379
+ expect(result.content).toContain("Included Skills (immediate): none");
380
+ expect(result.content).toContain('<loaded_skill id="app-builder"');
381
+ });
382
+
383
+ test("bundled phone-calls loads when setup includes are unavailable", async () => {
384
+ const result = await executeSkillLoad({ skill: "phone-calls" });
385
+
386
+ expect(result.isError).toBe(false);
387
+ expect(result.content).toContain("Skill: Phone Calls");
388
+ expect(result.content).toContain("Suggested Included Skills (not loaded):");
389
+ expect(result.content).toContain("twilio-setup");
390
+ expect(result.content).toContain('<loaded_skill id="phone-calls"');
391
+ expect(result.content).not.toContain('<loaded_skill id="twilio-setup"');
392
+ });
393
+
368
394
  test("skill_load output includes immediate child metadata", async () => {
369
395
  writeSkill("child-skill", "Child Skill", "A child skill", "Child body");
370
396
  const parentDir = join(TEST_DIR, "skills", "parent-with-children");
@@ -883,7 +909,7 @@ describe("skill_load tool", () => {
883
909
  expect(mockAutoInstall).toHaveBeenCalledWith("trans-c");
884
910
  });
885
911
 
886
- test("returns error when auto-install of missing include fails", async () => {
912
+ test("continues when auto-install of missing include fails", async () => {
887
913
  writeSkillWithIncludes(
888
914
  "fail-parent",
889
915
  "Fail Parent",
@@ -902,10 +928,12 @@ describe("skill_load tool", () => {
902
928
  });
903
929
 
904
930
  const result = await executeSkillLoad({ skill: "fail-parent" });
905
- expect(result.isError).toBe(true);
931
+ expect(result.isError).toBe(false);
932
+ expect(result.content).toContain("Skill: Fail Parent");
933
+ expect(result.content).toContain("Suggested Included Skills (not loaded):");
906
934
  expect(result.content).toContain("dep-x");
907
- expect(result.content).toContain("not found");
908
- expect(result.content).not.toContain("<loaded_skill");
935
+ expect(result.content).toContain('<loaded_skill id="fail-parent"');
936
+ expect(result.content).not.toContain('<loaded_skill id="dep-x"');
909
937
  });
910
938
 
911
939
  test("stops after MAX_INSTALL_ROUNDS", async () => {
@@ -941,10 +969,8 @@ describe("skill_load tool", () => {
941
969
  });
942
970
 
943
971
  const result = await executeSkillLoad({ skill: "loop-root" });
944
- // Should terminate with an error (the final dep is still missing)
945
- expect(result.isError).toBe(true);
946
- expect(result.content).toContain("not found");
947
- // Should have terminated — installCount should be bounded by MAX_INSTALL_ROUNDS (5)
972
+ expect(result.isError).toBe(false);
973
+ expect(result.content).toContain("Suggested Included Skills (not loaded):");
948
974
  expect(installCount).toBeLessThanOrEqual(5);
949
975
  });
950
976
  });
@@ -1,6 +1,7 @@
1
1
  import {
2
2
  existsSync,
3
3
  mkdirSync,
4
+ readdirSync,
4
5
  readFileSync,
5
6
  rmSync,
6
7
  symlinkSync,
@@ -678,3 +679,41 @@ describe("bundled computer-use skill", () => {
678
679
  ]);
679
680
  });
680
681
  });
682
+
683
+ describe("skill source ownership", () => {
684
+ const BUNDLED_SKILLS_DIR = join(
685
+ import.meta.dir,
686
+ "..",
687
+ "config",
688
+ "bundled-skills",
689
+ );
690
+ const FIRST_PARTY_SKILLS_DIR = join(
691
+ import.meta.dir,
692
+ "..",
693
+ "..",
694
+ "..",
695
+ "skills",
696
+ );
697
+
698
+ function collectSourceSkillIds(rootDir: string): string[] {
699
+ return readdirSync(rootDir, { withFileTypes: true })
700
+ .filter(
701
+ (entry) =>
702
+ entry.isDirectory() &&
703
+ existsSync(join(rootDir, entry.name, "SKILL.md")),
704
+ )
705
+ .map((entry) => entry.name)
706
+ .sort((a, b) => a.localeCompare(b));
707
+ }
708
+
709
+ test("bundled skills are not duplicated in the first-party source catalog", () => {
710
+ const firstPartyIds = new Set(
711
+ collectSourceSkillIds(FIRST_PARTY_SKILLS_DIR),
712
+ );
713
+ const duplicates = collectSourceSkillIds(BUNDLED_SKILLS_DIR).filter((id) =>
714
+ firstPartyIds.has(id),
715
+ );
716
+
717
+ expect(duplicates).toEqual([]);
718
+ });
719
+ });
@@ -110,16 +110,39 @@ mock.module("../prompts/system-prompt.js", () => ({
110
110
  buildSubagentSystemPrompt: () => "subagent system",
111
111
  }));
112
112
 
113
- // Provider registry return distinct stubs so we can verify the selection.
113
+ // Provider registry + connection resolver routing goes through
114
+ // `provider_connection` exclusively. `getProvider` is kept here purely
115
+ // because the registry module still exports it; the production code under
116
+ // test does not call it.
114
117
  const anthropicStub = { name: "anthropic" };
115
118
  const openaiStub = { name: "openai" };
116
119
 
117
120
  mock.module("../providers/registry.js", () => ({
118
121
  getProvider: (name: string) => {
119
- if (name === "anthropic") return anthropicStub;
120
- if (name === "openai") return openaiStub;
121
- throw new Error(`unknown provider: ${name}`);
122
+ throw new Error(`legacy getProvider should not be called: ${name}`);
122
123
  },
124
+ resolveProviderFromConnection: async (connection: { name: string }) => {
125
+ if (connection.name === "anthropic-conn") return anthropicStub;
126
+ if (connection.name === "openai-conn") return openaiStub;
127
+ return null;
128
+ },
129
+ clearConnectionProviderCache: () => {},
130
+ }));
131
+
132
+ // Connection lookup — feeds `resolveProviderFromConnection` above. The DB
133
+ // is stubbed; tests don't touch SQLite.
134
+ mock.module("../providers/inference/connections.js", () => ({
135
+ getConnection: (_db: unknown, name: string) => {
136
+ if (name === "anthropic-conn")
137
+ return { name: "anthropic-conn", provider: "anthropic", auth: { type: "platform" } };
138
+ if (name === "openai-conn")
139
+ return { name: "openai-conn", provider: "openai", auth: { type: "platform" } };
140
+ return null;
141
+ },
142
+ }));
143
+
144
+ mock.module("../memory/db-connection.js", () => ({
145
+ getDb: () => ({}),
123
146
  }));
124
147
 
125
148
  // Mutable LLM config — tests rewrite this per-case.
@@ -154,7 +177,11 @@ function setLlmConfig(raw: unknown): void {
154
177
  describe("SubagentManager — provider call-site routing", () => {
155
178
  test("wraps the default provider in CallSiteRoutingProvider", async () => {
156
179
  setLlmConfig({
157
- default: { provider: "anthropic", model: "claude-opus-4-7" },
180
+ default: {
181
+ provider: "anthropic",
182
+ provider_connection: "anthropic-conn",
183
+ model: "claude-opus-4-7",
184
+ },
158
185
  });
159
186
 
160
187
  capturedProvider = undefined;
@@ -172,10 +199,27 @@ describe("SubagentManager — provider call-site routing", () => {
172
199
  });
173
200
 
174
201
  test("the wrapped provider exposes the default provider's name (stable identity for outer wrappers)", async () => {
202
+ // Note: `provider_connection` lives on `ProfileEntry` and `LLMConfigBase`,
203
+ // NOT on `LLMCallSiteConfig` (which is `LLMConfigFragment.extend({
204
+ // profile })`). Setting `provider_connection` directly on a `callSites.*`
205
+ // entry would be silently stripped by Zod. The correct shape for an
206
+ // alternate-provider call-site override is a profile reference, defined
207
+ // here as `altOpenai`.
175
208
  setLlmConfig({
176
- default: { provider: "anthropic", model: "claude-opus-4-7" },
209
+ default: {
210
+ provider: "anthropic",
211
+ provider_connection: "anthropic-conn",
212
+ model: "claude-opus-4-7",
213
+ },
214
+ profiles: {
215
+ altOpenai: {
216
+ provider: "openai",
217
+ provider_connection: "openai-conn",
218
+ model: "gpt-5.4",
219
+ },
220
+ },
177
221
  callSites: {
178
- subagentSpawn: { provider: "openai", model: "gpt-5.4" },
222
+ subagentSpawn: { profile: "altOpenai" },
179
223
  },
180
224
  });
181
225
 
@@ -202,7 +246,11 @@ describe("SubagentManager — provider call-site routing", () => {
202
246
 
203
247
  test("falls back to default provider when subagentSpawn callSite is absent", async () => {
204
248
  setLlmConfig({
205
- default: { provider: "anthropic", model: "claude-opus-4-7" },
249
+ default: {
250
+ provider: "anthropic",
251
+ provider_connection: "anthropic-conn",
252
+ model: "claude-opus-4-7",
253
+ },
206
254
  // No subagentSpawn override.
207
255
  });
208
256
 
@@ -224,7 +272,11 @@ describe("SubagentManager — provider call-site routing", () => {
224
272
 
225
273
  test("copies parent guardian and auth context into spawned conversation", async () => {
226
274
  setLlmConfig({
227
- default: { provider: "anthropic", model: "claude-opus-4-7" },
275
+ default: {
276
+ provider: "anthropic",
277
+ provider_connection: "anthropic-conn",
278
+ model: "claude-opus-4-7",
279
+ },
228
280
  });
229
281
 
230
282
  const parentTrustContext = {
@@ -273,11 +325,18 @@ describe("SubagentManager — provider call-site routing", () => {
273
325
  // ── Direct unit test for CallSiteRoutingProvider's selection logic ─────────
274
326
 
275
327
  describe("CallSiteRoutingProvider — selectProvider behavior", () => {
276
- test("routes to the resolved provider when callSite.provider differs from default", async () => {
328
+ test("routes to the resolved provider when callSite resolves to a profile with provider_connection", async () => {
277
329
  setLlmConfig({
278
330
  default: { provider: "anthropic", model: "claude-opus-4-7" },
331
+ profiles: {
332
+ altOpenai: {
333
+ provider: "openai",
334
+ provider_connection: "openai-conn",
335
+ model: "gpt-5.4",
336
+ },
337
+ },
279
338
  callSites: {
280
- subagentSpawn: { provider: "openai", model: "gpt-5.4" },
339
+ subagentSpawn: { profile: "altOpenai" },
281
340
  },
282
341
  });
283
342
 
@@ -309,10 +368,13 @@ describe("CallSiteRoutingProvider — selectProvider behavior", () => {
309
368
  },
310
369
  };
311
370
 
312
- const wrapper = new CallSiteRoutingProvider(defaultProvider, (name) => {
313
- if (name === "openai") return altProvider;
314
- return undefined;
315
- });
371
+ const wrapper = new CallSiteRoutingProvider(
372
+ defaultProvider,
373
+ async (connectionName) => {
374
+ if (connectionName === "openai-conn") return altProvider;
375
+ return null;
376
+ },
377
+ );
316
378
 
317
379
  await wrapper.sendMessage([], undefined, undefined, {
318
380
  config: { callSite: "subagentSpawn" },
@@ -347,7 +409,7 @@ describe("CallSiteRoutingProvider — selectProvider behavior", () => {
347
409
 
348
410
  const wrapper = new CallSiteRoutingProvider(
349
411
  defaultProvider,
350
- () => undefined,
412
+ async () => null,
351
413
  );
352
414
 
353
415
  await wrapper.sendMessage([], undefined, undefined, {
@@ -532,7 +532,7 @@ describe("GET /v1/suggestion", () => {
532
532
  );
533
533
  });
534
534
 
535
- test("uses conversationStarters call site", async () => {
535
+ test("uses replySuggestion call site", async () => {
536
536
  const provider = makeMockProvider("Quick reply");
537
537
  mockGetConfiguredProvider.mockImplementation(async () => provider);
538
538
  mockGetConversationByKey.mockImplementation(() => ({
@@ -558,7 +558,7 @@ describe("GET /v1/suggestion", () => {
558
558
  const options = callArgs[3] as
559
559
  | { config?: { callSite?: string } }
560
560
  | undefined;
561
- expect(options?.config?.callSite).toBe("conversationStarters");
561
+ expect(options?.config?.callSite).toBe("replySuggestion");
562
562
  });
563
563
 
564
564
  test("disables thinking and zeros effort to avoid Anthropic temp/thinking 400", async () => {
@@ -612,7 +612,7 @@ describe("GET /v1/suggestion", () => {
612
612
  // whenever the request triggers extended thinking (e.g. Opus 4.x at
613
613
  // `effort: "xhigh"`). The suggestion generator must only send a
614
614
  // single user-role message so it stays compatible with every
615
- // possible `conversationStarters` call-site config.
615
+ // possible `replySuggestion` call-site config.
616
616
  const provider = makeMockProvider("<reply>Sure, works for me</reply>");
617
617
  mockGetConfiguredProvider.mockImplementation(async () => provider);
618
618
  mockGetConversationByKey.mockImplementation(() => ({