@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
@@ -12,14 +12,8 @@
12
12
  */
13
13
  import { describe, expect, mock, test } from "bun:test";
14
14
 
15
- import { _setOverridesForTesting } from "../config/assistant-feature-flags.js";
16
15
  import type { Message, ProviderResponse } from "../providers/types.js";
17
16
 
18
- // This test exercises v1 conversation routing. The `memory-v2-enabled` flag
19
- // (registry default `true`) flips memory routing to v2 — disable it here so
20
- // the v1 paths under test stay active.
21
- _setOverridesForTesting({ "memory-v2-enabled": false });
22
-
23
17
  // Use an object wrapper so TypeScript doesn't narrow the captured type to
24
18
  // `undefined` based on the initial assignment in the test setup.
25
19
  const captured: {
@@ -46,9 +40,28 @@ mock.module("../memory/guardian-action-store.js", () => ({
46
40
  resolveGuardianActionRequest: () => {},
47
41
  }));
48
42
 
43
+ const mockProviderStub = { name: "mock-provider" };
49
44
  mock.module("../providers/registry.js", () => ({
50
- getProvider: () => ({ name: "mock-provider" }),
45
+ getProvider: () => mockProviderStub,
51
46
  initializeProviders: () => {},
47
+ listProviders: () => ["anthropic", "openai", "gemini"],
48
+ resolveProviderFromConnection: async () => mockProviderStub,
49
+ }));
50
+
51
+ // Connection-aware resolver path: satisfy
52
+ // `tryResolveProviderForConnectionName` lookups so resolveDefaultProvider
53
+ // returns a usable provider for the inline `anthropic-conn` fixture.
54
+ mock.module("../providers/inference/connections.js", () => ({
55
+ getConnection: (_db: unknown, name: string) => ({
56
+ id: 1,
57
+ name,
58
+ provider: "anthropic",
59
+ auth_strategy: "user_managed_credential",
60
+ credential_alias: null,
61
+ metadata_json: null,
62
+ created_at: new Date().toISOString(),
63
+ updated_at: new Date().toISOString(),
64
+ }),
52
65
  }));
53
66
 
54
67
  mock.module("../config/loader.js", () => ({
@@ -57,6 +70,7 @@ mock.module("../config/loader.js", () => ({
57
70
  llm: {
58
71
  default: {
59
72
  provider: "anthropic",
73
+ provider_connection: "anthropic-conn",
60
74
  model: "claude-opus-4-6",
61
75
  maxTokens: 4096,
62
76
  effort: "max" as const,
@@ -83,6 +97,7 @@ mock.module("../config/loader.js", () => ({
83
97
  pricingOverrides: [],
84
98
  },
85
99
  rateLimit: { maxRequestsPerMinute: 0 },
100
+ memory: { v2: { enabled: false } },
86
101
  daemon: {
87
102
  startupSocketWaitMs: 5000,
88
103
  stopTimeoutMs: 5000,
@@ -1,17 +1,11 @@
1
1
  import { beforeEach, describe, expect, mock, test } from "bun:test";
2
2
 
3
3
  import type { AgentEvent } from "../agent/loop.js";
4
- import { _setOverridesForTesting } from "../config/assistant-feature-flags.js";
5
4
  import type { UserMessageAttachment } from "../daemon/message-protocol.js";
6
5
  import { resetPluginRegistryAndRegisterDefaults } from "../plugins/defaults/index.js";
7
6
  import type { Message, ProviderResponse } from "../providers/types.js";
8
7
  import { ProviderError } from "../util/errors.js";
9
8
 
10
- // This test exercises v1 conversation routing. The `memory-v2-enabled` flag
11
- // (registry default `true`) flips memory routing to v2 — disable it here so
12
- // the v1 paths under test stay active.
13
- _setOverridesForTesting({ "memory-v2-enabled": false });
14
-
15
9
  mock.module("../util/logger.js", () => ({
16
10
  getLogger: () =>
17
11
  new Proxy({} as Record<string, unknown>, { get: () => () => {} }),
@@ -63,6 +57,7 @@ mock.module("../config/loader.js", () => ({
63
57
  pricingOverrides: [],
64
58
  },
65
59
  rateLimit: { maxRequestsPerMinute: 0 },
60
+ memory: { v2: { enabled: false } },
66
61
  services: {
67
62
  inference: {
68
63
  mode: "your-own",
@@ -1,11 +1,20 @@
1
1
  import { beforeEach, describe, expect, mock, test } from "bun:test";
2
2
 
3
- import { _setOverridesForTesting } from "../config/assistant-feature-flags.js";
4
-
5
- // This test exercises v1 conversation routing. The `memory-v2-enabled` flag
6
- // (registry default `true`) flips memory routing to v2 — disable it here so
7
- // the v1 paths under test stay active.
8
- _setOverridesForTesting({ "memory-v2-enabled": false });
3
+ // This test exercises v1 PKB injection. `config.memory.v2.enabled` (default
4
+ // `true`) makes the PKB injector go silent — force it off here so the v1
5
+ // injection chain assertions stay meaningful.
6
+ const realLoaderForAssemblyTest = await import("../config/loader.js");
7
+ const realGetConfigForAssemblyTest = realLoaderForAssemblyTest.getConfig;
8
+ mock.module("../config/loader.js", () => ({
9
+ ...realLoaderForAssemblyTest,
10
+ getConfig: () => {
11
+ const real = realGetConfigForAssemblyTest();
12
+ return {
13
+ ...real,
14
+ memory: { ...real.memory, v2: { ...real.memory.v2, enabled: false } },
15
+ };
16
+ },
17
+ }));
9
18
 
10
19
  // PKB search is mocked so the reminder-hints tests can assert behavior
11
20
  // without standing up Qdrant. The mock returns whatever is staged in
@@ -1870,7 +1879,7 @@ describe("applyRuntimeInjections — PKB relevance hints", () => {
1870
1879
  },
1871
1880
  ];
1872
1881
 
1873
- const FLAT_REMINDER = buildPkbReminder([]);
1882
+ const FLAT_REMINDER = buildPkbReminder([], false);
1874
1883
 
1875
1884
  // Use a platform-agnostic absolute workspace root so the tests work on
1876
1885
  // macOS and Linux runners alike. `pkbRoot` sits under `pkbWorkingDir` to
@@ -2126,7 +2135,7 @@ describe("applyRuntimeInjections — PKB relevance hints", () => {
2126
2135
  role: "user",
2127
2136
  content: [
2128
2137
  { type: "text", text: "hello" },
2129
- { type: "text", text: buildPkbReminder([]) },
2138
+ { type: "text", text: buildPkbReminder([], false) },
2130
2139
  ],
2131
2140
  };
2132
2141
  const hintedMessage: Message = {
@@ -2135,7 +2144,7 @@ describe("applyRuntimeInjections — PKB relevance hints", () => {
2135
2144
  { type: "text", text: "hello" },
2136
2145
  {
2137
2146
  type: "text",
2138
- text: buildPkbReminder(["topics/alpha.md", "topics/beta.md"]),
2147
+ text: buildPkbReminder(["topics/alpha.md", "topics/beta.md"], false),
2139
2148
  },
2140
2149
  ],
2141
2150
  };
@@ -4751,7 +4760,7 @@ describe("applyRuntimeInjections blocks.pkbSystemReminder", () => {
4751
4760
  mode: "full",
4752
4761
  });
4753
4762
 
4754
- const expected = buildPkbReminder([]);
4763
+ const expected = buildPkbReminder([], false);
4755
4764
  expect(blocks.pkbSystemReminder).toBe(expected);
4756
4765
  });
4757
4766
 
@@ -1,10 +1,16 @@
1
- import { describe, expect, test } from "bun:test";
1
+ import { writeFileSync } from "node:fs";
2
+ import { afterEach, beforeEach, describe, expect, test } from "bun:test";
2
3
 
4
+ import {
5
+ invalidateConfigCache,
6
+ loadRawConfig,
7
+ } from "../config/loader.js";
3
8
  import {
4
9
  classifySlash,
5
10
  resolveSlash,
6
11
  type SlashContext,
7
12
  } from "../daemon/conversation-slash.js";
13
+ import { getWorkspaceConfigPath } from "../util/platform.js";
8
14
 
9
15
  function makeSlashContext(overrides: Partial<SlashContext> = {}): SlashContext {
10
16
  return {
@@ -37,12 +43,12 @@ describe("resolveSlash /commands interface-aware help", () => {
37
43
  "/commands — List all available commands",
38
44
  "/compact — Force context compaction immediately",
39
45
  "/context — Show conversation context usage",
46
+ "/model — List or switch inference profile",
40
47
  "/models — List all available models",
41
48
  "/status — Show conversation status and context usage",
42
49
  "/btw — Ask a side question while the assistant is working",
43
50
  "/fork — Fork the current conversation into a new branch",
44
51
  ]);
45
- expect(lines).not.toContain("/model — Switch the active model");
46
52
  });
47
53
 
48
54
  test("renders iOS command help with /fork", async () => {
@@ -53,6 +59,7 @@ describe("resolveSlash /commands interface-aware help", () => {
53
59
  "/commands — List all available commands",
54
60
  "/compact — Force context compaction immediately",
55
61
  "/context — Show conversation context usage",
62
+ "/model — List or switch inference profile",
56
63
  "/models — List all available models",
57
64
  "/status — Show conversation status and context usage",
58
65
  "/btw — Ask a side question while the assistant is working",
@@ -68,6 +75,7 @@ describe("resolveSlash /commands interface-aware help", () => {
68
75
  "/commands — List all available commands",
69
76
  "/compact — Force context compaction immediately",
70
77
  "/context — Show conversation context usage",
78
+ "/model — List or switch inference profile",
71
79
  "/models — List all available models",
72
80
  "/status — Show conversation status and context usage",
73
81
  "/btw — Ask a side question while the assistant is working",
@@ -80,6 +88,7 @@ describe("resolveSlash /commands interface-aware help", () => {
80
88
  "/commands — List all available commands",
81
89
  "/compact — Force context compaction immediately",
82
90
  "/context — Show conversation context usage",
91
+ "/model — List or switch inference profile",
83
92
  "/models — List all available models",
84
93
  "/status — Show conversation status and context usage",
85
94
  ]);
@@ -90,6 +99,7 @@ describe("resolveSlash /commands interface-aware help", () => {
90
99
  expect(lines).toEqual([
91
100
  "/commands — List all available commands",
92
101
  "/compact — Force context compaction immediately",
102
+ "/model — List or switch inference profile",
93
103
  "/models — List all available models",
94
104
  ]);
95
105
  });
@@ -128,6 +138,55 @@ describe("resolveSlash command contract", () => {
128
138
  });
129
139
  });
130
140
 
141
+ describe("resolveSlash /compact target override", () => {
142
+ test("plain /compact returns no override", async () => {
143
+ const result = await resolveSlash("/compact");
144
+ expect(result).toEqual({ kind: "compact" });
145
+ });
146
+
147
+ test("/compact <integer> sets explicit token target", async () => {
148
+ const result = await resolveSlash("/compact 30000");
149
+ expect(result).toEqual({
150
+ kind: "compact",
151
+ targetInputTokensOverride: 30000,
152
+ });
153
+ });
154
+
155
+ test("/compact <n>k expands to thousands", async () => {
156
+ const result = await resolveSlash("/compact 30k");
157
+ expect(result).toEqual({
158
+ kind: "compact",
159
+ targetInputTokensOverride: 30_000,
160
+ });
161
+ });
162
+
163
+ test("/compact <n>m expands to millions", async () => {
164
+ const result = await resolveSlash("/compact 1.5M");
165
+ expect(result).toEqual({
166
+ kind: "compact",
167
+ targetInputTokensOverride: 1_500_000,
168
+ });
169
+ });
170
+
171
+ test("/compact rejects malformed args with usage hint", async () => {
172
+ const result = await resolveSlash("/compact bogus");
173
+ expect(result.kind).toBe("unknown");
174
+ if (result.kind !== "unknown") throw new Error("expected unknown");
175
+ expect(result.message).toContain("`bogus`");
176
+ expect(result.message).toContain("/compact");
177
+ });
178
+
179
+ test("/compact rejects zero", async () => {
180
+ const result = await resolveSlash("/compact 0");
181
+ expect(result.kind).toBe("unknown");
182
+ });
183
+
184
+ test("/compact rejects negative numbers", async () => {
185
+ const result = await resolveSlash("/compact -50");
186
+ expect(result.kind).toBe("unknown");
187
+ });
188
+ });
189
+
131
190
  describe("classifySlash is a pure classifier matching resolveSlash kinds", () => {
132
191
  // Lookahead in `buildPassthroughBatch` must not run `resolveSlash`'s side
133
192
  // effects. The pure classifier is synchronous, takes no side-effecting
@@ -141,11 +200,16 @@ describe("classifySlash is a pure classifier matching resolveSlash kinds", () =>
141
200
  { input: "/status", kind: "unknown" },
142
201
  { input: "/commands", kind: "unknown" },
143
202
  { input: "/compact", kind: "compact" },
203
+ { input: "/compact 30000", kind: "compact" },
204
+ { input: "/compact 30k", kind: "compact" },
205
+ { input: "/compact 1.5M", kind: "compact" },
206
+ { input: "/compact bogus", kind: "unknown" },
144
207
  { input: "/model", kind: "unknown" },
145
208
  { input: "/model foo", kind: "unknown" },
146
209
  { input: "/opus", kind: "unknown" },
147
210
  { input: "hello", kind: "passthrough" },
148
211
  { input: " /compact ", kind: "compact" },
212
+ { input: " /compact 50k ", kind: "compact" },
149
213
  { input: "/models foo", kind: "passthrough" },
150
214
  ];
151
215
 
@@ -160,3 +224,131 @@ describe("classifySlash is a pure classifier matching resolveSlash kinds", () =>
160
224
  });
161
225
  }
162
226
  });
227
+
228
+ // ── /model — inference profile switcher ────────────────────────────
229
+
230
+ function writeFixtureConfig(config: Record<string, unknown>): void {
231
+ writeFileSync(getWorkspaceConfigPath(), JSON.stringify(config), "utf-8");
232
+ invalidateConfigCache();
233
+ }
234
+
235
+ describe("resolveSlash /model — inference profile switcher", () => {
236
+ beforeEach(() => {
237
+ writeFixtureConfig({
238
+ llm: {
239
+ profiles: {
240
+ balanced: {
241
+ label: "Balanced",
242
+ description: "Default mix of speed and quality",
243
+ },
244
+ "cost-optimized": {
245
+ label: "Cost-optimized",
246
+ description: "Cheaper models, slower",
247
+ },
248
+ "short-context": {
249
+ label: "Short context",
250
+ status: "disabled",
251
+ },
252
+ },
253
+ profileOrder: ["balanced", "cost-optimized", "short-context"],
254
+ activeProfile: "balanced",
255
+ },
256
+ });
257
+ });
258
+
259
+ afterEach(() => {
260
+ invalidateConfigCache();
261
+ });
262
+
263
+ test("`/model` lists profiles with current marker, status, and description", async () => {
264
+ const result = await resolveSlash("/model");
265
+ expect(result.kind).toBe("unknown");
266
+ if (result.kind !== "unknown") throw new Error("expected unknown kind");
267
+ expect(result.message).toContain("Inference profiles:");
268
+ expect(result.message).toContain(
269
+ "`balanced` (Balanced) **[current]** — Default mix of speed and quality",
270
+ );
271
+ expect(result.message).toContain(
272
+ "`cost-optimized` (Cost-optimized) — Cheaper models, slower",
273
+ );
274
+ expect(result.message).toContain(
275
+ "`short-context` (Short context) *(disabled)*",
276
+ );
277
+ expect(result.message).toContain("Switch with `/model <name>`.");
278
+ });
279
+
280
+ test("`/model <name>` switches the active profile and writes config to disk", async () => {
281
+ const result = await resolveSlash("/model cost-optimized");
282
+ expect(result.kind).toBe("unknown");
283
+ if (result.kind !== "unknown") throw new Error("expected unknown kind");
284
+ expect(result.message).toBe(
285
+ "Switched to profile `cost-optimized` (Cost-optimized).",
286
+ );
287
+
288
+ const persisted = loadRawConfig() as {
289
+ llm?: { activeProfile?: string };
290
+ };
291
+ expect(persisted.llm?.activeProfile).toBe("cost-optimized");
292
+ });
293
+
294
+ test("`/model <unknown>` returns an error with available profile names", async () => {
295
+ const result = await resolveSlash("/model gemini");
296
+ expect(result.kind).toBe("unknown");
297
+ if (result.kind !== "unknown") throw new Error("expected unknown kind");
298
+ expect(result.message).toContain("Profile `gemini` not found.");
299
+ expect(result.message).toContain("`balanced`");
300
+ expect(result.message).toContain("`cost-optimized`");
301
+ });
302
+
303
+ test("`/model <disabled>` refuses to switch and points at Settings", async () => {
304
+ const result = await resolveSlash("/model short-context");
305
+ expect(result.kind).toBe("unknown");
306
+ if (result.kind !== "unknown") throw new Error("expected unknown kind");
307
+ expect(result.message).toBe(
308
+ "Profile `short-context` is disabled. Enable it in **Settings → Models & Services** first.",
309
+ );
310
+ // Disk should NOT have been written.
311
+ const persisted = loadRawConfig() as {
312
+ llm?: { activeProfile?: string };
313
+ };
314
+ expect(persisted.llm?.activeProfile).toBe("balanced");
315
+ });
316
+
317
+ test("`/model <current>` is a no-op with a friendly message", async () => {
318
+ const result = await resolveSlash("/model balanced");
319
+ expect(result.kind).toBe("unknown");
320
+ if (result.kind !== "unknown") throw new Error("expected unknown kind");
321
+ expect(result.message).toBe(
322
+ "Already using profile `balanced` (Balanced).",
323
+ );
324
+ });
325
+
326
+ test("`/model` with no profiles defined points at Settings", async () => {
327
+ writeFixtureConfig({
328
+ llm: { profiles: {}, profileOrder: [] },
329
+ });
330
+ const result = await resolveSlash("/model");
331
+ expect(result.kind).toBe("unknown");
332
+ if (result.kind !== "unknown") throw new Error("expected unknown kind");
333
+ expect(result.message).toBe(
334
+ "No inference profiles are defined. Use **Settings → Models & Services** to create one.",
335
+ );
336
+ });
337
+
338
+ test("`/model <name>` trims surrounding whitespace from the argument", async () => {
339
+ const result = await resolveSlash("/model cost-optimized ");
340
+ expect(result.kind).toBe("unknown");
341
+ if (result.kind !== "unknown") throw new Error("expected unknown kind");
342
+ expect(result.message).toBe(
343
+ "Switched to profile `cost-optimized` (Cost-optimized).",
344
+ );
345
+ });
346
+
347
+ test("`/models` (plural) is not parsed as a /model invocation", async () => {
348
+ // /models is a separate command handled elsewhere; this test guards the
349
+ // boundary so we don't accidentally swallow it as a typo'd /model.
350
+ expect(classifySlash("/models")).toBe("unknown");
351
+ // /models foo is passthrough (existing behavior).
352
+ expect(classifySlash("/models foo")).toBe("passthrough");
353
+ });
354
+ });
@@ -5,15 +5,9 @@ import type {
5
5
  CheckpointDecision,
6
6
  CheckpointInfo,
7
7
  } from "../agent/loop.js";
8
- import { _setOverridesForTesting } from "../config/assistant-feature-flags.js";
9
8
  import type { ServerMessage } from "../daemon/message-protocol.js";
10
9
  import type { Message, ProviderResponse } from "../providers/types.js";
11
10
 
12
- // This test exercises v1 conversation routing. The `memory-v2-enabled` flag
13
- // (registry default `true`) flips memory routing to v2 — disable it here so
14
- // the v1 paths under test stay active.
15
- _setOverridesForTesting({ "memory-v2-enabled": false });
16
-
17
11
  // ---------------------------------------------------------------------------
18
12
  // Mocks — must precede the Conversation import so Bun applies them at load time.
19
13
  // ---------------------------------------------------------------------------
@@ -66,6 +60,7 @@ mock.module("../config/loader.js", () => ({
66
60
  pricingOverrides: [],
67
61
  },
68
62
  rateLimit: { maxRequestsPerMinute: 0 },
63
+ memory: { v2: { enabled: false } },
69
64
  daemon: {
70
65
  startupSocketWaitMs: 5000,
71
66
  stopTimeoutMs: 5000,
@@ -1,13 +1,19 @@
1
- import { describe, expect, test } from "bun:test";
2
-
3
- import {
4
- createSurfaceMutex,
5
- handleSurfaceAction,
6
- type SurfaceConversationContext,
7
- surfaceProxyResolver,
8
- } from "../daemon/conversation-surfaces.js";
1
+ import { beforeEach, describe, expect, mock, test } from "bun:test";
2
+
3
+ import type { ServerMessage } from "../daemon/message-protocol.js";
4
+
5
+ let broadcastedMessages: ServerMessage[] = [];
6
+ const realEventHub = await import("../runtime/assistant-event-hub.js");
7
+ mock.module("../runtime/assistant-event-hub.js", () => ({
8
+ ...realEventHub,
9
+ broadcastMessage: (msg: ServerMessage) => broadcastedMessages.push(msg),
10
+ }));
11
+
12
+ const { createSurfaceMutex, handleSurfaceAction, surfaceProxyResolver } =
13
+ await import("../daemon/conversation-surfaces.js");
14
+
15
+ import type { SurfaceConversationContext } from "../daemon/conversation-surfaces.js";
9
16
  import type {
10
- ServerMessage,
11
17
  SurfaceData,
12
18
  SurfaceType,
13
19
  UiSurfaceShow,
@@ -81,6 +87,10 @@ function makeContext(sent: ServerMessage[] = []): SurfaceConversationContext & {
81
87
  }
82
88
 
83
89
  describe("surface action delivery to assistant", () => {
90
+ beforeEach(() => {
91
+ broadcastedMessages = [];
92
+ });
93
+
84
94
  test("table action button click triggers processMessage with action content", async () => {
85
95
  const sent: ServerMessage[] = [];
86
96
  const ctx = makeContext(sent);
@@ -199,4 +209,155 @@ describe("surface action delivery to assistant", () => {
199
209
  "[User action on app:",
200
210
  );
201
211
  });
212
+
213
+ test("confirmation surface broadcasts ui_surface_complete on action", async () => {
214
+ const sent: ServerMessage[] = [];
215
+ const ctx = makeContext(sent);
216
+
217
+ const showResult = await surfaceProxyResolver(ctx, "ui_show", {
218
+ surface_type: "confirmation",
219
+ title: "Delete files?",
220
+ data: {
221
+ message: "This will permanently delete 3 files.",
222
+ confirmLabel: "Delete",
223
+ cancelLabel: "Keep",
224
+ },
225
+ });
226
+
227
+ expect(showResult.isError).toBe(false);
228
+ expect(showResult.yieldToUser).toBe(true);
229
+
230
+ const showMessage = sent.find(
231
+ (msg): msg is UiSurfaceShow => msg.type === "ui_surface_show",
232
+ ) as UiSurfaceShow;
233
+ const surfaceId = showMessage.surfaceId;
234
+ expect(ctx.pendingSurfaceActions.has(surfaceId)).toBe(true);
235
+
236
+ await handleSurfaceAction(ctx, surfaceId, "confirm", {});
237
+
238
+ const completeMsg = broadcastedMessages.find(
239
+ (m) =>
240
+ (m as unknown as Record<string, unknown>).type ===
241
+ "ui_surface_complete" &&
242
+ (m as unknown as Record<string, unknown>).surfaceId === surfaceId,
243
+ ) as unknown as Record<string, unknown> | undefined;
244
+ expect(completeMsg).toBeDefined();
245
+ expect(completeMsg?.conversationId).toBe("conv-1");
246
+ expect(completeMsg?.summary).toContain("Delete");
247
+ });
248
+
249
+ test("file_upload surface broadcasts ui_surface_complete on action", async () => {
250
+ const sent: ServerMessage[] = [];
251
+ const ctx = makeContext(sent);
252
+
253
+ const showResult = await surfaceProxyResolver(ctx, "ui_show", {
254
+ surface_type: "file_upload",
255
+ title: "Upload documents",
256
+ data: { accept: ".pdf,.docx", maxFiles: 5 },
257
+ });
258
+
259
+ expect(showResult.isError).toBe(false);
260
+ expect(showResult.yieldToUser).toBe(true);
261
+
262
+ const showMessage = sent.find(
263
+ (msg): msg is UiSurfaceShow => msg.type === "ui_surface_show",
264
+ ) as UiSurfaceShow;
265
+ const surfaceId = showMessage.surfaceId;
266
+ expect(ctx.pendingSurfaceActions.has(surfaceId)).toBe(true);
267
+
268
+ await handleSurfaceAction(ctx, surfaceId, "submit", {
269
+ files: [
270
+ {
271
+ filename: "doc.pdf",
272
+ mimeType: "application/pdf",
273
+ data: "base64encodedcontent",
274
+ },
275
+ ],
276
+ });
277
+
278
+ const completeMsg = broadcastedMessages.find(
279
+ (m) =>
280
+ (m as unknown as Record<string, unknown>).type ===
281
+ "ui_surface_complete" &&
282
+ (m as unknown as Record<string, unknown>).surfaceId === surfaceId,
283
+ ) as unknown as Record<string, unknown> | undefined;
284
+ expect(completeMsg).toBeDefined();
285
+ expect(completeMsg?.conversationId).toBe("conv-1");
286
+ });
287
+
288
+ test("file_upload completion event does not include base64 file blobs", async () => {
289
+ const sent: ServerMessage[] = [];
290
+ const ctx = makeContext(sent);
291
+
292
+ await surfaceProxyResolver(ctx, "ui_show", {
293
+ surface_type: "file_upload",
294
+ title: "Upload",
295
+ data: { accept: "*" },
296
+ });
297
+
298
+ const showMessage = sent.find(
299
+ (msg): msg is UiSurfaceShow => msg.type === "ui_surface_show",
300
+ ) as UiSurfaceShow;
301
+ const surfaceId = showMessage.surfaceId;
302
+
303
+ const largeBase64 = "A".repeat(10_000);
304
+ await handleSurfaceAction(ctx, surfaceId, "submit", {
305
+ files: [
306
+ {
307
+ filename: "big.pdf",
308
+ mimeType: "application/pdf",
309
+ data: largeBase64,
310
+ },
311
+ ],
312
+ });
313
+
314
+ const completeMsg = broadcastedMessages.find(
315
+ (m) =>
316
+ (m as unknown as Record<string, unknown>).type ===
317
+ "ui_surface_complete" &&
318
+ (m as unknown as Record<string, unknown>).surfaceId === surfaceId,
319
+ ) as unknown as Record<string, unknown> | undefined;
320
+ expect(completeMsg).toBeDefined();
321
+
322
+ const submittedData = completeMsg?.submittedData as
323
+ | Record<string, unknown>
324
+ | undefined;
325
+ // The files array with base64 blobs should be stripped from the
326
+ // completion event — only the sanitized payload (without files) is sent.
327
+ expect(submittedData?.files).toBeUndefined();
328
+ // The raw base64 content should not appear anywhere in the event
329
+ expect(JSON.stringify(completeMsg)).not.toContain(largeBase64);
330
+ });
331
+
332
+ test("table surface does NOT broadcast ui_surface_complete (not one-shot)", async () => {
333
+ const sent: ServerMessage[] = [];
334
+ const ctx = makeContext(sent);
335
+
336
+ await surfaceProxyResolver(ctx, "ui_show", {
337
+ surface_type: "table",
338
+ title: "Items",
339
+ data: {
340
+ columns: [{ id: "name", label: "Name" }],
341
+ rows: [{ id: "r1", cells: { name: "Item 1" } }],
342
+ },
343
+ actions: [{ id: "select", label: "Select" }],
344
+ });
345
+
346
+ const showMessage = sent.find(
347
+ (msg): msg is UiSurfaceShow => msg.type === "ui_surface_show",
348
+ ) as UiSurfaceShow;
349
+ const surfaceId = showMessage.surfaceId;
350
+
351
+ broadcastedMessages = [];
352
+ await handleSurfaceAction(ctx, surfaceId, "select", {
353
+ selectedIds: ["r1"],
354
+ });
355
+
356
+ const completeMsg = broadcastedMessages.find(
357
+ (m) =>
358
+ (m as unknown as Record<string, unknown>).type ===
359
+ "ui_surface_complete",
360
+ );
361
+ expect(completeMsg).toBeUndefined();
362
+ });
202
363
  });