@vellumai/assistant 0.8.8 → 0.8.9-dev.202606091926.ebb2d62

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 (490) hide show
  1. package/ARCHITECTURE.md +6 -6
  2. package/bun.lock +2 -2
  3. package/docs/activation-funnel-telemetry.md +310 -0
  4. package/examples/plugins/echo/README.md +61 -60
  5. package/examples/plugins/echo/hooks/post-tool-use.ts +18 -0
  6. package/examples/plugins/echo/hooks/stop.ts +16 -0
  7. package/examples/plugins/echo/hooks/user-prompt-submit.ts +18 -0
  8. package/examples/plugins/echo/package.json +1 -2
  9. package/examples/plugins/echo/src/emit.ts +19 -0
  10. package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +7 -6
  11. package/openapi.yaml +273 -121
  12. package/package.json +2 -2
  13. package/scripts/sync-llm-catalog.ts +2 -0
  14. package/src/__tests__/activation-early-marking.test.ts +120 -0
  15. package/src/__tests__/agent-loop-callsite-precedence.test.ts +69 -14
  16. package/src/__tests__/agent-loop-exit-reason.test.ts +204 -144
  17. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +50 -35
  18. package/src/__tests__/agent-loop-output-hooks.test.ts +357 -0
  19. package/src/__tests__/agent-loop-override-profile.test.ts +25 -6
  20. package/src/__tests__/agent-loop-provider-error-recording.test.ts +41 -21
  21. package/src/__tests__/agent-loop-thinking.test.ts +36 -20
  22. package/src/__tests__/agent-loop.test.ts +441 -96
  23. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +14 -14
  24. package/src/__tests__/agent-wake-override-profile.test.ts +17 -21
  25. package/src/__tests__/anthropic-provider.test.ts +23 -8
  26. package/src/__tests__/app-builder-tool-scripts.test.ts +21 -0
  27. package/src/__tests__/app-control-flow.test.ts +1 -1
  28. package/src/__tests__/app-dir-path-guard.test.ts +1 -0
  29. package/src/__tests__/app-executors.test.ts +132 -0
  30. package/src/__tests__/approval-cascade.test.ts +6 -5
  31. package/src/__tests__/approval-routes-http.test.ts +4 -1
  32. package/src/__tests__/background-workers-disk-pressure.test.ts +1 -1
  33. package/src/__tests__/build-persisted-content.test.ts +75 -1
  34. package/src/__tests__/channel-approval-routes.test.ts +1 -1
  35. package/src/__tests__/channel-approvals.test.ts +1 -1
  36. package/src/__tests__/compaction-circuit.test.ts +258 -0
  37. package/src/__tests__/compaction-direct.test.ts +146 -0
  38. package/src/__tests__/compaction-events.test.ts +7 -7
  39. package/src/__tests__/compaction.benchmark.test.ts +1 -1
  40. package/src/__tests__/compactor-web-search-strip.test.ts +213 -0
  41. package/src/__tests__/config-managed-gemini-defaults.test.ts +2 -46
  42. package/src/__tests__/context-overflow-reducer.test.ts +265 -125
  43. package/src/__tests__/context-window-manager-compact-retry.test.ts +121 -15
  44. package/src/__tests__/conversation-abort-tool-results.test.ts +7 -5
  45. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +7 -10
  46. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +78 -119
  47. package/src/__tests__/conversation-agent-loop-overflow.test.ts +158 -234
  48. package/src/__tests__/conversation-agent-loop.test.ts +342 -623
  49. package/src/__tests__/conversation-clean-command.test.ts +5 -2
  50. package/src/__tests__/conversation-confirmation-signals.test.ts +6 -5
  51. package/src/__tests__/conversation-crud-inference-profile.test.ts +7 -9
  52. package/src/__tests__/conversation-error.test.ts +15 -1
  53. package/src/__tests__/conversation-history-web-search.test.ts +6 -1
  54. package/src/__tests__/conversation-media-retry.test.ts +1 -1
  55. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +44 -4
  56. package/src/__tests__/conversation-process-callsite.test.ts +15 -15
  57. package/src/__tests__/conversation-provider-retry-repair.test.ts +66 -65
  58. package/src/__tests__/conversation-queue.test.ts +10 -10
  59. package/src/__tests__/conversation-runtime-assembly.test.ts +1059 -231
  60. package/src/__tests__/conversation-runtime-workspace.test.ts +115 -20
  61. package/src/__tests__/conversation-slash-queue.test.ts +7 -5
  62. package/src/__tests__/conversation-slash-unknown.test.ts +7 -5
  63. package/src/__tests__/conversation-speed-override.test.ts +11 -10
  64. package/src/__tests__/conversation-starter-routes.test.ts +14 -6
  65. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +395 -0
  66. package/src/__tests__/conversation-surfaces-app-control.test.ts +48 -1
  67. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +73 -4
  68. package/src/__tests__/conversation-undo.test.ts +2 -2
  69. package/src/__tests__/conversation-workspace-cache-state.test.ts +24 -21
  70. package/src/__tests__/conversation-workspace-injection.test.ts +69 -7
  71. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +15 -12
  72. package/src/__tests__/conversations-import-system-filter.test.ts +101 -0
  73. package/src/__tests__/corrected-target.test.ts +93 -0
  74. package/src/__tests__/credential-execution-feature-gates.test.ts +5 -4
  75. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  76. package/src/__tests__/cu-unified-flow.test.ts +36 -0
  77. package/src/__tests__/db-acp-history.test.ts +101 -0
  78. package/src/__tests__/dynamic-page-surface.test.ts +31 -0
  79. package/src/__tests__/embedding-managed-proxy-selection.test.ts +6 -40
  80. package/src/__tests__/empty-response-hook.test.ts +1 -1
  81. package/src/__tests__/file-write-tool.test.ts +63 -0
  82. package/src/__tests__/gateway-only-guard.test.ts +17 -2
  83. package/src/__tests__/guardian-grant-minting.test.ts +1 -1
  84. package/src/__tests__/guardian-routing-invariants.test.ts +93 -4
  85. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
  86. package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
  87. package/src/__tests__/heartbeat-service.test.ts +1 -0
  88. package/src/__tests__/history-repair-hook.test.ts +5 -1
  89. package/src/__tests__/host-app-control-proxy.test.ts +45 -0
  90. package/src/__tests__/host-app-control-routes.test.ts +1 -1
  91. package/src/__tests__/host-cu-routes-targeted.test.ts +3 -3
  92. package/src/__tests__/inference-profile-reaper.test.ts +62 -0
  93. package/src/__tests__/inference-profile-session-handler.test.ts +86 -0
  94. package/src/__tests__/injector-background-turn.test.ts +13 -23
  95. package/src/__tests__/injector-chain.test.ts +268 -44
  96. package/src/__tests__/injector-disk-pressure.test.ts +210 -52
  97. package/src/__tests__/injector-document-comments.test.ts +97 -114
  98. package/src/__tests__/injector-pkb-v2-silenced.test.ts +2 -2
  99. package/src/__tests__/injector-v3-suppression.test.ts +4 -4
  100. package/src/__tests__/list-messages-client-message-id.test.ts +91 -0
  101. package/src/__tests__/list-messages-hidden-metadata.test.ts +38 -0
  102. package/src/__tests__/llm-catalog-parity.test.ts +4 -0
  103. package/src/__tests__/llm-resolver.test.ts +73 -0
  104. package/src/__tests__/memory-retrieval-hook.test.ts +156 -38
  105. package/src/__tests__/memory-v2-static-injector.test.ts +86 -8
  106. package/src/__tests__/notification-decision-strategy.test.ts +3 -3
  107. package/src/__tests__/parallel-tool.benchmark.test.ts +35 -8
  108. package/src/__tests__/persist-unsendable-image-downscale.test.ts +145 -0
  109. package/src/__tests__/persist-unsendable-image.test.ts +97 -1
  110. package/src/__tests__/persistence-secret-redaction.test.ts +78 -0
  111. package/src/__tests__/plugin-api-shim.test.ts +6 -9
  112. package/src/__tests__/plugin-bootstrap.test.ts +91 -81
  113. package/src/__tests__/plugin-registry.test.ts +3 -49
  114. package/src/__tests__/plugin-skill-contribution.test.ts +15 -14
  115. package/src/__tests__/plugin-tool-contribution.test.ts +7 -4
  116. package/src/__tests__/plugin-types.test.ts +0 -70
  117. package/src/__tests__/post-turn-tool-result-truncation.test.ts +69 -0
  118. package/src/__tests__/pre-model-call-sanitize.test.ts +109 -0
  119. package/src/__tests__/published-app-updater.test.ts +138 -0
  120. package/src/__tests__/reaction-persistence.test.ts +1 -1
  121. package/src/__tests__/retry-thinking-adaptive-only.test.ts +245 -0
  122. package/src/__tests__/send-endpoint-busy.test.ts +4 -1
  123. package/src/__tests__/server-history-render.test.ts +39 -0
  124. package/src/__tests__/skill-feature-flags-integration.test.ts +31 -0
  125. package/src/__tests__/steer-tool-repair.test.ts +1 -1
  126. package/src/__tests__/subagent-call-site-routing.test.ts +1 -1
  127. package/src/__tests__/subagent-detail.test.ts +25 -7
  128. package/src/__tests__/subagent-fork-notifications.test.ts +1 -3
  129. package/src/__tests__/subagent-fork-spawn.test.ts +1 -1
  130. package/src/__tests__/subagent-manager-notify.test.ts +1 -3
  131. package/src/__tests__/subagent-notify-parent.test.ts +1 -3
  132. package/src/__tests__/subagent-spawn-tool-fork.test.ts +1 -1
  133. package/src/__tests__/title-generate-hook.test.ts +5 -1
  134. package/src/__tests__/tool-error-hook.test.ts +1 -1
  135. package/src/__tests__/tool-result-truncate-hook.test.ts +1 -1
  136. package/src/__tests__/tool-start-timestamp.test.ts +218 -0
  137. package/src/__tests__/user-plugin-loader.test.ts +54 -286
  138. package/src/__tests__/web-fetch.test.ts +45 -0
  139. package/src/acp/__tests__/agent-process.test.ts +161 -0
  140. package/src/acp/__tests__/client-handler.test.ts +40 -0
  141. package/src/acp/__tests__/helpers/acp-config-stub.ts +0 -2
  142. package/src/acp/__tests__/helpers/acp-history-db.ts +82 -0
  143. package/src/acp/__tests__/helpers/exec-file-stub.ts +106 -0
  144. package/src/acp/__tests__/prepare-agent-env.test.ts +97 -0
  145. package/src/acp/__tests__/session-manager-persistence.test.ts +95 -28
  146. package/src/acp/__tests__/session-manager-resume.test.ts +888 -0
  147. package/src/acp/agent-process.ts +61 -1
  148. package/src/acp/auto-install.test.ts +280 -0
  149. package/src/acp/auto-install.ts +232 -0
  150. package/src/acp/client-handler.ts +31 -0
  151. package/src/acp/prepare-agent-env.ts +80 -27
  152. package/src/acp/resolve-agent.test.ts +188 -28
  153. package/src/acp/resolve-agent.ts +119 -42
  154. package/src/acp/resume-hint.ts +23 -0
  155. package/src/acp/session-manager.ts +507 -73
  156. package/src/agent/compaction-circuit.ts +60 -102
  157. package/src/agent/loop.ts +403 -251
  158. package/src/api/events/tool-result.ts +9 -0
  159. package/src/api/events/tool-use-start.ts +7 -0
  160. package/src/api/responses/conversation-message.ts +72 -13
  161. package/src/api/responses/memory-v3-selection-log.ts +19 -10
  162. package/src/approvals/guardian-request-resolvers.ts +27 -1
  163. package/src/background-wake/next-wake.ts +1 -0
  164. package/src/cli/commands/__tests__/memory-v3.test.ts +191 -210
  165. package/src/cli/commands/channel-verification-sessions.ts +6 -6
  166. package/src/cli/commands/db/__tests__/repair.test.ts +3 -1
  167. package/src/cli/commands/memory-v3.ts +57 -199
  168. package/src/cli/commands/plugins.ts +43 -37
  169. package/src/cli/lib/__tests__/install-from-github.test.ts +790 -111
  170. package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +196 -0
  171. package/src/cli/lib/__tests__/plugin-details.test.ts +381 -0
  172. package/src/cli/lib/__tests__/plugin-marketplace.test.ts +270 -0
  173. package/src/cli/lib/__tests__/search-plugins.test.ts +233 -32
  174. package/src/cli/lib/install-from-github.ts +797 -60
  175. package/src/cli/lib/plugin-catalog-cache.ts +84 -0
  176. package/src/cli/lib/plugin-details.ts +416 -0
  177. package/src/cli/lib/plugin-marketplace.ts +215 -0
  178. package/src/cli/lib/search-plugins.ts +201 -29
  179. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  180. package/src/config/acp-defaults.test.ts +10 -0
  181. package/src/config/acp-defaults.ts +9 -3
  182. package/src/config/acp-schema.ts +1 -7
  183. package/src/config/bundled-skills/acp/SKILL.md +80 -41
  184. package/src/config/bundled-skills/acp/TOOLS.json +4 -4
  185. package/src/config/bundled-skills/app-builder/SKILL.md +224 -381
  186. package/src/config/bundled-skills/app-builder/TOOLS.json +72 -2
  187. package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +48 -0
  188. package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +57 -0
  189. package/src/config/bundled-skills/app-builder/references/SLIDES.md +38 -0
  190. package/src/config/bundled-skills/app-builder/tools/app-list.ts +62 -0
  191. package/src/config/bundled-skills/app-builder/tools/app-update.ts +18 -0
  192. package/src/config/bundled-skills/document-editor/SKILL.md +28 -23
  193. package/src/config/bundled-skills/document-editor/TOOLS.json +1 -1
  194. package/src/config/bundled-tool-registry.ts +4 -0
  195. package/src/config/call-site-defaults.ts +0 -3
  196. package/src/config/feature-flag-registry.json +10 -56
  197. package/src/config/llm-resolver.ts +39 -7
  198. package/src/config/loader.ts +5 -22
  199. package/src/config/schemas/__tests__/memory-v3.test.ts +25 -9
  200. package/src/config/schemas/call-site-catalog.ts +0 -21
  201. package/src/config/schemas/heartbeat.ts +9 -0
  202. package/src/config/schemas/llm.ts +17 -3
  203. package/src/config/schemas/memory-v3.ts +58 -8
  204. package/src/config/seed-inference-profiles.ts +18 -0
  205. package/src/context/compactor.ts +22 -4
  206. package/src/context/post-turn-tool-result-truncation.ts +39 -1
  207. package/src/context/strip-injections.ts +8 -2
  208. package/src/daemon/conversation-agent-loop-handlers.ts +120 -42
  209. package/src/daemon/conversation-agent-loop.ts +308 -1297
  210. package/src/daemon/conversation-error.ts +31 -4
  211. package/src/daemon/conversation-history.ts +1 -1
  212. package/src/daemon/conversation-lifecycle.ts +11 -255
  213. package/src/daemon/conversation-media-retry.ts +19 -6
  214. package/src/daemon/conversation-messaging.ts +17 -0
  215. package/src/daemon/conversation-process.ts +22 -141
  216. package/src/daemon/conversation-queue-manager.ts +8 -0
  217. package/src/daemon/conversation-registry.ts +159 -0
  218. package/src/daemon/conversation-runtime-assembly.ts +361 -393
  219. package/src/daemon/conversation-store.ts +9 -90
  220. package/src/daemon/conversation-surfaces.ts +165 -11
  221. package/src/daemon/conversation-workspace.ts +17 -0
  222. package/src/daemon/conversation.ts +444 -62
  223. package/src/daemon/disk-pressure-policy.ts +0 -1
  224. package/src/daemon/external-plugins-bootstrap.ts +36 -46
  225. package/src/daemon/handlers/config-channels.ts +11 -2
  226. package/src/daemon/handlers/conversations.ts +3 -1
  227. package/src/daemon/handlers/shared.ts +9 -1
  228. package/src/daemon/handlers/skills.ts +4 -1
  229. package/src/daemon/host-app-control-proxy.ts +72 -57
  230. package/src/daemon/host-proxy-preactivation.ts +1 -3
  231. package/src/daemon/lifecycle.ts +21 -7
  232. package/src/daemon/persist-unsendable-image.ts +62 -25
  233. package/src/daemon/process-message.ts +1 -1
  234. package/src/daemon/server.ts +2 -0
  235. package/src/daemon/tool-side-effects.ts +15 -0
  236. package/src/daemon/wake-conversation-ops.ts +269 -0
  237. package/src/embedded/plugin-api.ts +2 -2
  238. package/src/export/__tests__/transcript-formatter.test.ts +5 -0
  239. package/src/heartbeat/__tests__/heartbeat-service.test.ts +3 -0
  240. package/src/heartbeat/heartbeat-run-store.ts +23 -1
  241. package/src/heartbeat/heartbeat-service.ts +26 -0
  242. package/src/ipc/__tests__/browser-ipc.test.ts +1 -1
  243. package/src/ipc/__tests__/ui-request-route.test.ts +3 -3
  244. package/src/ipc/skill-routes/__tests__/memory.test.ts +15 -0
  245. package/src/ipc/skill-routes/memory.ts +4 -2
  246. package/src/memory/__tests__/activation-session-store.test.ts +41 -0
  247. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +87 -0
  248. package/src/memory/__tests__/onboarding-events-store.test.ts +80 -0
  249. package/src/memory/activation-session-store.ts +43 -0
  250. package/src/memory/conversation-crud.ts +29 -19
  251. package/src/memory/conversation-starter-checkpoints.ts +1 -0
  252. package/src/memory/db-init.ts +6 -0
  253. package/src/memory/embedding-backend.ts +5 -22
  254. package/src/memory/job-handlers/conversation-starters.ts +13 -2
  255. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +5 -4
  256. package/src/memory/jobs-worker.ts +25 -1
  257. package/src/memory/migrations/272-acp-session-history-cwd.ts +36 -0
  258. package/src/memory/migrations/273-onboarding-events-funnel-columns.ts +46 -0
  259. package/src/memory/migrations/274-create-activation-sessions.ts +15 -0
  260. package/src/memory/migrations/index.ts +3 -0
  261. package/src/memory/onboarding-events-store.ts +66 -18
  262. package/src/memory/schema/acp.ts +4 -0
  263. package/src/memory/schema/infrastructure.ts +13 -0
  264. package/src/memory/v2/__tests__/consolidation-job.test.ts +4 -97
  265. package/src/memory/v2/__tests__/page-store.test.ts +22 -0
  266. package/src/memory/v2/consolidation-job.ts +2 -63
  267. package/src/memory/v2/types.ts +5 -0
  268. package/src/messaging/providers/telegram-bot/api.ts +14 -5
  269. package/src/notifications/__tests__/copy-composer.test.ts +244 -0
  270. package/src/notifications/access-request-copy.ts +298 -0
  271. package/src/notifications/adapters/slack.ts +3 -3
  272. package/src/notifications/adapters/telegram.ts +9 -2
  273. package/src/notifications/copy-composer.ts +49 -267
  274. package/src/notifications/decision-engine.ts +16 -35
  275. package/src/notifications/home-feed-side-effect.ts +1 -6
  276. package/src/plugin-api/constants.ts +4 -0
  277. package/src/plugin-api/index.ts +40 -11
  278. package/src/plugin-api/types.ts +108 -0
  279. package/src/plugins/defaults/compaction/compact.ts +106 -0
  280. package/src/{daemon → plugins/defaults/compaction}/context-overflow-reducer.ts +250 -42
  281. package/src/plugins/defaults/compaction/corrected-target.ts +53 -0
  282. package/src/plugins/defaults/compaction/manager-store.ts +57 -0
  283. package/src/plugins/defaults/compaction/package.json +1 -2
  284. package/src/{context → plugins/defaults/compaction}/window-manager.ts +95 -25
  285. package/src/plugins/defaults/empty-response/package.json +0 -1
  286. package/src/plugins/defaults/history-repair/package.json +0 -1
  287. package/src/plugins/defaults/index.ts +156 -26
  288. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +100 -52
  289. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +285 -0
  290. package/src/plugins/defaults/memory-retrieval/injector-chain.ts +2 -2
  291. package/src/plugins/defaults/{injectors/register.ts → memory-retrieval/injectors.ts} +148 -73
  292. package/src/plugins/defaults/memory-retrieval/package.json +14 -0
  293. package/src/plugins/defaults/memory-retrieval/unified-turn-context.ts +223 -0
  294. package/src/plugins/defaults/memory-v3-shadow/__tests__/capabilities.test.ts +71 -0
  295. package/src/plugins/defaults/memory-v3-shadow/__tests__/dense.test.ts +181 -0
  296. package/src/plugins/defaults/memory-v3-shadow/__tests__/edge.test.ts +247 -0
  297. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/live-integration.test.ts +147 -134
  298. package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +456 -0
  299. package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +662 -0
  300. package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +306 -0
  301. package/src/plugins/defaults/memory-v3-shadow/__tests__/render-injection.test.ts +91 -0
  302. package/src/plugins/defaults/memory-v3-shadow/__tests__/section-dense-store.test.ts +402 -0
  303. package/src/plugins/defaults/memory-v3-shadow/__tests__/section-needle.test.ts +135 -0
  304. package/src/plugins/defaults/memory-v3-shadow/__tests__/sections.test.ts +125 -0
  305. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/selection-log-store.test.ts +74 -19
  306. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-integration.test.ts +446 -0
  307. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +592 -0
  308. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/types.test.ts +2 -24
  309. package/src/plugins/defaults/memory-v3-shadow/capabilities.ts +91 -0
  310. package/src/plugins/defaults/memory-v3-shadow/dense.ts +97 -0
  311. package/src/plugins/defaults/memory-v3-shadow/edge.ts +252 -0
  312. package/src/plugins/defaults/memory-v3-shadow/hooks/post-compact.ts +14 -0
  313. package/src/plugins/defaults/memory-v3-shadow/hooks/user-prompt-submit.ts +19 -0
  314. package/src/plugins/defaults/memory-v3-shadow/injector.ts +76 -0
  315. package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +555 -0
  316. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +266 -0
  317. package/src/plugins/defaults/memory-v3-shadow/package.json +14 -0
  318. package/src/plugins/defaults/memory-v3-shadow/page-content.ts +71 -0
  319. package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +204 -0
  320. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/render-injection.ts +16 -8
  321. package/src/plugins/defaults/memory-v3-shadow/section-dense-store.ts +236 -0
  322. package/src/plugins/defaults/memory-v3-shadow/section-needle.ts +200 -0
  323. package/src/plugins/defaults/memory-v3-shadow/sections.ts +115 -0
  324. package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +156 -0
  325. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +382 -0
  326. package/src/plugins/defaults/memory-v3-shadow/types.ts +92 -0
  327. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/working-set.ts +4 -1
  328. package/src/plugins/defaults/title-generate/package.json +0 -1
  329. package/src/plugins/defaults/tool-error/package.json +0 -1
  330. package/src/plugins/defaults/tool-result-truncate/package.json +0 -1
  331. package/src/plugins/external-api.ts +12 -2
  332. package/src/plugins/pipeline.ts +6 -293
  333. package/src/plugins/registry.ts +9 -37
  334. package/src/plugins/types.ts +76 -381
  335. package/src/plugins/user-loader.ts +30 -127
  336. package/src/prompts/__tests__/system-prompt.test.ts +6 -0
  337. package/src/prompts/system-prompt.ts +61 -10
  338. package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +71 -4
  339. package/src/providers/anthropic/client.ts +9 -10
  340. package/src/providers/inference/kimi-cjk-token-ids.ts +493 -0
  341. package/src/providers/inference/logit-bias.ts +55 -0
  342. package/src/providers/model-catalog.ts +57 -0
  343. package/src/providers/openai/__tests__/vision-not-supported.test.ts +75 -0
  344. package/src/providers/openai/chat-completions-provider.ts +44 -1
  345. package/src/providers/retry.ts +57 -7
  346. package/src/providers/types.ts +6 -0
  347. package/src/runtime/__tests__/agent-wake.test.ts +555 -691
  348. package/src/runtime/__tests__/interactive-ui.test.ts +1 -1
  349. package/src/runtime/agent-wake.ts +108 -209
  350. package/src/runtime/assistant-event-hub.ts +1 -1
  351. package/src/runtime/channel-approvals.ts +1 -1
  352. package/src/runtime/interactive-ui.ts +1 -1
  353. package/src/runtime/routes/__tests__/acp-routes.test.ts +466 -55
  354. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +1 -1
  355. package/src/runtime/routes/__tests__/plugins-routes.test.ts +423 -73
  356. package/src/runtime/routes/__tests__/stt-routes.test.ts +112 -0
  357. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +5 -4
  358. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +4 -1
  359. package/src/runtime/routes/acp-routes.test.ts +185 -32
  360. package/src/runtime/routes/acp-routes.ts +328 -30
  361. package/src/runtime/routes/app-management-routes.ts +3 -0
  362. package/src/runtime/routes/approval-routes.ts +1 -1
  363. package/src/runtime/routes/browser-routes.ts +1 -1
  364. package/src/runtime/routes/browser-tabs-routes.ts +6 -10
  365. package/src/runtime/routes/channel-verification-routes.ts +14 -5
  366. package/src/runtime/routes/conversation-cli-routes.ts +1 -1
  367. package/src/runtime/routes/conversation-list-routes.ts +1 -1
  368. package/src/runtime/routes/conversation-query-routes.ts +1 -1
  369. package/src/runtime/routes/conversation-routes.ts +30 -2
  370. package/src/runtime/routes/conversation-starter-routes.ts +13 -7
  371. package/src/runtime/routes/conversations-import-routes.ts +24 -7
  372. package/src/runtime/routes/host-app-control-routes.ts +1 -1
  373. package/src/runtime/routes/host-cu-routes.ts +1 -1
  374. package/src/runtime/routes/identity-routes.ts +18 -3
  375. package/src/runtime/routes/inbound-message-handler.ts +1 -1
  376. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +33 -34
  377. package/src/runtime/routes/inference-profile-session-handler.ts +11 -0
  378. package/src/runtime/routes/inference-profile-session-reaper.ts +6 -0
  379. package/src/runtime/routes/memory-v3-routes.ts +65 -305
  380. package/src/runtime/routes/playground/__tests__/force-compact.test.ts +1 -1
  381. package/src/runtime/routes/playground/helpers.ts +1 -1
  382. package/src/runtime/routes/plugins-routes.ts +337 -35
  383. package/src/runtime/routes/stt-routes.ts +45 -12
  384. package/src/runtime/routes/surface-conversation-resolver.ts +4 -3
  385. package/src/runtime/routes/work-items-routes.ts +2 -4
  386. package/src/runtime/routes/workspace-routes.ts +50 -15
  387. package/src/runtime/services/conversation-serializer.ts +1 -1
  388. package/src/runtime/verification-outbound-actions.ts +147 -2
  389. package/src/runtime/verification-templates.ts +29 -3
  390. package/src/services/published-app-updater.ts +30 -8
  391. package/src/signals/cancel.ts +2 -4
  392. package/src/subagent/manager.ts +21 -5
  393. package/src/telemetry/__tests__/activation-funnel.test.ts +95 -0
  394. package/src/telemetry/activation-funnel.ts +167 -0
  395. package/src/telemetry/types.ts +13 -0
  396. package/src/telemetry/usage-telemetry-reporter.test.ts +154 -0
  397. package/src/telemetry/usage-telemetry-reporter.ts +26 -1
  398. package/src/tools/acp/context.ts +20 -0
  399. package/src/tools/acp/list-agents.test.ts +9 -19
  400. package/src/tools/acp/list-agents.ts +3 -15
  401. package/src/tools/acp/spawn.test.ts +173 -202
  402. package/src/tools/acp/spawn.ts +37 -172
  403. package/src/tools/acp/steer.test.ts +105 -8
  404. package/src/tools/acp/steer.ts +48 -17
  405. package/src/tools/apps/executors.ts +166 -50
  406. package/src/tools/browser/browser-execution.ts +12 -2
  407. package/src/tools/filesystem/write.ts +34 -0
  408. package/src/tools/network/web-fetch.ts +65 -24
  409. package/src/tools/skills/load.ts +1 -1
  410. package/src/tools/subagent/spawn.ts +2 -4
  411. package/src/tools/ui-surface/definitions.ts +32 -5
  412. package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +4 -5
  413. package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +69 -45
  414. package/docs/plugins.md +0 -832
  415. package/examples/plugins/echo/register.ts +0 -143
  416. package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -405
  417. package/src/__tests__/compaction-pipeline.test.ts +0 -210
  418. package/src/__tests__/compaction-timeout-recovery.test.ts +0 -251
  419. package/src/__tests__/overflow-reduce-pipeline.test.ts +0 -667
  420. package/src/__tests__/pipeline-runner.test.ts +0 -554
  421. package/src/daemon/wake-target-adapter.ts +0 -253
  422. package/src/memory/v3/__tests__/assign.test.ts +0 -242
  423. package/src/memory/v3/__tests__/capabilities.test.ts +0 -118
  424. package/src/memory/v3/__tests__/core.test.ts +0 -39
  425. package/src/memory/v3/__tests__/health.test.ts +0 -219
  426. package/src/memory/v3/__tests__/maintain-job.test.ts +0 -288
  427. package/src/memory/v3/__tests__/needle.test.ts +0 -107
  428. package/src/memory/v3/__tests__/orchestrate.test.ts +0 -436
  429. package/src/memory/v3/__tests__/provider-blocks.test.ts +0 -13
  430. package/src/memory/v3/__tests__/reconcile.test.ts +0 -274
  431. package/src/memory/v3/__tests__/render-injection.test.ts +0 -61
  432. package/src/memory/v3/__tests__/router.test.ts +0 -332
  433. package/src/memory/v3/__tests__/selector.test.ts +0 -470
  434. package/src/memory/v3/__tests__/shadow-plugin.test.ts +0 -432
  435. package/src/memory/v3/__tests__/snapshot.test.ts +0 -168
  436. package/src/memory/v3/__tests__/tree.test.ts +0 -192
  437. package/src/memory/v3/assign.ts +0 -268
  438. package/src/memory/v3/capabilities.ts +0 -124
  439. package/src/memory/v3/core.ts +0 -26
  440. package/src/memory/v3/health.ts +0 -0
  441. package/src/memory/v3/maintain-job.ts +0 -314
  442. package/src/memory/v3/needle.ts +0 -115
  443. package/src/memory/v3/orchestrate.ts +0 -126
  444. package/src/memory/v3/page-content.ts +0 -34
  445. package/src/memory/v3/provider-blocks.ts +0 -26
  446. package/src/memory/v3/reconcile.ts +0 -523
  447. package/src/memory/v3/router.ts +0 -190
  448. package/src/memory/v3/selection-log-store.ts +0 -84
  449. package/src/memory/v3/selector.ts +0 -226
  450. package/src/memory/v3/shadow-plugin.ts +0 -411
  451. package/src/memory/v3/snapshot.ts +0 -209
  452. package/src/memory/v3/tree.ts +0 -174
  453. package/src/memory/v3/types.ts +0 -59
  454. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +0 -187
  455. package/src/plugins/defaults/circuit-breaker/middlewares/circuitBreaker.ts +0 -93
  456. package/src/plugins/defaults/circuit-breaker/package.json +0 -15
  457. package/src/plugins/defaults/circuit-breaker/register.ts +0 -39
  458. package/src/plugins/defaults/compaction/middlewares/compaction.ts +0 -25
  459. package/src/plugins/defaults/compaction/register.ts +0 -35
  460. package/src/plugins/defaults/compaction/terminal.ts +0 -73
  461. package/src/plugins/defaults/empty-response/register.ts +0 -23
  462. package/src/plugins/defaults/history-repair/register.ts +0 -24
  463. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit-temp.ts +0 -216
  464. package/src/plugins/defaults/overflow-reduce/middlewares/overflowReduce.ts +0 -126
  465. package/src/plugins/defaults/overflow-reduce/package.json +0 -15
  466. package/src/plugins/defaults/overflow-reduce/register.ts +0 -42
  467. package/src/plugins/defaults/title-generate/register.ts +0 -35
  468. package/src/plugins/defaults/tool-error/register.ts +0 -23
  469. package/src/plugins/defaults/tool-result-truncate/register.ts +0 -24
  470. package/src/proactive-artifact/aux-message-injector.ts +0 -97
  471. package/src/proactive-artifact/decision.test.ts +0 -226
  472. package/src/proactive-artifact/decision.ts +0 -165
  473. package/src/proactive-artifact/index.ts +0 -7
  474. package/src/proactive-artifact/job.test.ts +0 -962
  475. package/src/proactive-artifact/job.ts +0 -372
  476. package/src/proactive-artifact/message-copy.ts +0 -58
  477. package/src/proactive-artifact/trigger-state.test.ts +0 -286
  478. package/src/proactive-artifact/trigger-state.ts +0 -123
  479. package/src/util/map-limit.ts +0 -27
  480. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/eval-turns.json +0 -0
  481. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/live-turns.json +0 -0
  482. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-eviction.test.ts +0 -0
  483. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-skeleton.test.ts +0 -0
  484. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/README.md +0 -0
  485. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/assignments.json +0 -0
  486. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/core.json +0 -0
  487. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-x.md +0 -0
  488. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-y.md +0 -0
  489. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-b/topic-z.md +0 -0
  490. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/llm-retry.ts +0 -0
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Shared test helpers for the `acp_session_history` table.
3
+ *
4
+ * Several suites (session-manager resume/persistence, the ACP route
5
+ * handlers) seed and read history rows directly via SQL; this module
6
+ * consolidates the copy-pasted row shape + insert/read/clear helpers.
7
+ * Tests must run `initializeDb()` themselves before calling these.
8
+ */
9
+
10
+ import { getSqlite } from "../../../memory/db-connection.js";
11
+
12
+ /** Raw column snapshot of an `acp_session_history` row. */
13
+ export interface HistoryRow {
14
+ id: string;
15
+ agent_id: string;
16
+ acp_session_id: string;
17
+ parent_conversation_id: string;
18
+ started_at: number;
19
+ completed_at: number | null;
20
+ status: string;
21
+ stop_reason: string | null;
22
+ error: string | null;
23
+ event_log_json: string;
24
+ cwd: string | null;
25
+ }
26
+
27
+ export function clearHistory(): void {
28
+ getSqlite().run("DELETE FROM acp_session_history");
29
+ }
30
+
31
+ /**
32
+ * Inserts a history row. Every field except `id` defaults to the values
33
+ * the resume suites were built around (a completed claude run in
34
+ * /tmp/proj); pass explicit values to override, including `null` where the
35
+ * column is nullable (e.g. `cwd: null` for legacy rows).
36
+ */
37
+ export function insertHistoryRow(row: {
38
+ id: string;
39
+ agentId?: string;
40
+ acpSessionId?: string;
41
+ parentConversationId?: string;
42
+ startedAt?: number;
43
+ completedAt?: number | null;
44
+ status?: string;
45
+ stopReason?: string | null;
46
+ error?: string | null;
47
+ eventLogJson?: string;
48
+ cwd?: string | null;
49
+ }): void {
50
+ getSqlite()
51
+ .query(
52
+ `INSERT INTO acp_session_history (
53
+ id, agent_id, acp_session_id, parent_conversation_id,
54
+ started_at, completed_at, status, stop_reason, error,
55
+ event_log_json, cwd
56
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
57
+ )
58
+ .run(
59
+ row.id,
60
+ row.agentId ?? "claude",
61
+ row.acpSessionId ?? "proto-old",
62
+ row.parentConversationId ?? "conv-1",
63
+ row.startedAt ?? 1234,
64
+ row.completedAt === undefined ? 5678 : row.completedAt,
65
+ row.status ?? "completed",
66
+ row.stopReason === undefined ? "end_turn" : row.stopReason,
67
+ row.error ?? null,
68
+ row.eventLogJson ?? "[]",
69
+ row.cwd === undefined ? "/tmp/proj" : row.cwd,
70
+ );
71
+ }
72
+
73
+ export function readHistoryRow(id: string): HistoryRow | null {
74
+ return getSqlite()
75
+ .query(
76
+ `SELECT id, agent_id, acp_session_id, parent_conversation_id,
77
+ started_at, completed_at, status, stop_reason, error,
78
+ event_log_json, cwd
79
+ FROM acp_session_history WHERE id = ?`,
80
+ )
81
+ .get(id) as HistoryRow | null;
82
+ }
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Shared test helper: stub `execFile` from `node:child_process` for ACP tests.
3
+ *
4
+ * Several ACP suites (the adapter auto-installer and the `/v1/acp/spawn`
5
+ * route) shell out via `execFileWithTimeout` (e.g. `bun add --global`). Each
6
+ * test file used to duplicate the same `mock.module("node:child_process",
7
+ * ...)` + scripted-responses boilerplate; this helper consolidates it,
8
+ * mirroring `which-stub.ts`.
9
+ *
10
+ * The mock records every call's args, INCLUDING the options object (cwd, env,
11
+ * ...) at `execFileMock.mock.calls[i][2]`, so tests can assert the installer's
12
+ * sandboxed cwd and sanitized env.
13
+ *
14
+ * Like the other helpers here, the hook is process-global by design (Bun's
15
+ * `mock.module` is process-global). Each test file should call
16
+ * `installExecFileStub()` once at the top level, script calls per test via
17
+ * `execScripts`, and clear state in `beforeEach` via `reset()`.
18
+ */
19
+
20
+ import * as realChildProcess from "node:child_process";
21
+ import { mock } from "bun:test";
22
+
23
+ type ExecCallback = (
24
+ err: Error | null,
25
+ stdout: string | Buffer,
26
+ stderr: string | Buffer,
27
+ ) => void;
28
+
29
+ export interface ExecScript {
30
+ /** When set, the call rejects with this error. */
31
+ error?: Error;
32
+ /** When set, the call resolves with this stdout. */
33
+ stdout?: string;
34
+ /** When set, runs as the call executes (e.g. flip a which-stub flag). */
35
+ onCall?: () => void;
36
+ }
37
+
38
+ type ExecFileMock = ReturnType<
39
+ typeof mock<
40
+ (
41
+ command: string,
42
+ args: string[],
43
+ options: unknown,
44
+ callback?: ExecCallback,
45
+ ) => ReturnType<typeof realChildProcess.execFile>
46
+ >
47
+ >;
48
+
49
+ export interface ExecFileStubHandle {
50
+ /**
51
+ * Per-call scripted responses, keyed by `${command} ${args[0]}` so tests
52
+ * can target distinct subcommands (e.g. `<bunPath> add`) independently.
53
+ * Calls with no script reject with a recognizable "No script for <key>"
54
+ * error.
55
+ */
56
+ execScripts: Map<string, ExecScript>;
57
+ execFileMock: ExecFileMock;
58
+ /** Clears scripts and recorded calls. Call from `beforeEach`. */
59
+ reset(): void;
60
+ }
61
+
62
+ /** Installs a process-global `execFile` mock. Returns handles to drive it. */
63
+ export function installExecFileStub(): ExecFileStubHandle {
64
+ const execScripts: Map<string, ExecScript> = new Map();
65
+
66
+ const execFileMock: ExecFileMock = mock(
67
+ (
68
+ command: string,
69
+ args: string[],
70
+ _options: unknown,
71
+ callback?: ExecCallback,
72
+ ) => {
73
+ const key = `${command} ${args[0]}`;
74
+ const script = execScripts.get(key);
75
+ queueMicrotask(() => {
76
+ if (!callback) return;
77
+ if (!script) {
78
+ callback(new Error(`No script for ${key}`), "", "");
79
+ return;
80
+ }
81
+ script.onCall?.();
82
+ if (script.error) {
83
+ callback(script.error, "", "");
84
+ return;
85
+ }
86
+ callback(null, script.stdout ?? "", "");
87
+ });
88
+ // Return value is not used by execFileWithTimeout.
89
+ return {} as ReturnType<typeof realChildProcess.execFile>;
90
+ },
91
+ );
92
+
93
+ mock.module("node:child_process", () => ({
94
+ ...realChildProcess,
95
+ execFile: execFileMock,
96
+ }));
97
+
98
+ return {
99
+ execScripts,
100
+ execFileMock,
101
+ reset(): void {
102
+ execScripts.clear();
103
+ execFileMock.mockClear();
104
+ },
105
+ };
106
+ }
@@ -234,6 +234,103 @@ describe("prepareAgentEnv — claude-agent-acp gating", () => {
234
234
  });
235
235
  });
236
236
 
237
+ describe("prepareAgentEnv - gemini gating", () => {
238
+ function seedVaultGeminiKey(key: string): void {
239
+ vaultStore.set("acp/gemini_api_key", key);
240
+ }
241
+
242
+ test("injects GEMINI_API_KEY from the vault via the broker when agent.env has no override", async () => {
243
+ seedVaultGeminiKey("vault-gem-AAA");
244
+
245
+ const prepared = await prepareAgentEnv({
246
+ command: "gemini",
247
+ args: ["--acp"],
248
+ });
249
+
250
+ expect(prepared.env?.GEMINI_API_KEY).toBe("vault-gem-AAA");
251
+ });
252
+
253
+ test("auto-registers metadata with acp_spawn in allowedTools when none exists", async () => {
254
+ seedVaultGeminiKey("vault-gem-auto-meta");
255
+
256
+ await prepareAgentEnv({ command: "gemini", args: ["--acp"] });
257
+
258
+ const meta = metadataStore.get("acp/gemini_api_key");
259
+ expect(meta).toBeDefined();
260
+ expect(meta!.allowedTools).toContain("acp_spawn");
261
+ });
262
+
263
+ test("a vault miss does NOT throw and spawns without GEMINI_API_KEY (key is optional)", async () => {
264
+ const prepared = await prepareAgentEnv({
265
+ command: "gemini",
266
+ args: ["--acp"],
267
+ });
268
+
269
+ expect(prepared.env).not.toHaveProperty("GEMINI_API_KEY");
270
+ });
271
+
272
+ test("respects explicit tool policy that excludes acp_spawn without failing the spawn", async () => {
273
+ metadataStore.set("acp/gemini_api_key", {
274
+ allowedTools: ["other_tool"],
275
+ });
276
+ seedVaultGeminiKey("vault-gem-restricted");
277
+
278
+ const prepared = await prepareAgentEnv({
279
+ command: "gemini",
280
+ args: ["--acp"],
281
+ });
282
+
283
+ expect(prepared.env).not.toHaveProperty("GEMINI_API_KEY");
284
+ const meta = metadataStore.get("acp/gemini_api_key");
285
+ expect(meta!.allowedTools).toEqual(["other_tool"]);
286
+ });
287
+
288
+ test("agent.env override wins over the vault entry and skips the broker (precedence pin)", async () => {
289
+ // Seed a vault value but no metadata: if the override path consulted the
290
+ // broker anyway, ensureAcpCredentialPolicy would create metadata here.
291
+ seedVaultGeminiKey("vault-gem-CCC");
292
+
293
+ const prepared = await prepareAgentEnv({
294
+ command: "gemini",
295
+ args: ["--acp"],
296
+ env: { GEMINI_API_KEY: "config-gem-DDD" },
297
+ });
298
+
299
+ expect(prepared.env?.GEMINI_API_KEY).toBe("config-gem-DDD");
300
+ expect(metadataStore.has("acp/gemini_api_key")).toBe(false);
301
+ });
302
+
303
+ test("preserves unrelated env vars on agent.env when injecting from the vault", async () => {
304
+ seedVaultGeminiKey("vault-gem-EEE");
305
+
306
+ const prepared = await prepareAgentEnv({
307
+ command: "gemini",
308
+ args: ["--acp"],
309
+ env: { NO_COLOR: "1" },
310
+ });
311
+
312
+ expect(prepared.env?.GEMINI_API_KEY).toBe("vault-gem-EEE");
313
+ expect(prepared.env?.NO_COLOR).toBe("1");
314
+ });
315
+
316
+ test("does NOT mutate the caller's agentConfig", async () => {
317
+ seedVaultGeminiKey("vault-gem-GGG");
318
+ const original = {
319
+ command: "gemini",
320
+ args: ["--acp"],
321
+ env: { OTHER: "keep" },
322
+ };
323
+ const beforeEnv = { ...original.env };
324
+
325
+ const prepared = await prepareAgentEnv(original);
326
+
327
+ expect(prepared).not.toBe(original);
328
+ expect(prepared.env).not.toBe(original.env);
329
+ expect(original.env).toEqual(beforeEnv);
330
+ expect(original.env).not.toHaveProperty("GEMINI_API_KEY");
331
+ });
332
+ });
333
+
237
334
  describe("prepareAgentEnv — non-claude commands", () => {
238
335
  test("returns the config unchanged for codex-acp (no required env vars today)", async () => {
239
336
  const prepared = await prepareAgentEnv({
@@ -23,35 +23,13 @@ import type { ServerMessage } from "../../daemon/message-protocol.js";
23
23
  import type { AcpSessionUpdate } from "../../daemon/message-types/acp.js";
24
24
  import { getSqlite } from "../../memory/db-connection.js";
25
25
  import { initializeDb } from "../../memory/db-init.js";
26
+ import {
27
+ clearHistory,
28
+ insertHistoryRow,
29
+ readHistoryRow,
30
+ } from "./helpers/acp-history-db.js";
26
31
  initializeDb();
27
32
 
28
- function clearHistory() {
29
- getSqlite().run("DELETE FROM acp_session_history");
30
- }
31
-
32
- interface HistoryRow {
33
- id: string;
34
- agent_id: string;
35
- acp_session_id: string;
36
- parent_conversation_id: string;
37
- started_at: number;
38
- completed_at: number | null;
39
- status: string;
40
- stop_reason: string | null;
41
- error: string | null;
42
- event_log_json: string;
43
- }
44
-
45
- function readHistoryRow(id: string): HistoryRow | null {
46
- return getSqlite()
47
- .query(
48
- `SELECT id, agent_id, acp_session_id, parent_conversation_id,
49
- started_at, completed_at, status, stop_reason, error, event_log_json
50
- FROM acp_session_history WHERE id = ?`,
51
- )
52
- .get(id) as HistoryRow | null;
53
- }
54
-
55
33
  /**
56
34
  * Builds a manager with a fake session pre-injected and returns the handles
57
35
  * needed to drive terminal transitions in tests.
@@ -61,6 +39,7 @@ function buildSessionWithFakeProcess(opts: {
61
39
  agentId: string;
62
40
  protocolSessionId: string;
63
41
  parentConversationId: string;
42
+ cwd?: string;
64
43
  }): {
65
44
  manager: AcpSessionManager;
66
45
  resolvePrompt: (v: { stopReason: string }) => void;
@@ -126,7 +105,7 @@ function buildSessionWithFakeProcess(opts: {
126
105
  sendToVellum: wrappedSend,
127
106
  currentPrompt: null as Promise<unknown> | null,
128
107
  parentConversationId: opts.parentConversationId,
129
- cwd: "/tmp",
108
+ cwd: opts.cwd ?? "/tmp",
130
109
  command: "claude-agent-acp",
131
110
  };
132
111
  sessions.set(opts.id, entry);
@@ -345,6 +324,94 @@ describe("AcpSessionManager — terminal persistence", () => {
345
324
  expect(row!.event_log_json.length).toBeLessThan(256 * 1024 + 1024);
346
325
  });
347
326
 
327
+ test("persists the spawn cwd on terminal transition", async () => {
328
+ const id = "session-cwd-1";
329
+ const handles = buildSessionWithFakeProcess({
330
+ id,
331
+ agentId: "agent-cwd",
332
+ protocolSessionId: "proto-cwd",
333
+ parentConversationId: "conv-cwd",
334
+ cwd: "/Users/me/projects/widget",
335
+ });
336
+
337
+ handles.resolvePrompt({ stopReason: "end_turn" });
338
+ await Promise.resolve();
339
+ await Promise.resolve();
340
+
341
+ const row = readHistoryRow(id);
342
+ expect(row).not.toBeNull();
343
+ expect(row!.cwd).toBe("/Users/me/projects/widget");
344
+ });
345
+
346
+ test("legacy rows without a cwd read back as null", () => {
347
+ insertHistoryRow({
348
+ id: "legacy-row-1",
349
+ agentId: "agent-legacy",
350
+ acpSessionId: "proto-legacy",
351
+ parentConversationId: "conv-legacy",
352
+ startedAt: 1000,
353
+ completedAt: null,
354
+ status: "completed",
355
+ stopReason: null,
356
+ cwd: null,
357
+ });
358
+
359
+ const row = readHistoryRow("legacy-row-1");
360
+ expect(row).not.toBeNull();
361
+ expect(row!.cwd).toBeNull();
362
+ });
363
+
364
+ test("upserts over a pre-existing row with the same id (resumed runs)", async () => {
365
+ const id = "session-upsert-1";
366
+ // Simulate the row left behind by the original run that a resumed run
367
+ // reuses the id of.
368
+ insertHistoryRow({
369
+ id,
370
+ agentId: "agent-up",
371
+ acpSessionId: "proto-up",
372
+ parentConversationId: "conv-up",
373
+ startedAt: 1000,
374
+ completedAt: 2000,
375
+ status: "cancelled",
376
+ stopReason: "daemon_restarted",
377
+ eventLogJson: '[{"old":true}]',
378
+ cwd: "/old/cwd",
379
+ });
380
+
381
+ const handles = buildSessionWithFakeProcess({
382
+ id,
383
+ agentId: "agent-up",
384
+ protocolSessionId: "proto-up",
385
+ parentConversationId: "conv-up",
386
+ cwd: "/new/cwd",
387
+ });
388
+
389
+ handles.emitUpdate({
390
+ type: "acp_session_update",
391
+ acpSessionId: id,
392
+ updateType: "agent_message_chunk",
393
+ content: "from the resumed run",
394
+ });
395
+
396
+ handles.resolvePrompt({ stopReason: "end_turn" });
397
+ await Promise.resolve();
398
+ await Promise.resolve();
399
+
400
+ const count = getSqlite()
401
+ .query(`SELECT COUNT(*) AS n FROM acp_session_history WHERE id = ?`)
402
+ .get(id) as { n: number };
403
+ expect(count.n).toBe(1);
404
+
405
+ const row = readHistoryRow(id);
406
+ expect(row).not.toBeNull();
407
+ expect(row!.status).toBe("completed");
408
+ expect(row!.stop_reason).toBe("end_turn");
409
+ expect(row!.cwd).toBe("/new/cwd");
410
+ const log = JSON.parse(row!.event_log_json) as AcpSessionUpdate[];
411
+ expect(log).toHaveLength(1);
412
+ expect(log[0]).toMatchObject({ content: "from the resumed run" });
413
+ });
414
+
348
415
  test("persists empty event log when no updates were emitted", async () => {
349
416
  const id = "session-empty-1";
350
417
  const handles = buildSessionWithFakeProcess({