@vellumai/assistant 0.8.8 → 0.8.9-dev.202606091853.fbaa2ae

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 (475) 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 +263 -121
  12. package/package.json +2 -2
  13. package/src/__tests__/activation-early-marking.test.ts +120 -0
  14. package/src/__tests__/agent-loop-callsite-precedence.test.ts +69 -14
  15. package/src/__tests__/agent-loop-exit-reason.test.ts +204 -144
  16. package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +50 -35
  17. package/src/__tests__/agent-loop-output-hooks.test.ts +357 -0
  18. package/src/__tests__/agent-loop-override-profile.test.ts +25 -6
  19. package/src/__tests__/agent-loop-provider-error-recording.test.ts +41 -21
  20. package/src/__tests__/agent-loop-thinking.test.ts +36 -20
  21. package/src/__tests__/agent-loop.test.ts +441 -96
  22. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +14 -14
  23. package/src/__tests__/agent-wake-override-profile.test.ts +17 -21
  24. package/src/__tests__/anthropic-provider.test.ts +23 -8
  25. package/src/__tests__/app-builder-tool-scripts.test.ts +21 -0
  26. package/src/__tests__/app-control-flow.test.ts +1 -1
  27. package/src/__tests__/app-dir-path-guard.test.ts +1 -0
  28. package/src/__tests__/app-executors.test.ts +132 -0
  29. package/src/__tests__/approval-cascade.test.ts +6 -5
  30. package/src/__tests__/approval-routes-http.test.ts +4 -1
  31. package/src/__tests__/background-workers-disk-pressure.test.ts +1 -1
  32. package/src/__tests__/channel-approval-routes.test.ts +1 -1
  33. package/src/__tests__/channel-approvals.test.ts +1 -1
  34. package/src/__tests__/compaction-circuit.test.ts +258 -0
  35. package/src/__tests__/compaction-direct.test.ts +146 -0
  36. package/src/__tests__/compaction-events.test.ts +7 -7
  37. package/src/__tests__/compaction.benchmark.test.ts +1 -1
  38. package/src/__tests__/compactor-web-search-strip.test.ts +213 -0
  39. package/src/__tests__/context-overflow-reducer.test.ts +265 -125
  40. package/src/__tests__/context-window-manager-compact-retry.test.ts +121 -15
  41. package/src/__tests__/conversation-abort-tool-results.test.ts +7 -5
  42. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +7 -10
  43. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +78 -119
  44. package/src/__tests__/conversation-agent-loop-overflow.test.ts +158 -234
  45. package/src/__tests__/conversation-agent-loop.test.ts +342 -623
  46. package/src/__tests__/conversation-clean-command.test.ts +5 -2
  47. package/src/__tests__/conversation-confirmation-signals.test.ts +6 -5
  48. package/src/__tests__/conversation-crud-inference-profile.test.ts +7 -9
  49. package/src/__tests__/conversation-error.test.ts +15 -1
  50. package/src/__tests__/conversation-history-web-search.test.ts +6 -1
  51. package/src/__tests__/conversation-media-retry.test.ts +1 -1
  52. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +44 -4
  53. package/src/__tests__/conversation-process-callsite.test.ts +15 -15
  54. package/src/__tests__/conversation-provider-retry-repair.test.ts +66 -65
  55. package/src/__tests__/conversation-queue.test.ts +10 -10
  56. package/src/__tests__/conversation-runtime-assembly.test.ts +1059 -231
  57. package/src/__tests__/conversation-runtime-workspace.test.ts +115 -20
  58. package/src/__tests__/conversation-slash-queue.test.ts +7 -5
  59. package/src/__tests__/conversation-slash-unknown.test.ts +7 -5
  60. package/src/__tests__/conversation-speed-override.test.ts +11 -10
  61. package/src/__tests__/conversation-starter-routes.test.ts +14 -6
  62. package/src/__tests__/conversation-surfaces-activation-emit.test.ts +395 -0
  63. package/src/__tests__/conversation-surfaces-app-control.test.ts +48 -1
  64. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +73 -4
  65. package/src/__tests__/conversation-undo.test.ts +2 -2
  66. package/src/__tests__/conversation-workspace-cache-state.test.ts +24 -21
  67. package/src/__tests__/conversation-workspace-injection.test.ts +69 -7
  68. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +15 -12
  69. package/src/__tests__/conversations-import-system-filter.test.ts +101 -0
  70. package/src/__tests__/corrected-target.test.ts +93 -0
  71. package/src/__tests__/credential-security-invariants.test.ts +1 -0
  72. package/src/__tests__/cu-unified-flow.test.ts +36 -0
  73. package/src/__tests__/db-acp-history.test.ts +101 -0
  74. package/src/__tests__/dynamic-page-surface.test.ts +31 -0
  75. package/src/__tests__/empty-response-hook.test.ts +1 -1
  76. package/src/__tests__/file-write-tool.test.ts +63 -0
  77. package/src/__tests__/gateway-only-guard.test.ts +17 -2
  78. package/src/__tests__/guardian-grant-minting.test.ts +1 -1
  79. package/src/__tests__/guardian-routing-invariants.test.ts +93 -4
  80. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
  81. package/src/__tests__/heartbeat-disk-pressure.test.ts +1 -0
  82. package/src/__tests__/heartbeat-service.test.ts +1 -0
  83. package/src/__tests__/history-repair-hook.test.ts +5 -1
  84. package/src/__tests__/host-app-control-proxy.test.ts +45 -0
  85. package/src/__tests__/host-app-control-routes.test.ts +1 -1
  86. package/src/__tests__/host-cu-routes-targeted.test.ts +3 -3
  87. package/src/__tests__/inference-profile-reaper.test.ts +62 -0
  88. package/src/__tests__/inference-profile-session-handler.test.ts +86 -0
  89. package/src/__tests__/injector-background-turn.test.ts +13 -23
  90. package/src/__tests__/injector-chain.test.ts +268 -44
  91. package/src/__tests__/injector-disk-pressure.test.ts +210 -52
  92. package/src/__tests__/injector-document-comments.test.ts +97 -114
  93. package/src/__tests__/injector-pkb-v2-silenced.test.ts +2 -2
  94. package/src/__tests__/injector-v3-suppression.test.ts +4 -4
  95. package/src/__tests__/list-messages-client-message-id.test.ts +91 -0
  96. package/src/__tests__/list-messages-hidden-metadata.test.ts +38 -0
  97. package/src/__tests__/llm-resolver.test.ts +73 -0
  98. package/src/__tests__/memory-retrieval-hook.test.ts +156 -38
  99. package/src/__tests__/memory-v2-static-injector.test.ts +86 -8
  100. package/src/__tests__/notification-decision-strategy.test.ts +3 -3
  101. package/src/__tests__/parallel-tool.benchmark.test.ts +35 -8
  102. package/src/__tests__/persist-unsendable-image-downscale.test.ts +145 -0
  103. package/src/__tests__/persist-unsendable-image.test.ts +97 -1
  104. package/src/__tests__/plugin-api-shim.test.ts +6 -9
  105. package/src/__tests__/plugin-bootstrap.test.ts +91 -81
  106. package/src/__tests__/plugin-registry.test.ts +3 -49
  107. package/src/__tests__/plugin-skill-contribution.test.ts +15 -14
  108. package/src/__tests__/plugin-tool-contribution.test.ts +7 -4
  109. package/src/__tests__/plugin-types.test.ts +0 -70
  110. package/src/__tests__/post-turn-tool-result-truncation.test.ts +69 -0
  111. package/src/__tests__/pre-model-call-sanitize.test.ts +109 -0
  112. package/src/__tests__/published-app-updater.test.ts +138 -0
  113. package/src/__tests__/reaction-persistence.test.ts +1 -1
  114. package/src/__tests__/send-endpoint-busy.test.ts +4 -1
  115. package/src/__tests__/skill-feature-flags-integration.test.ts +31 -0
  116. package/src/__tests__/steer-tool-repair.test.ts +1 -1
  117. package/src/__tests__/subagent-call-site-routing.test.ts +1 -1
  118. package/src/__tests__/subagent-detail.test.ts +25 -7
  119. package/src/__tests__/subagent-fork-notifications.test.ts +1 -3
  120. package/src/__tests__/subagent-fork-spawn.test.ts +1 -1
  121. package/src/__tests__/subagent-manager-notify.test.ts +1 -3
  122. package/src/__tests__/subagent-notify-parent.test.ts +1 -3
  123. package/src/__tests__/subagent-spawn-tool-fork.test.ts +1 -1
  124. package/src/__tests__/title-generate-hook.test.ts +5 -1
  125. package/src/__tests__/tool-error-hook.test.ts +1 -1
  126. package/src/__tests__/tool-result-truncate-hook.test.ts +1 -1
  127. package/src/__tests__/user-plugin-loader.test.ts +54 -286
  128. package/src/__tests__/web-fetch.test.ts +45 -0
  129. package/src/acp/__tests__/agent-process.test.ts +161 -0
  130. package/src/acp/__tests__/client-handler.test.ts +40 -0
  131. package/src/acp/__tests__/helpers/acp-config-stub.ts +0 -2
  132. package/src/acp/__tests__/helpers/acp-history-db.ts +82 -0
  133. package/src/acp/__tests__/helpers/exec-file-stub.ts +106 -0
  134. package/src/acp/__tests__/prepare-agent-env.test.ts +97 -0
  135. package/src/acp/__tests__/session-manager-persistence.test.ts +95 -28
  136. package/src/acp/__tests__/session-manager-resume.test.ts +888 -0
  137. package/src/acp/agent-process.ts +61 -1
  138. package/src/acp/auto-install.test.ts +280 -0
  139. package/src/acp/auto-install.ts +232 -0
  140. package/src/acp/client-handler.ts +31 -0
  141. package/src/acp/prepare-agent-env.ts +80 -27
  142. package/src/acp/resolve-agent.test.ts +188 -28
  143. package/src/acp/resolve-agent.ts +119 -42
  144. package/src/acp/resume-hint.ts +23 -0
  145. package/src/acp/session-manager.ts +507 -73
  146. package/src/agent/compaction-circuit.ts +60 -102
  147. package/src/agent/loop.ts +403 -251
  148. package/src/api/responses/conversation-message.ts +22 -2
  149. package/src/api/responses/memory-v3-selection-log.ts +19 -10
  150. package/src/approvals/guardian-request-resolvers.ts +27 -1
  151. package/src/background-wake/next-wake.ts +1 -0
  152. package/src/cli/commands/__tests__/memory-v3.test.ts +191 -210
  153. package/src/cli/commands/channel-verification-sessions.ts +6 -6
  154. package/src/cli/commands/db/__tests__/repair.test.ts +3 -1
  155. package/src/cli/commands/memory-v3.ts +57 -199
  156. package/src/cli/commands/plugins.ts +43 -37
  157. package/src/cli/lib/__tests__/install-from-github.test.ts +790 -111
  158. package/src/cli/lib/__tests__/plugin-catalog-cache.test.ts +196 -0
  159. package/src/cli/lib/__tests__/plugin-details.test.ts +381 -0
  160. package/src/cli/lib/__tests__/plugin-marketplace.test.ts +270 -0
  161. package/src/cli/lib/__tests__/search-plugins.test.ts +233 -32
  162. package/src/cli/lib/install-from-github.ts +797 -60
  163. package/src/cli/lib/plugin-catalog-cache.ts +84 -0
  164. package/src/cli/lib/plugin-details.ts +416 -0
  165. package/src/cli/lib/plugin-marketplace.ts +215 -0
  166. package/src/cli/lib/search-plugins.ts +201 -29
  167. package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
  168. package/src/config/acp-defaults.test.ts +10 -0
  169. package/src/config/acp-defaults.ts +9 -3
  170. package/src/config/acp-schema.ts +1 -7
  171. package/src/config/bundled-skills/acp/SKILL.md +80 -41
  172. package/src/config/bundled-skills/acp/TOOLS.json +4 -4
  173. package/src/config/bundled-skills/app-builder/SKILL.md +224 -381
  174. package/src/config/bundled-skills/app-builder/TOOLS.json +72 -2
  175. package/src/config/bundled-skills/app-builder/references/DESIGN_SYSTEM.md +48 -0
  176. package/src/config/bundled-skills/app-builder/references/RESPONSIVE.md +57 -0
  177. package/src/config/bundled-skills/app-builder/references/SLIDES.md +38 -0
  178. package/src/config/bundled-skills/app-builder/tools/app-list.ts +62 -0
  179. package/src/config/bundled-skills/app-builder/tools/app-update.ts +18 -0
  180. package/src/config/bundled-skills/document-editor/SKILL.md +28 -23
  181. package/src/config/bundled-skills/document-editor/TOOLS.json +1 -1
  182. package/src/config/bundled-tool-registry.ts +4 -0
  183. package/src/config/call-site-defaults.ts +0 -3
  184. package/src/config/feature-flag-registry.json +10 -16
  185. package/src/config/llm-resolver.ts +39 -7
  186. package/src/config/schemas/__tests__/memory-v3.test.ts +25 -9
  187. package/src/config/schemas/call-site-catalog.ts +0 -21
  188. package/src/config/schemas/heartbeat.ts +9 -0
  189. package/src/config/schemas/llm.ts +17 -3
  190. package/src/config/schemas/memory-v3.ts +58 -8
  191. package/src/config/seed-inference-profiles.ts +18 -0
  192. package/src/context/compactor.ts +22 -4
  193. package/src/context/post-turn-tool-result-truncation.ts +39 -1
  194. package/src/context/strip-injections.ts +8 -2
  195. package/src/daemon/conversation-agent-loop-handlers.ts +18 -36
  196. package/src/daemon/conversation-agent-loop.ts +308 -1297
  197. package/src/daemon/conversation-error.ts +31 -4
  198. package/src/daemon/conversation-history.ts +1 -1
  199. package/src/daemon/conversation-lifecycle.ts +11 -255
  200. package/src/daemon/conversation-media-retry.ts +19 -6
  201. package/src/daemon/conversation-messaging.ts +17 -0
  202. package/src/daemon/conversation-process.ts +22 -141
  203. package/src/daemon/conversation-queue-manager.ts +8 -0
  204. package/src/daemon/conversation-registry.ts +159 -0
  205. package/src/daemon/conversation-runtime-assembly.ts +361 -393
  206. package/src/daemon/conversation-store.ts +9 -90
  207. package/src/daemon/conversation-surfaces.ts +165 -11
  208. package/src/daemon/conversation-workspace.ts +17 -0
  209. package/src/daemon/conversation.ts +444 -62
  210. package/src/daemon/disk-pressure-policy.ts +0 -1
  211. package/src/daemon/external-plugins-bootstrap.ts +36 -46
  212. package/src/daemon/handlers/config-channels.ts +11 -2
  213. package/src/daemon/handlers/conversations.ts +3 -1
  214. package/src/daemon/handlers/skills.ts +4 -1
  215. package/src/daemon/host-app-control-proxy.ts +72 -57
  216. package/src/daemon/host-proxy-preactivation.ts +1 -3
  217. package/src/daemon/lifecycle.ts +21 -7
  218. package/src/daemon/persist-unsendable-image.ts +62 -25
  219. package/src/daemon/process-message.ts +1 -1
  220. package/src/daemon/server.ts +2 -0
  221. package/src/daemon/tool-side-effects.ts +15 -0
  222. package/src/daemon/wake-conversation-ops.ts +269 -0
  223. package/src/embedded/plugin-api.ts +2 -2
  224. package/src/export/__tests__/transcript-formatter.test.ts +5 -0
  225. package/src/heartbeat/__tests__/heartbeat-service.test.ts +3 -0
  226. package/src/heartbeat/heartbeat-run-store.ts +23 -1
  227. package/src/heartbeat/heartbeat-service.ts +26 -0
  228. package/src/ipc/__tests__/browser-ipc.test.ts +1 -1
  229. package/src/ipc/__tests__/ui-request-route.test.ts +3 -3
  230. package/src/ipc/skill-routes/__tests__/memory.test.ts +15 -0
  231. package/src/ipc/skill-routes/memory.ts +4 -2
  232. package/src/memory/__tests__/activation-session-store.test.ts +41 -0
  233. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +87 -0
  234. package/src/memory/__tests__/onboarding-events-store.test.ts +80 -0
  235. package/src/memory/activation-session-store.ts +43 -0
  236. package/src/memory/conversation-crud.ts +29 -19
  237. package/src/memory/conversation-starter-checkpoints.ts +1 -0
  238. package/src/memory/db-init.ts +6 -0
  239. package/src/memory/job-handlers/conversation-starters.ts +13 -2
  240. package/src/memory/jobs/__tests__/embed-concept-page.test.ts +5 -4
  241. package/src/memory/jobs-worker.ts +25 -1
  242. package/src/memory/migrations/272-acp-session-history-cwd.ts +36 -0
  243. package/src/memory/migrations/273-onboarding-events-funnel-columns.ts +46 -0
  244. package/src/memory/migrations/274-create-activation-sessions.ts +15 -0
  245. package/src/memory/migrations/index.ts +3 -0
  246. package/src/memory/onboarding-events-store.ts +66 -18
  247. package/src/memory/schema/acp.ts +4 -0
  248. package/src/memory/schema/infrastructure.ts +13 -0
  249. package/src/memory/v2/__tests__/consolidation-job.test.ts +4 -97
  250. package/src/memory/v2/__tests__/page-store.test.ts +22 -0
  251. package/src/memory/v2/consolidation-job.ts +2 -63
  252. package/src/memory/v2/types.ts +5 -0
  253. package/src/messaging/providers/telegram-bot/api.ts +14 -5
  254. package/src/notifications/__tests__/copy-composer.test.ts +244 -0
  255. package/src/notifications/access-request-copy.ts +298 -0
  256. package/src/notifications/adapters/slack.ts +3 -3
  257. package/src/notifications/adapters/telegram.ts +9 -2
  258. package/src/notifications/copy-composer.ts +49 -267
  259. package/src/notifications/decision-engine.ts +16 -35
  260. package/src/notifications/home-feed-side-effect.ts +1 -6
  261. package/src/plugin-api/constants.ts +4 -0
  262. package/src/plugin-api/index.ts +40 -11
  263. package/src/plugin-api/types.ts +108 -0
  264. package/src/plugins/defaults/compaction/compact.ts +106 -0
  265. package/src/{daemon → plugins/defaults/compaction}/context-overflow-reducer.ts +250 -42
  266. package/src/plugins/defaults/compaction/corrected-target.ts +53 -0
  267. package/src/plugins/defaults/compaction/manager-store.ts +57 -0
  268. package/src/plugins/defaults/compaction/package.json +1 -2
  269. package/src/{context → plugins/defaults/compaction}/window-manager.ts +95 -25
  270. package/src/plugins/defaults/empty-response/package.json +0 -1
  271. package/src/plugins/defaults/history-repair/package.json +0 -1
  272. package/src/plugins/defaults/index.ts +156 -26
  273. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +100 -52
  274. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +285 -0
  275. package/src/plugins/defaults/memory-retrieval/injector-chain.ts +2 -2
  276. package/src/plugins/defaults/{injectors/register.ts → memory-retrieval/injectors.ts} +148 -73
  277. package/src/plugins/defaults/memory-retrieval/package.json +14 -0
  278. package/src/plugins/defaults/memory-retrieval/unified-turn-context.ts +223 -0
  279. package/src/plugins/defaults/memory-v3-shadow/__tests__/capabilities.test.ts +71 -0
  280. package/src/plugins/defaults/memory-v3-shadow/__tests__/dense.test.ts +181 -0
  281. package/src/plugins/defaults/memory-v3-shadow/__tests__/edge.test.ts +247 -0
  282. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/live-integration.test.ts +147 -134
  283. package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +456 -0
  284. package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +662 -0
  285. package/src/plugins/defaults/memory-v3-shadow/__tests__/pool-select.test.ts +306 -0
  286. package/src/plugins/defaults/memory-v3-shadow/__tests__/render-injection.test.ts +91 -0
  287. package/src/plugins/defaults/memory-v3-shadow/__tests__/section-dense-store.test.ts +402 -0
  288. package/src/plugins/defaults/memory-v3-shadow/__tests__/section-needle.test.ts +135 -0
  289. package/src/plugins/defaults/memory-v3-shadow/__tests__/sections.test.ts +125 -0
  290. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/selection-log-store.test.ts +74 -19
  291. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-integration.test.ts +446 -0
  292. package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +592 -0
  293. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/types.test.ts +2 -24
  294. package/src/plugins/defaults/memory-v3-shadow/capabilities.ts +91 -0
  295. package/src/plugins/defaults/memory-v3-shadow/dense.ts +97 -0
  296. package/src/plugins/defaults/memory-v3-shadow/edge.ts +252 -0
  297. package/src/plugins/defaults/memory-v3-shadow/hooks/post-compact.ts +14 -0
  298. package/src/plugins/defaults/memory-v3-shadow/hooks/user-prompt-submit.ts +19 -0
  299. package/src/plugins/defaults/memory-v3-shadow/injector.ts +76 -0
  300. package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +555 -0
  301. package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +266 -0
  302. package/src/plugins/defaults/memory-v3-shadow/package.json +14 -0
  303. package/src/plugins/defaults/memory-v3-shadow/page-content.ts +71 -0
  304. package/src/plugins/defaults/memory-v3-shadow/pool-select.ts +204 -0
  305. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/render-injection.ts +16 -8
  306. package/src/plugins/defaults/memory-v3-shadow/section-dense-store.ts +236 -0
  307. package/src/plugins/defaults/memory-v3-shadow/section-needle.ts +200 -0
  308. package/src/plugins/defaults/memory-v3-shadow/sections.ts +115 -0
  309. package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +156 -0
  310. package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +382 -0
  311. package/src/plugins/defaults/memory-v3-shadow/types.ts +92 -0
  312. package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/working-set.ts +4 -1
  313. package/src/plugins/defaults/title-generate/package.json +0 -1
  314. package/src/plugins/defaults/tool-error/package.json +0 -1
  315. package/src/plugins/defaults/tool-result-truncate/package.json +0 -1
  316. package/src/plugins/external-api.ts +12 -2
  317. package/src/plugins/pipeline.ts +6 -293
  318. package/src/plugins/registry.ts +9 -37
  319. package/src/plugins/types.ts +76 -381
  320. package/src/plugins/user-loader.ts +30 -127
  321. package/src/prompts/__tests__/system-prompt.test.ts +6 -0
  322. package/src/prompts/system-prompt.ts +61 -10
  323. package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +71 -4
  324. package/src/providers/anthropic/client.ts +9 -10
  325. package/src/providers/inference/kimi-cjk-token-ids.ts +493 -0
  326. package/src/providers/inference/logit-bias.ts +55 -0
  327. package/src/providers/model-catalog.ts +34 -0
  328. package/src/providers/openai/__tests__/vision-not-supported.test.ts +75 -0
  329. package/src/providers/openai/chat-completions-provider.ts +44 -1
  330. package/src/providers/retry.ts +22 -0
  331. package/src/providers/types.ts +6 -0
  332. package/src/runtime/__tests__/agent-wake.test.ts +555 -691
  333. package/src/runtime/__tests__/interactive-ui.test.ts +1 -1
  334. package/src/runtime/agent-wake.ts +108 -209
  335. package/src/runtime/assistant-event-hub.ts +1 -1
  336. package/src/runtime/channel-approvals.ts +1 -1
  337. package/src/runtime/interactive-ui.ts +1 -1
  338. package/src/runtime/routes/__tests__/acp-routes.test.ts +466 -55
  339. package/src/runtime/routes/__tests__/conversation-list-routes.test.ts +1 -1
  340. package/src/runtime/routes/__tests__/plugins-routes.test.ts +423 -73
  341. package/src/runtime/routes/__tests__/stt-routes.test.ts +112 -0
  342. package/src/runtime/routes/__tests__/surface-action-routes.test.ts +5 -4
  343. package/src/runtime/routes/__tests__/surface-content-routes.test.ts +4 -1
  344. package/src/runtime/routes/acp-routes.test.ts +185 -32
  345. package/src/runtime/routes/acp-routes.ts +328 -30
  346. package/src/runtime/routes/app-management-routes.ts +3 -0
  347. package/src/runtime/routes/approval-routes.ts +1 -1
  348. package/src/runtime/routes/browser-routes.ts +1 -1
  349. package/src/runtime/routes/browser-tabs-routes.ts +6 -10
  350. package/src/runtime/routes/channel-verification-routes.ts +14 -5
  351. package/src/runtime/routes/conversation-cli-routes.ts +1 -1
  352. package/src/runtime/routes/conversation-list-routes.ts +1 -1
  353. package/src/runtime/routes/conversation-query-routes.ts +1 -1
  354. package/src/runtime/routes/conversation-routes.ts +30 -2
  355. package/src/runtime/routes/conversation-starter-routes.ts +13 -7
  356. package/src/runtime/routes/conversations-import-routes.ts +24 -7
  357. package/src/runtime/routes/host-app-control-routes.ts +1 -1
  358. package/src/runtime/routes/host-cu-routes.ts +1 -1
  359. package/src/runtime/routes/identity-routes.ts +18 -3
  360. package/src/runtime/routes/inbound-message-handler.ts +1 -1
  361. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +33 -34
  362. package/src/runtime/routes/inference-profile-session-handler.ts +11 -0
  363. package/src/runtime/routes/inference-profile-session-reaper.ts +6 -0
  364. package/src/runtime/routes/memory-v3-routes.ts +65 -305
  365. package/src/runtime/routes/playground/__tests__/force-compact.test.ts +1 -1
  366. package/src/runtime/routes/playground/helpers.ts +1 -1
  367. package/src/runtime/routes/plugins-routes.ts +337 -35
  368. package/src/runtime/routes/stt-routes.ts +45 -12
  369. package/src/runtime/routes/surface-conversation-resolver.ts +4 -3
  370. package/src/runtime/routes/work-items-routes.ts +2 -4
  371. package/src/runtime/routes/workspace-routes.ts +50 -15
  372. package/src/runtime/services/conversation-serializer.ts +1 -1
  373. package/src/runtime/verification-outbound-actions.ts +147 -2
  374. package/src/runtime/verification-templates.ts +29 -3
  375. package/src/services/published-app-updater.ts +30 -8
  376. package/src/signals/cancel.ts +2 -4
  377. package/src/subagent/manager.ts +21 -5
  378. package/src/telemetry/__tests__/activation-funnel.test.ts +95 -0
  379. package/src/telemetry/activation-funnel.ts +167 -0
  380. package/src/telemetry/types.ts +13 -0
  381. package/src/telemetry/usage-telemetry-reporter.test.ts +154 -0
  382. package/src/telemetry/usage-telemetry-reporter.ts +26 -1
  383. package/src/tools/acp/context.ts +20 -0
  384. package/src/tools/acp/list-agents.test.ts +9 -19
  385. package/src/tools/acp/list-agents.ts +3 -15
  386. package/src/tools/acp/spawn.test.ts +173 -202
  387. package/src/tools/acp/spawn.ts +37 -172
  388. package/src/tools/acp/steer.test.ts +105 -8
  389. package/src/tools/acp/steer.ts +48 -17
  390. package/src/tools/apps/executors.ts +166 -50
  391. package/src/tools/browser/browser-execution.ts +12 -2
  392. package/src/tools/filesystem/write.ts +34 -0
  393. package/src/tools/network/web-fetch.ts +65 -24
  394. package/src/tools/skills/load.ts +1 -1
  395. package/src/tools/subagent/spawn.ts +2 -4
  396. package/src/tools/ui-surface/definitions.ts +32 -5
  397. package/src/workspace/migrations/051-seed-conversation-summarization-callsite.ts +4 -5
  398. package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +69 -45
  399. package/docs/plugins.md +0 -832
  400. package/examples/plugins/echo/register.ts +0 -143
  401. package/src/__tests__/circuit-breaker-pipeline.test.ts +0 -405
  402. package/src/__tests__/compaction-pipeline.test.ts +0 -210
  403. package/src/__tests__/compaction-timeout-recovery.test.ts +0 -251
  404. package/src/__tests__/overflow-reduce-pipeline.test.ts +0 -667
  405. package/src/__tests__/pipeline-runner.test.ts +0 -554
  406. package/src/daemon/wake-target-adapter.ts +0 -253
  407. package/src/memory/v3/__tests__/assign.test.ts +0 -242
  408. package/src/memory/v3/__tests__/capabilities.test.ts +0 -118
  409. package/src/memory/v3/__tests__/core.test.ts +0 -39
  410. package/src/memory/v3/__tests__/health.test.ts +0 -219
  411. package/src/memory/v3/__tests__/maintain-job.test.ts +0 -288
  412. package/src/memory/v3/__tests__/needle.test.ts +0 -107
  413. package/src/memory/v3/__tests__/orchestrate.test.ts +0 -436
  414. package/src/memory/v3/__tests__/provider-blocks.test.ts +0 -13
  415. package/src/memory/v3/__tests__/reconcile.test.ts +0 -274
  416. package/src/memory/v3/__tests__/render-injection.test.ts +0 -61
  417. package/src/memory/v3/__tests__/router.test.ts +0 -332
  418. package/src/memory/v3/__tests__/selector.test.ts +0 -470
  419. package/src/memory/v3/__tests__/shadow-plugin.test.ts +0 -432
  420. package/src/memory/v3/__tests__/snapshot.test.ts +0 -168
  421. package/src/memory/v3/__tests__/tree.test.ts +0 -192
  422. package/src/memory/v3/assign.ts +0 -268
  423. package/src/memory/v3/capabilities.ts +0 -124
  424. package/src/memory/v3/core.ts +0 -26
  425. package/src/memory/v3/health.ts +0 -0
  426. package/src/memory/v3/maintain-job.ts +0 -314
  427. package/src/memory/v3/needle.ts +0 -115
  428. package/src/memory/v3/orchestrate.ts +0 -126
  429. package/src/memory/v3/page-content.ts +0 -34
  430. package/src/memory/v3/provider-blocks.ts +0 -26
  431. package/src/memory/v3/reconcile.ts +0 -523
  432. package/src/memory/v3/router.ts +0 -190
  433. package/src/memory/v3/selection-log-store.ts +0 -84
  434. package/src/memory/v3/selector.ts +0 -226
  435. package/src/memory/v3/shadow-plugin.ts +0 -411
  436. package/src/memory/v3/snapshot.ts +0 -209
  437. package/src/memory/v3/tree.ts +0 -174
  438. package/src/memory/v3/types.ts +0 -59
  439. package/src/notifications/__tests__/emit-signal-home-feed.test.ts +0 -187
  440. package/src/plugins/defaults/circuit-breaker/middlewares/circuitBreaker.ts +0 -93
  441. package/src/plugins/defaults/circuit-breaker/package.json +0 -15
  442. package/src/plugins/defaults/circuit-breaker/register.ts +0 -39
  443. package/src/plugins/defaults/compaction/middlewares/compaction.ts +0 -25
  444. package/src/plugins/defaults/compaction/register.ts +0 -35
  445. package/src/plugins/defaults/compaction/terminal.ts +0 -73
  446. package/src/plugins/defaults/empty-response/register.ts +0 -23
  447. package/src/plugins/defaults/history-repair/register.ts +0 -24
  448. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit-temp.ts +0 -216
  449. package/src/plugins/defaults/overflow-reduce/middlewares/overflowReduce.ts +0 -126
  450. package/src/plugins/defaults/overflow-reduce/package.json +0 -15
  451. package/src/plugins/defaults/overflow-reduce/register.ts +0 -42
  452. package/src/plugins/defaults/title-generate/register.ts +0 -35
  453. package/src/plugins/defaults/tool-error/register.ts +0 -23
  454. package/src/plugins/defaults/tool-result-truncate/register.ts +0 -24
  455. package/src/proactive-artifact/aux-message-injector.ts +0 -97
  456. package/src/proactive-artifact/decision.test.ts +0 -226
  457. package/src/proactive-artifact/decision.ts +0 -165
  458. package/src/proactive-artifact/index.ts +0 -7
  459. package/src/proactive-artifact/job.test.ts +0 -962
  460. package/src/proactive-artifact/job.ts +0 -372
  461. package/src/proactive-artifact/message-copy.ts +0 -58
  462. package/src/proactive-artifact/trigger-state.test.ts +0 -286
  463. package/src/proactive-artifact/trigger-state.ts +0 -123
  464. package/src/util/map-limit.ts +0 -27
  465. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/eval-turns.json +0 -0
  466. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/fixtures/live-turns.json +0 -0
  467. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-eviction.test.ts +0 -0
  468. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/__tests__/working-set-skeleton.test.ts +0 -0
  469. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/README.md +0 -0
  470. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/assignments.json +0 -0
  471. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/core.json +0 -0
  472. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-x.md +0 -0
  473. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-a/topic-y.md +0 -0
  474. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/data/leaves/domain-b/topic-z.md +0 -0
  475. /package/src/{memory/v3 → plugins/defaults/memory-v3-shadow}/llm-retry.ts +0 -0
@@ -22,7 +22,6 @@ import type { Message } from "../providers/types.js";
22
22
 
23
23
  mock.module("../memory/conversation-crud.js", () => ({
24
24
  getConversationOverrideProfile: () => undefined,
25
- reserveMessage: mock(async () => ({ id: "msg-reserve" })),
26
25
  }));
27
26
 
28
27
  mock.module("../config/loader.js", () => ({
@@ -62,36 +61,37 @@ mock.module("../daemon/disk-pressure-guard.js", () => ({
62
61
  }),
63
62
  }));
64
63
 
64
+ import type { Conversation } from "../daemon/conversation.js";
65
65
  import {
66
66
  __resetWakeChainForTests,
67
67
  wakeAgentForOpportunity,
68
- type WakeTarget,
69
68
  } from "../runtime/agent-wake.js";
70
69
 
71
- function makeTarget(): WakeTarget {
72
- const history: Message[] = [];
70
+ function makeTarget(): Conversation {
71
+ const messages: Message[] = [];
73
72
  let processing = false;
74
- return {
73
+ const target = {
75
74
  conversationId: "conv-wake-callsite",
76
75
  agentLoop: {
77
- run: (async (messages: Message[]) => ({
76
+ run: async ({ messages }: { messages: Message[] }) => ({
78
77
  history: messages,
79
78
  exitReason: null,
80
79
  appendedNewMessages: false,
81
80
  newMessages: [],
82
- })) as WakeTarget["agentLoop"]["run"],
81
+ }),
83
82
  },
84
- getMessages: () => history,
85
- pushMessage: (msg) => {
86
- history.push(msg);
87
- },
88
- emitAgentEvent: () => {},
83
+ messages,
84
+ getMessages: () => messages,
89
85
  isProcessing: () => processing,
90
- markProcessing: (on) => {
86
+ setProcessing: (on: boolean) => {
91
87
  processing = on;
92
88
  },
93
- persistTailMessage: async () => {},
89
+ setTrustContext: () => {},
90
+ getTurnChannelContext: () => null,
91
+ getTurnInterfaceContext: () => null,
92
+ drainQueue: async () => {},
94
93
  };
94
+ return target as unknown as Conversation;
95
95
  }
96
96
 
97
97
  beforeEach(() => {
@@ -48,8 +48,9 @@ mock.module("../config/loader.js", () => ({
48
48
  }),
49
49
  }));
50
50
 
51
- import type { AgentEvent, AgentLoopRunOptions } from "../agent/loop.js";
51
+ import type { AgentLoopRunOptions } from "../agent/loop.js";
52
52
  import { LLMSchema } from "../config/schemas/llm.js";
53
+ import type { Conversation } from "../daemon/conversation.js";
53
54
  import { RetryProvider } from "../providers/retry.js";
54
55
  import type {
55
56
  Message,
@@ -60,7 +61,6 @@ import type {
60
61
  import {
61
62
  __resetWakeChainForTests,
62
63
  wakeAgentForOpportunity,
63
- type WakeTarget,
64
64
  } from "../runtime/agent-wake.js";
65
65
 
66
66
  interface RunArgs {
@@ -69,44 +69,40 @@ interface RunArgs {
69
69
  }
70
70
 
71
71
  function makeTarget(): {
72
- target: WakeTarget;
72
+ target: Conversation;
73
73
  runArgs: RunArgs[];
74
74
  } {
75
75
  const runArgs: RunArgs[] = [];
76
- const history: Message[] = [
76
+ const messages: Message[] = [
77
77
  { role: "user", content: [{ type: "text", text: "hi" }] },
78
78
  ];
79
79
  let processing = false;
80
80
 
81
- const target: WakeTarget = {
81
+ const target = {
82
82
  conversationId: "conv-wake-override",
83
83
  agentLoop: {
84
- run: (async (
85
- messages: Message[],
86
- _onEvent: (event: AgentEvent) => void | Promise<void>,
87
- options?: AgentLoopRunOptions,
88
- ) => {
84
+ run: async (options: AgentLoopRunOptions) => {
89
85
  runArgs.push({
90
- messages: [...messages],
86
+ messages: [...options.messages],
91
87
  options,
92
88
  });
93
89
  // Return the input verbatim → silent no-op (no assistant tail).
94
90
  // Wake never yields at a checkpoint, so the pause-reason is null.
95
- return { history: messages, exitReason: null };
96
- }) as WakeTarget["agentLoop"]["run"],
97
- },
98
- getMessages: () => history,
99
- pushMessage: (msg) => {
100
- history.push(msg);
91
+ return { history: options.messages, exitReason: null };
92
+ },
101
93
  },
102
- emitAgentEvent: () => {},
94
+ messages,
95
+ getMessages: () => messages,
103
96
  isProcessing: () => processing,
104
- markProcessing: (on) => {
97
+ setProcessing: (on: boolean) => {
105
98
  processing = on;
106
99
  },
107
- persistTailMessage: async () => {},
100
+ setTrustContext: () => {},
101
+ getTurnChannelContext: () => null,
102
+ getTurnInterfaceContext: () => null,
103
+ drainQueue: async () => {},
108
104
  };
109
- return { target, runArgs };
105
+ return { target: target as unknown as Conversation, runArgs };
110
106
  }
111
107
 
112
108
  beforeEach(() => {
@@ -2,7 +2,11 @@ import { beforeEach, describe, expect, mock, test } from "bun:test";
2
2
 
3
3
  import type { Anthropic } from "@anthropic-ai/sdk";
4
4
 
5
- import type { Message, ToolDefinition } from "../providers/types.js";
5
+ import type {
6
+ ContentBlock,
7
+ Message,
8
+ ToolDefinition,
9
+ } from "../providers/types.js";
6
10
 
7
11
  // ---------------------------------------------------------------------------
8
12
  // Mock Anthropic SDK — must be before importing the provider
@@ -102,7 +106,6 @@ mock.module("@anthropic-ai/sdk", () => ({
102
106
  }));
103
107
 
104
108
  // Import after mocking
105
- import { cachedTextBlock } from "../memory/v3/provider-blocks.js";
106
109
  import { AnthropicProvider } from "../providers/anthropic/client.js";
107
110
  import {
108
111
  isPlaceholderSentinelText,
@@ -138,6 +141,18 @@ function toolResultMsg(toolUseId: string, content: string): Message {
138
141
  };
139
142
  }
140
143
 
144
+ // A stable prefix text block carrying a 1h-TTL cache_control breakpoint, as a
145
+ // caller may stamp before the provider sees it. The internal ContentBlock type
146
+ // omits cache_control (only the provider transforms it onto the wire), so reach
147
+ // it via a cast.
148
+ function cachedPrefixBlock(text: string): ContentBlock {
149
+ return {
150
+ type: "text",
151
+ text,
152
+ cache_control: { type: "ephemeral", ttl: "1h" },
153
+ } as unknown as ContentBlock;
154
+ }
155
+
141
156
  const sampleTools: ToolDefinition[] = [
142
157
  {
143
158
  name: "file_read",
@@ -325,13 +340,13 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
325
340
  });
326
341
 
327
342
  test("preserves a caller's 1h block cache_control and sends the extended-cache beta (non-Haiku)", async () => {
328
- // v3's `cachedTextBlock` stamps a stable prefix block with a 1h TTL; the
329
- // non-Haiku path must forward it unchanged and send the beta header.
343
+ // A caller that stamps a stable prefix block with a 1h TTL: the non-Haiku
344
+ // path must forward it unchanged and send the beta header.
330
345
  await provider.sendMessage([
331
346
  {
332
347
  role: "user",
333
348
  content: [
334
- cachedTextBlock("stable pages block"),
349
+ cachedPrefixBlock("stable pages block"),
335
350
  { type: "text", text: "volatile current message" },
336
351
  ],
337
352
  },
@@ -349,7 +364,7 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
349
364
 
350
365
  test("strips ttl from a caller's block cache_control and omits the beta for Haiku", async () => {
351
366
  // Haiku doesn't support the extended-cache-ttl beta, so a caller-stamped
352
- // 1h ttl (e.g. from `cachedTextBlock`) must be stripped before sending.
367
+ // 1h ttl on a message block must be stripped before sending.
353
368
  const haiku = new AnthropicProvider(
354
369
  "sk-ant-test",
355
370
  "claude-haiku-4-5-20251001",
@@ -358,7 +373,7 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
358
373
  {
359
374
  role: "user",
360
375
  content: [
361
- cachedTextBlock("stable pages block"),
376
+ cachedPrefixBlock("stable pages block"),
362
377
  { type: "text", text: "volatile current message" },
363
378
  ],
364
379
  },
@@ -385,7 +400,7 @@ describe("AnthropicProvider — Cache-Control Characterization", () => {
385
400
  {
386
401
  role: "user",
387
402
  content: [
388
- cachedTextBlock("stable pages block"),
403
+ cachedPrefixBlock("stable pages block"),
389
404
  { type: "text", text: "volatile current message" },
390
405
  ],
391
406
  },
@@ -81,6 +81,7 @@ mock.module("../bundler/app-compiler.js", () => ({
81
81
  import * as appCreateScript from "../config/bundled-skills/app-builder/tools/app-create.js";
82
82
  import * as appDeleteScript from "../config/bundled-skills/app-builder/tools/app-delete.js";
83
83
  import * as appRefreshScript from "../config/bundled-skills/app-builder/tools/app-refresh.js";
84
+ import * as appUpdateScript from "../config/bundled-skills/app-builder/tools/app-update.js";
84
85
 
85
86
  // ---------------------------------------------------------------------------
86
87
  // Tests
@@ -171,4 +172,24 @@ describe("app-builder skill tool scripts", () => {
171
172
  expect(parsed.appId).toBe("app-1");
172
173
  });
173
174
  });
175
+
176
+ // ---- app-update --------------------------------------------------------
177
+
178
+ describe("app-update", () => {
179
+ test("exports a run function", () => {
180
+ expect(typeof appUpdateScript.run).toBe("function");
181
+ });
182
+
183
+ test("delegates to executeAppUpdate and returns result", async () => {
184
+ const result = await appUpdateScript.run(
185
+ { app_id: "app-1", name: "Renamed" },
186
+ makeContext(),
187
+ );
188
+ expect(result.isError).toBe(false);
189
+ const parsed = JSON.parse(result.content);
190
+ expect(parsed.updated).toBe(true);
191
+ expect(parsed.appId).toBe("app-1");
192
+ expect(parsed.name).toBe("Renamed");
193
+ });
194
+ });
174
195
  });
@@ -103,7 +103,7 @@ const { ROUTES } = await import("../runtime/routes/host-app-control-routes.js");
103
103
  const { surfaceProxyResolver } =
104
104
  await import("../daemon/conversation-surfaces.js");
105
105
  const { setConversation, clearConversations } =
106
- await import("../daemon/conversation-store.js");
106
+ await import("../daemon/conversation-registry.js");
107
107
  type SurfaceConversationContext =
108
108
  import("../daemon/conversation-surfaces.js").SurfaceConversationContext;
109
109
 
@@ -19,6 +19,7 @@ const ALLOWLIST = new Set([
19
19
  "assistant/src/memory/app-store.ts", // defines getAppsDir
20
20
  "assistant/src/memory/app-git-service.ts", // uses getAppsDir for git repo root, not per-app paths
21
21
  "assistant/src/daemon/app-source-watcher.ts", // uses getAppsDir for recursive fs.watch root, not per-app paths
22
+ "assistant/src/tools/filesystem/write.ts", // uses getAppsDir as an exemption root for the artifact-HTML guard, not per-app paths
22
23
  ]);
23
24
 
24
25
  function isTestFile(filePath: string): boolean {
@@ -32,6 +32,7 @@ import type { AppStore } from "../tools/apps/executors.js";
32
32
  import {
33
33
  executeAppCreate,
34
34
  executeAppRefresh,
35
+ executeAppUpdate,
35
36
  } from "../tools/apps/executors.js";
36
37
 
37
38
  // ---------------------------------------------------------------------------
@@ -89,6 +90,46 @@ function mockStore(
89
90
  // ---------------------------------------------------------------------------
90
91
 
91
92
  describe("executeAppCreate", () => {
93
+ test("falls back to the preview title when the name is omitted or blank", async () => {
94
+ let createdParams: Record<string, unknown> | undefined;
95
+ const app = makeMultifileApp({ name: "Coffee Tracker" });
96
+ const store: AppStore = {
97
+ ...mockStore(app, {}),
98
+ createApp: (params) => {
99
+ createdParams = params as unknown as Record<string, unknown>;
100
+ return app;
101
+ },
102
+ };
103
+
104
+ const result = await executeAppCreate(
105
+ { name: " ", preview: { title: "Coffee Tracker" } },
106
+ store,
107
+ );
108
+
109
+ expect(result.isError).toBe(false);
110
+ expect(createdParams?.name).toBe("Coffee Tracker");
111
+ });
112
+
113
+ test("defaults the name to 'New App' when neither name nor preview title is given", async () => {
114
+ let createdParams: Record<string, unknown> | undefined;
115
+ const app = makeMultifileApp({ name: "New App" });
116
+ const store: AppStore = {
117
+ ...mockStore(app, {}),
118
+ createApp: (params) => {
119
+ createdParams = params as unknown as Record<string, unknown>;
120
+ return app;
121
+ },
122
+ };
123
+
124
+ const result = await executeAppCreate(
125
+ {} as unknown as Parameters<typeof executeAppCreate>[0],
126
+ store,
127
+ );
128
+
129
+ expect(result.isError).toBe(false);
130
+ expect(createdParams?.name).toBe("New App");
131
+ });
132
+
92
133
  test("creates multifile app with src/ scaffold", async () => {
93
134
  const files: Record<string, string> = {};
94
135
  let createdParams: Record<string, unknown> | undefined;
@@ -408,3 +449,94 @@ describe("executeAppRefresh", () => {
408
449
  expect(parsed.error).toContain("not found");
409
450
  });
410
451
  });
452
+
453
+ // ---------------------------------------------------------------------------
454
+ // executeAppUpdate
455
+ // ---------------------------------------------------------------------------
456
+
457
+ describe("executeAppUpdate", () => {
458
+ test("updates metadata and recompiles a multifile app", async () => {
459
+ const app = makeMultifileApp({ name: "Old", description: "old desc" });
460
+ let updateArgs: unknown;
461
+ const store: AppStore = {
462
+ ...mockStore(app),
463
+ updateApp: (_id, updates) => {
464
+ updateArgs = updates;
465
+ return { ...app, ...updates };
466
+ },
467
+ };
468
+
469
+ const result = await executeAppUpdate(
470
+ { app_id: app.id, name: "New Name", description: "new desc" },
471
+ store,
472
+ );
473
+
474
+ expect(result.isError).toBe(false);
475
+ expect(updateArgs).toEqual({ name: "New Name", description: "new desc" });
476
+ const parsed = JSON.parse(result.content);
477
+ expect(parsed.updated).toBe(true);
478
+ expect(parsed.name).toBe("New Name");
479
+ expect(parsed.description).toBe("new desc");
480
+ expect(parsed.compiled).toBe(true);
481
+ });
482
+
483
+ test("writes source_files before recompiling", async () => {
484
+ const files: Record<string, string> = {};
485
+ const app = makeMultifileApp();
486
+ const store: AppStore = {
487
+ ...mockStore(app, files),
488
+ updateApp: (_id, updates) => ({ ...app, ...updates }),
489
+ };
490
+
491
+ const result = await executeAppUpdate(
492
+ { app_id: app.id, source_files: { "src/App.tsx": "// new code" } },
493
+ store,
494
+ );
495
+
496
+ expect(result.isError).toBe(false);
497
+ expect(files["src/App.tsx"]).toBe("// new code");
498
+ expect(JSON.parse(result.content).compiled).toBe(true);
499
+ });
500
+
501
+ test("legacy app: updates without compiling", async () => {
502
+ const app = makeLegacyApp({ name: "Legacy" });
503
+ const store: AppStore = {
504
+ ...mockStore(app),
505
+ updateApp: (_id, updates) => ({ ...app, ...updates }),
506
+ };
507
+
508
+ const result = await executeAppUpdate(
509
+ { app_id: app.id, name: "Renamed" },
510
+ store,
511
+ );
512
+
513
+ expect(result.isError).toBe(false);
514
+ const parsed = JSON.parse(result.content);
515
+ expect(parsed.updated).toBe(true);
516
+ expect(parsed.name).toBe("Renamed");
517
+ expect(parsed.compiled).toBeUndefined();
518
+ });
519
+
520
+ test("returns error for unknown app", async () => {
521
+ const store = mockStore(makeMultifileApp());
522
+ const result = await executeAppUpdate({ app_id: "nope" }, store);
523
+
524
+ expect(result.isError).toBe(true);
525
+ expect(JSON.parse(result.content).error).toContain("not found");
526
+ });
527
+
528
+ test("rejects invalid source_files", async () => {
529
+ const app = makeMultifileApp();
530
+ const store = mockStore(app);
531
+ const result = await executeAppUpdate(
532
+ {
533
+ app_id: app.id,
534
+ source_files: { "src/App.tsx": 123 as unknown as string },
535
+ },
536
+ store,
537
+ );
538
+
539
+ expect(result.isError).toBe(true);
540
+ expect(JSON.parse(result.content).error).toContain("must be a string");
541
+ });
542
+ });
@@ -173,9 +173,10 @@ mock.module("../memory/retriever.js", () => ({
173
173
  injectMemoryRecallAsUserBlock: (msgs: Message[]) => msgs,
174
174
  }));
175
175
 
176
- mock.module("../context/window-manager.js", () => ({
176
+ mock.module("../plugins/defaults/compaction/window-manager.js", () => ({
177
177
  ContextWindowManager: class {
178
178
  constructor() {}
179
+ updateConfig() {}
179
180
  shouldCompact() {
180
181
  return { needed: false, estimatedTokens: 0 };
181
182
  }
@@ -208,10 +209,10 @@ mock.module("../agent/loop.js", () => ({
208
209
  getActiveModel() {
209
210
  return undefined;
210
211
  }
211
- async run(
212
- _messages: Message[],
213
- _onEvent: (event: AgentEvent) => void,
214
- ): Promise<Message[]> {
212
+ async run(_options: {
213
+ messages: Message[];
214
+ onEvent: (event: AgentEvent) => void;
215
+ }): Promise<Message[]> {
215
216
  return [];
216
217
  }
217
218
  },
@@ -119,12 +119,15 @@ mock.module("../permissions/trust-store.js", () => ({
119
119
  // ---------------------------------------------------------------------------
120
120
  let _conversationFactory: (() => Conversation) | undefined;
121
121
 
122
- mock.module("../daemon/conversation-store.js", () => ({
122
+ mock.module("../daemon/conversation-registry.js", () => ({
123
123
  findConversation: () => {
124
124
  // Return the current test session for any conversation ID lookup.
125
125
  if (!_conversationFactory) return undefined;
126
126
  return _conversationFactory();
127
127
  },
128
+ }));
129
+
130
+ mock.module("../daemon/conversation-store.js", () => ({
128
131
  getOrCreateConversation: async () => {
129
132
  if (!_conversationFactory)
130
133
  throw new Error("_conversationFactory not set in test");
@@ -117,7 +117,7 @@ mock.module("../memory/conversation-crud.js", () => ({
117
117
  findMostRecentRetrospectiveFor: mock(() => null),
118
118
  forkConversation: mock(() => ({ id: "conv-fork" })),
119
119
  getConversationOverrideProfile: () => undefined,
120
- getConversationOverrideProfileFromRow: () => undefined,
120
+ resolveOverrideProfile: () => undefined,
121
121
  getConversationMemoryScopeId: () => "default",
122
122
  getConversationOriginChannel: () => null,
123
123
  getConversationOriginInterface: () => null,
@@ -16,7 +16,7 @@ mock.module("../util/logger.js", () => ({
16
16
  }));
17
17
 
18
18
  const _conversationMocks = new Map<string, unknown>();
19
- mock.module("../daemon/conversation-store.js", () => ({
19
+ mock.module("../daemon/conversation-registry.js", () => ({
20
20
  findConversation: (id: string) => _conversationMocks.get(id),
21
21
  }));
22
22
 
@@ -11,7 +11,7 @@ mock.module("../util/logger.js", () => ({
11
11
 
12
12
  // Map conversationId → mock session so findConversation returns the right mock.
13
13
  const conversationMocks = new Map<string, unknown>();
14
- mock.module("../daemon/conversation-store.js", () => ({
14
+ mock.module("../daemon/conversation-registry.js", () => ({
15
15
  findConversation: (id: string) => conversationMocks.get(id),
16
16
  }));
17
17