@vellumai/assistant 0.8.7 → 0.8.8

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 (387) hide show
  1. package/Dockerfile +20 -4
  2. package/docker-entrypoint.sh +4 -2
  3. package/docker-init-apt-root.sh +3 -1
  4. package/docker-kata-apt-env.sh +3 -1
  5. package/docker-kata-runtime-family.sh +12 -0
  6. package/docs/architecture/memory.md +1 -1
  7. package/docs/plugins.md +75 -79
  8. package/examples/plugins/echo/README.md +6 -12
  9. package/examples/plugins/echo/register.ts +0 -41
  10. package/node_modules/@vellumai/skill-host-contracts/src/server-message.ts +3 -3
  11. package/openapi.yaml +3381 -348
  12. package/package.json +1 -1
  13. package/scripts/generate-openapi.ts +68 -41
  14. package/src/__tests__/agent-loop-exit-reason.test.ts +34 -39
  15. package/src/__tests__/agent-loop-provider-error-recording.test.ts +1 -1
  16. package/src/__tests__/agent-loop.test.ts +37 -87
  17. package/src/__tests__/agent-wake-disk-pressure-callsite.test.ts +2 -0
  18. package/src/__tests__/annotate-activity-metadata.test.ts +262 -0
  19. package/src/__tests__/annotate-risk-options.test.ts +2 -3
  20. package/src/__tests__/anthropic-provider.test.ts +95 -2
  21. package/src/__tests__/assistant-event-hub.test.ts +25 -0
  22. package/src/__tests__/assistant-events-sse-shed.test.ts +8 -0
  23. package/src/__tests__/{conversation-stream-state.test.ts → assistant-stream-state.test.ts} +252 -91
  24. package/src/__tests__/auth-fallback-events-store.test.ts +116 -0
  25. package/src/__tests__/background-workers-disk-pressure.test.ts +6 -0
  26. package/src/__tests__/btw-routes.test.ts +62 -3
  27. package/src/__tests__/build-persisted-content.test.ts +184 -0
  28. package/src/__tests__/catalog-files.test.ts +1 -1
  29. package/src/__tests__/clawhub-files.test.ts +1 -1
  30. package/src/__tests__/compaction-pipeline.test.ts +1 -1
  31. package/src/__tests__/compaction.benchmark.test.ts +0 -30
  32. package/src/__tests__/config-watcher.test.ts +1 -1
  33. package/src/__tests__/conversation-abort-tool-results.test.ts +57 -19
  34. package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +6 -2
  35. package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +10 -4
  36. package/src/__tests__/conversation-agent-loop-overflow.test.ts +313 -1136
  37. package/src/__tests__/conversation-agent-loop.test.ts +596 -1616
  38. package/src/__tests__/conversation-analysis-routes.test.ts +6 -0
  39. package/src/__tests__/conversation-history-web-search.test.ts +11 -1
  40. package/src/__tests__/conversation-pairing.test.ts +4 -31
  41. package/src/__tests__/conversation-process-app-control-preactivation.test.ts +6 -0
  42. package/src/__tests__/conversation-provider-retry-repair.test.ts +26 -5
  43. package/src/__tests__/conversation-queue.test.ts +2 -0
  44. package/src/__tests__/conversation-routes-disk-view.test.ts +3 -0
  45. package/src/__tests__/conversation-routes-slash-commands.test.ts +6 -5
  46. package/src/__tests__/conversation-runtime-assembly.test.ts +170 -229
  47. package/src/__tests__/conversation-runtime-workspace.test.ts +3 -24
  48. package/src/__tests__/conversation-slash-commands.test.ts +8 -42
  49. package/src/__tests__/conversation-slash-queue.test.ts +6 -1
  50. package/src/__tests__/conversation-surfaces-action-delivery.test.ts +84 -0
  51. package/src/__tests__/conversation-sync-tags.test.ts +27 -15
  52. package/src/__tests__/conversation-title-service.test.ts +135 -2
  53. package/src/__tests__/conversation-workspace-injection.test.ts +6 -1
  54. package/src/__tests__/cross-provider-web-search.test.ts +214 -1
  55. package/src/__tests__/db-schedule-syntax-migration.test.ts +5 -0
  56. package/src/__tests__/dm-persistence.test.ts +5 -1
  57. package/src/__tests__/empty-response-hook.test.ts +304 -0
  58. package/src/__tests__/feature-flag-test-helpers.ts +2 -2
  59. package/src/__tests__/gemini-image-service.test.ts +13 -0
  60. package/src/__tests__/helpers/mock-provider.ts +110 -0
  61. package/src/__tests__/helpers/native-web-search-harness.ts +129 -0
  62. package/src/__tests__/history-repair-hook.test.ts +1 -0
  63. package/src/__tests__/identity-intro-cache.test.ts +12 -100
  64. package/src/__tests__/identity-routes.test.ts +248 -7
  65. package/src/__tests__/inbound-slack-persistence.test.ts +5 -1
  66. package/src/__tests__/injector-background-turn.test.ts +2 -8
  67. package/src/__tests__/injector-chain.test.ts +106 -270
  68. package/src/__tests__/injector-disk-pressure.test.ts +3 -12
  69. package/src/__tests__/injector-document-comments.test.ts +2 -2
  70. package/src/__tests__/injector-pkb-v2-silenced.test.ts +30 -22
  71. package/src/__tests__/injector-v3-suppression.test.ts +31 -37
  72. package/src/__tests__/internal-telemetry-routes.test.ts +109 -0
  73. package/src/__tests__/list-messages-page-latest.test.ts +60 -0
  74. package/src/__tests__/list-messages-tool-merge.test.ts +20 -0
  75. package/src/__tests__/llm-usage-store.test.ts +223 -1
  76. package/src/__tests__/memory-retrieval-hook.test.ts +297 -0
  77. package/src/__tests__/memory-v2-static-injector.test.ts +103 -35
  78. package/src/__tests__/native-web-search.test.ts +191 -0
  79. package/src/__tests__/onboarding-template-contract.test.ts +2 -0
  80. package/src/__tests__/openai-image-service.test.ts +17 -0
  81. package/src/__tests__/openai-provider.test.ts +31 -1
  82. package/src/__tests__/persist-unsendable-image.test.ts +215 -0
  83. package/src/__tests__/persistence-secret-redaction.test.ts +1 -0
  84. package/src/__tests__/pipeline-runner.test.ts +29 -39
  85. package/src/__tests__/pkb-autoinject.test.ts +2 -5
  86. package/src/__tests__/plugin-bootstrap.test.ts +13 -28
  87. package/src/__tests__/plugin-registry.test.ts +0 -27
  88. package/src/__tests__/plugin-types.test.ts +2 -125
  89. package/src/__tests__/process-message-display-content.test.ts +6 -2
  90. package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +5 -1
  91. package/src/__tests__/resolve-trust-class.test.ts +4 -4
  92. package/src/__tests__/runtime-events-sse-reconnect.test.ts +60 -23
  93. package/src/__tests__/schedule-routes.test.ts +603 -2
  94. package/src/__tests__/schedule-store.test.ts +41 -0
  95. package/src/__tests__/schedule-tools.test.ts +35 -0
  96. package/src/__tests__/server-history-render.test.ts +314 -1
  97. package/src/__tests__/skillssh-files.test.ts +1 -1
  98. package/src/__tests__/system-prompt.test.ts +20 -0
  99. package/src/__tests__/task-scheduler.test.ts +162 -1
  100. package/src/__tests__/terminal-tools.test.ts +6 -1
  101. package/src/__tests__/title-generate-hook.test.ts +319 -0
  102. package/src/__tests__/tool-error-hook.test.ts +278 -0
  103. package/src/__tests__/tool-preview-lifecycle.test.ts +468 -5
  104. package/src/__tests__/tool-result-metadata-plumbing.test.ts +1 -0
  105. package/src/__tests__/tool-result-truncate-hook.test.ts +127 -0
  106. package/src/__tests__/tool-result-truncation.test.ts +0 -2
  107. package/src/__tests__/ui-choice-copy-surfaces.test.ts +254 -0
  108. package/src/__tests__/ui-work-result-surface.test.ts +159 -0
  109. package/src/__tests__/usage-routes.test.ts +285 -1
  110. package/src/__tests__/user-plugin-loader.test.ts +2 -2
  111. package/src/__tests__/voice-session-bridge.test.ts +6 -3
  112. package/src/__tests__/web-search-backend-failure.test.ts +166 -0
  113. package/src/agent/loop.ts +346 -442
  114. package/src/api/events/assistant-thinking-delta.ts +33 -0
  115. package/src/api/events/tool-output-chunk.ts +45 -0
  116. package/src/api/events/tool-use-preview-start.ts +32 -0
  117. package/src/api/events/trace-event.ts +69 -0
  118. package/src/api/index.ts +48 -13
  119. package/src/api/responses/conversation-message.ts +368 -0
  120. package/src/avatar/__tests__/avatar-store.test.ts +34 -29
  121. package/src/cli/commands/__tests__/notifications.test.ts +58 -14
  122. package/src/cli/commands/notifications.ts +112 -60
  123. package/src/config/assistant-feature-flags.ts +22 -11
  124. package/src/config/bundled-skills/app-builder/SKILL.md +3 -20
  125. package/src/config/bundled-skills/app-builder/references/examples/README.md +17 -0
  126. package/src/config/bundled-skills/app-builder/references/examples/expense-tracker.md +515 -0
  127. package/src/config/bundled-skills/app-builder/references/examples/focus-timer.md +342 -0
  128. package/src/config/bundled-skills/app-builder/references/examples/habit-tracker.md +490 -0
  129. package/src/config/bundled-skills/document-editor/SKILL.md +1 -1
  130. package/src/config/bundled-skills/messaging/SKILL.md +0 -7
  131. package/src/config/feature-flag-cache.ts +3 -3
  132. package/src/config/feature-flag-registry.json +35 -3
  133. package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
  134. package/src/config/schemas/__tests__/memory-v3.test.ts +25 -0
  135. package/src/config/schemas/llm.ts +1 -0
  136. package/src/config/schemas/memory-v2.ts +8 -0
  137. package/src/config/schemas/memory-v3.ts +8 -0
  138. package/src/config/schemas/platform.ts +8 -0
  139. package/src/config/seed-inference-profiles.ts +2 -2
  140. package/src/config/skills.ts +13 -0
  141. package/src/context/compactor.ts +1 -1
  142. package/src/context/strip-injections.ts +122 -0
  143. package/src/context/token-estimator.ts +23 -0
  144. package/src/context/tool-result-truncation.ts +0 -23
  145. package/src/context/window-manager.ts +3 -6
  146. package/src/credential-execution/executable-discovery.ts +16 -0
  147. package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +6 -0
  148. package/src/daemon/__tests__/inference-profile-notification.test.ts +153 -0
  149. package/src/daemon/__tests__/native-web-search-metadata.test.ts +10 -8
  150. package/src/daemon/assistant-attachments.ts +1 -1
  151. package/src/daemon/config-watcher.ts +2 -2
  152. package/src/daemon/context-overflow-reducer.ts +0 -1
  153. package/src/daemon/conversation-agent-loop-handlers.ts +605 -153
  154. package/src/daemon/conversation-agent-loop.ts +281 -760
  155. package/src/daemon/conversation-history.ts +5 -4
  156. package/src/daemon/conversation-lifecycle.ts +3 -4
  157. package/src/daemon/conversation-messaging.ts +7 -6
  158. package/src/daemon/conversation-process.ts +11 -16
  159. package/src/daemon/conversation-runtime-assembly.ts +130 -347
  160. package/src/daemon/conversation-slash.ts +6 -25
  161. package/src/daemon/conversation-surfaces.ts +222 -4
  162. package/src/daemon/conversation-tool-setup.ts +2 -29
  163. package/src/daemon/conversation.ts +32 -14
  164. package/src/daemon/external-plugins-bootstrap.ts +9 -10
  165. package/src/daemon/handlers/config-a2a.ts +51 -36
  166. package/src/daemon/handlers/config-slack-channel.ts +20 -14
  167. package/src/daemon/handlers/config-telegram.ts +16 -2
  168. package/src/daemon/handlers/shared.ts +156 -84
  169. package/src/daemon/handlers/skills.ts +39 -10
  170. package/src/daemon/lifecycle.ts +4 -0
  171. package/src/daemon/message-types/apps.ts +1 -29
  172. package/src/daemon/message-types/messages.ts +9 -57
  173. package/src/daemon/message-types/skills.ts +2 -0
  174. package/src/daemon/message-types/surfaces.ts +136 -3
  175. package/src/daemon/now-scratchpad.ts +21 -0
  176. package/src/daemon/orphan-reaper.test.ts +210 -0
  177. package/src/daemon/orphan-reaper.ts +240 -0
  178. package/src/daemon/persist-unsendable-image.ts +117 -0
  179. package/src/daemon/process-message.ts +1 -3
  180. package/src/daemon/trace-emitter.ts +6 -4
  181. package/src/daemon/trust-context.ts +19 -0
  182. package/src/daemon/wake-target-adapter.ts +3 -1
  183. package/src/home/home-greeting-cache.ts +24 -1
  184. package/src/ipc/gateway-client.test.ts +2 -2
  185. package/src/ipc/gateway-client.ts +3 -3
  186. package/src/media/gemini-image-service.ts +15 -0
  187. package/src/media/openai-image-service.ts +14 -0
  188. package/src/media/types.ts +34 -0
  189. package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +56 -0
  190. package/src/memory/auth-fallback-events-store.ts +94 -0
  191. package/src/memory/conversation-title-service.ts +65 -41
  192. package/src/memory/db-init.ts +4 -0
  193. package/src/memory/graph/__tests__/conversation-graph-memory-registry.test.ts +119 -0
  194. package/src/memory/graph/conversation-graph-memory.ts +65 -0
  195. package/src/memory/jobs-store.ts +33 -0
  196. package/src/memory/jobs-worker.ts +31 -4
  197. package/src/memory/llm-usage-store.ts +224 -50
  198. package/src/memory/migrations/222-strip-placeholder-sentinels-from-messages.ts +6 -5
  199. package/src/memory/migrations/270-schedule-source-conversation.ts +13 -0
  200. package/src/memory/migrations/271-create-auth-fallback-events.ts +21 -0
  201. package/src/memory/migrations/index.ts +2 -0
  202. package/src/memory/pkb/autoinject.ts +61 -0
  203. package/src/memory/pkb/context.ts +50 -0
  204. package/src/memory/pkb/types.ts +14 -0
  205. package/src/memory/schedule-attribution-sql.ts +104 -0
  206. package/src/memory/schema/infrastructure.ts +16 -0
  207. package/src/memory/usage-grouped-buckets.ts +6 -1
  208. package/src/memory/v2/__tests__/consolidation-job.test.ts +1 -1
  209. package/src/memory/v2/consolidation-job.ts +1 -1
  210. package/src/memory/v3/__tests__/health.test.ts +16 -0
  211. package/src/memory/v3/__tests__/orchestrate.test.ts +45 -9
  212. package/src/memory/v3/__tests__/provider-blocks.test.ts +13 -0
  213. package/src/memory/v3/__tests__/router.test.ts +101 -29
  214. package/src/memory/v3/__tests__/selector.test.ts +93 -27
  215. package/src/memory/v3/__tests__/shadow-plugin.test.ts +23 -5
  216. package/src/memory/v3/health.ts +0 -0
  217. package/src/memory/v3/llm-retry.ts +32 -0
  218. package/src/memory/v3/orchestrate.ts +26 -14
  219. package/src/memory/v3/provider-blocks.ts +15 -5
  220. package/src/memory/v3/router.ts +48 -42
  221. package/src/memory/v3/selector.ts +57 -42
  222. package/src/memory/v3/shadow-plugin.ts +47 -15
  223. package/src/memory/v3/types.ts +8 -0
  224. package/src/notifications/conversation-pairing.ts +8 -15
  225. package/src/notifications/decision-engine.ts +6 -3
  226. package/src/notifications/home-feed-side-effect.ts +12 -1
  227. package/src/permissions/prompter.ts +4 -0
  228. package/src/plugin-api/constants.ts +4 -0
  229. package/src/plugin-api/index.ts +8 -1
  230. package/src/plugin-api/types.ts +151 -1
  231. package/src/plugins/defaults/empty-response/hooks/stop.ts +126 -0
  232. package/src/plugins/defaults/empty-response/register.ts +8 -13
  233. package/src/plugins/defaults/index.ts +1 -15
  234. package/src/plugins/defaults/injectors/register.ts +243 -74
  235. package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +91 -0
  236. package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit-temp.ts +216 -0
  237. package/src/plugins/defaults/memory-retrieval/injector-chain.ts +35 -0
  238. package/src/plugins/defaults/title-generate/hooks/stop.ts +75 -0
  239. package/src/plugins/defaults/title-generate/hooks/user-prompt-submit.ts +35 -0
  240. package/src/plugins/defaults/title-generate/package.json +1 -1
  241. package/src/plugins/defaults/title-generate/register.ts +18 -18
  242. package/src/plugins/defaults/tool-error/hooks/post-tool-use.ts +118 -0
  243. package/src/plugins/defaults/tool-error/package.json +1 -1
  244. package/src/plugins/defaults/tool-error/register.ts +9 -21
  245. package/src/plugins/defaults/tool-result-truncate/hooks/post-tool-use.ts +32 -0
  246. package/src/plugins/defaults/tool-result-truncate/register.ts +10 -21
  247. package/src/plugins/defaults/tool-result-truncate/terminal.ts +37 -18
  248. package/src/plugins/pipeline.ts +6 -18
  249. package/src/plugins/registry.ts +8 -25
  250. package/src/plugins/types.ts +43 -474
  251. package/src/proactive-artifact/aux-message-injector.ts +3 -3
  252. package/src/proactive-artifact/job.test.ts +7 -12
  253. package/src/prompts/__tests__/system-prompt.test.ts +36 -0
  254. package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +62 -0
  255. package/src/prompts/templates/BOOTSTRAP.md +2 -2
  256. package/src/prompts/templates/system-sections.ts +15 -0
  257. package/src/providers/anthropic/client.ts +37 -29
  258. package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +112 -0
  259. package/src/providers/openai/chat-completions-provider.ts +44 -0
  260. package/src/providers/openrouter/client.ts +1 -0
  261. package/src/providers/placeholder-sentinels.ts +35 -0
  262. package/src/runtime/__tests__/agent-wake.test.ts +5 -1
  263. package/src/runtime/agent-wake.ts +2 -2
  264. package/src/runtime/assistant-event-hub.ts +36 -6
  265. package/src/runtime/{conversation-stream-state.ts → assistant-stream-state.ts} +132 -58
  266. package/src/runtime/http-router.ts +16 -21
  267. package/src/runtime/http-types.ts +16 -70
  268. package/src/runtime/pending-interactions.ts +1 -0
  269. package/src/runtime/routes/__tests__/consolidation-routes.test.ts +265 -2
  270. package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +31 -1
  271. package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +6 -2
  272. package/src/runtime/routes/__tests__/tts-routes.test.ts +6 -2
  273. package/src/runtime/routes/app-management-routes.ts +6 -117
  274. package/src/runtime/routes/app-routes.ts +13 -15
  275. package/src/runtime/routes/attachment-routes.ts +26 -15
  276. package/src/runtime/routes/avatar-routes.ts +26 -0
  277. package/src/runtime/routes/btw-routes.ts +29 -23
  278. package/src/runtime/routes/consolidation-routes.ts +120 -20
  279. package/src/runtime/routes/conversation-query-routes.ts +2 -0
  280. package/src/runtime/routes/conversation-routes.ts +358 -184
  281. package/src/runtime/routes/documents-routes.ts +4 -0
  282. package/src/runtime/routes/domain-routes.ts +51 -37
  283. package/src/runtime/routes/epoch-millis-range.ts +34 -0
  284. package/src/runtime/routes/events-routes.ts +28 -34
  285. package/src/runtime/routes/gateway-log-routes.ts +26 -4
  286. package/src/runtime/routes/heartbeat-routes.ts +32 -12
  287. package/src/runtime/routes/identity-intro-cache.ts +11 -34
  288. package/src/runtime/routes/identity-routes.ts +208 -17
  289. package/src/runtime/routes/image-generation-routes.ts +40 -2
  290. package/src/runtime/routes/index.ts +2 -0
  291. package/src/runtime/routes/integrations/a2a.ts +12 -10
  292. package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +16 -0
  293. package/src/runtime/routes/integrations/slack/channel.ts +4 -0
  294. package/src/runtime/routes/integrations/slack/share.ts +27 -6
  295. package/src/runtime/routes/integrations/telegram.ts +6 -0
  296. package/src/runtime/routes/integrations/twilio.ts +42 -0
  297. package/src/runtime/routes/internal-telemetry-routes.ts +88 -0
  298. package/src/runtime/routes/log-export-routes.ts +8 -0
  299. package/src/runtime/routes/memory-v2-routes.ts +15 -8
  300. package/src/runtime/routes/memory-v3-routes.ts +50 -28
  301. package/src/runtime/routes/oauth-apps.ts +66 -12
  302. package/src/runtime/routes/oauth-providers.ts +44 -5
  303. package/src/runtime/routes/platform-routes.ts +81 -5
  304. package/src/runtime/routes/playground/__tests__/force-compact.test.ts +6 -4
  305. package/src/runtime/routes/playground/force-compact.ts +1 -1
  306. package/src/runtime/routes/rename-conversation-routes.ts +5 -0
  307. package/src/runtime/routes/schedule-routes.ts +152 -42
  308. package/src/runtime/routes/secret-routes.ts +14 -2
  309. package/src/runtime/routes/skills-routes.ts +43 -14
  310. package/src/runtime/routes/tool-call-confirmation-enrichment.test.ts +161 -0
  311. package/src/runtime/routes/tool-call-confirmation-enrichment.ts +107 -0
  312. package/src/runtime/routes/trust-rules-routes.ts +26 -2
  313. package/src/runtime/routes/tts-routes.ts +35 -0
  314. package/src/runtime/routes/types.ts +66 -8
  315. package/src/runtime/routes/usage-routes.ts +47 -39
  316. package/src/runtime/routes/webhook-routes.ts +41 -2
  317. package/src/runtime/routes/workspace-routes.ts +4 -0
  318. package/src/runtime/services/__tests__/analyze-conversation.test.ts +6 -0
  319. package/src/runtime/services/analyze-conversation.ts +2 -2
  320. package/src/schedule/schedule-store.ts +20 -1
  321. package/src/schedule/schedule-usage-store.ts +83 -0
  322. package/src/schedule/scheduler.ts +12 -5
  323. package/src/skills/catalog-files.ts +2 -2
  324. package/src/skills/catalog-install.ts +3 -0
  325. package/src/skills/categories-cache.ts +118 -0
  326. package/src/skills/clawhub-files.ts +1 -2
  327. package/src/skills/skillssh-files.ts +1 -2
  328. package/src/telemetry/types.ts +29 -1
  329. package/src/telemetry/usage-telemetry-reporter.test.ts +112 -3
  330. package/src/telemetry/usage-telemetry-reporter.ts +57 -2
  331. package/src/tools/executor.ts +1 -53
  332. package/src/tools/network/__tests__/web-search-metadata.test.ts +7 -1
  333. package/src/tools/network/__tests__/web-search.test.ts +11 -3
  334. package/src/tools/network/web-search-error.test.ts +248 -0
  335. package/src/tools/network/web-search-error.ts +267 -0
  336. package/src/tools/network/web-search.ts +207 -48
  337. package/src/tools/schedule/create.ts +2 -0
  338. package/src/tools/terminal/safe-env.ts +10 -1
  339. package/src/tools/ui-surface/definitions.ts +9 -1
  340. package/src/tts/__tests__/provider-catalog-consistency.test.ts +85 -1
  341. package/src/tts/provider-catalog.ts +76 -1
  342. package/src/util/mutex.ts +47 -0
  343. package/src/workspace/git-service.ts +1 -42
  344. package/src/workspace/migrations/095-bump-heartbeat-interval-30m-to-60m.ts +51 -0
  345. package/src/workspace/migrations/096-reduce-quality-profile-effort.ts +72 -0
  346. package/src/workspace/migrations/097-enable-adaptive-thinking-managed-profiles.ts +93 -0
  347. package/src/workspace/migrations/registry.ts +6 -0
  348. package/src/__tests__/bootstrap-turn-cleanup.test.ts +0 -44
  349. package/src/__tests__/empty-response-pipeline.test.ts +0 -423
  350. package/src/__tests__/llm-call-pipeline.test.ts +0 -287
  351. package/src/__tests__/memory-retrieval-pipeline.test.ts +0 -418
  352. package/src/__tests__/persistence-pipeline.test.ts +0 -503
  353. package/src/__tests__/title-generate-pipeline.test.ts +0 -211
  354. package/src/__tests__/token-estimate-pipeline.test.ts +0 -479
  355. package/src/__tests__/tool-error-pipeline.test.ts +0 -241
  356. package/src/__tests__/tool-execute-pipeline.test.ts +0 -417
  357. package/src/__tests__/tool-result-truncate-pipeline.test.ts +0 -341
  358. package/src/daemon/bootstrap-turn-cleanup.ts +0 -45
  359. package/src/gallery/default-gallery.ts +0 -1359
  360. package/src/gallery/gallery-manifest.ts +0 -28
  361. package/src/home/feature-gate.ts +0 -22
  362. package/src/plugins/defaults/empty-response/middlewares/emptyResponse.ts +0 -22
  363. package/src/plugins/defaults/empty-response/terminal.ts +0 -106
  364. package/src/plugins/defaults/injectors/package.json +0 -15
  365. package/src/plugins/defaults/llm-call/middlewares/llmCall.ts +0 -17
  366. package/src/plugins/defaults/llm-call/package.json +0 -15
  367. package/src/plugins/defaults/llm-call/register.ts +0 -45
  368. package/src/plugins/defaults/memory-retrieval/middlewares/memoryRetrieval.ts +0 -17
  369. package/src/plugins/defaults/memory-retrieval/package.json +0 -15
  370. package/src/plugins/defaults/memory-retrieval/register.ts +0 -181
  371. package/src/plugins/defaults/persistence/middlewares/persistence.ts +0 -19
  372. package/src/plugins/defaults/persistence/package.json +0 -15
  373. package/src/plugins/defaults/persistence/register.ts +0 -38
  374. package/src/plugins/defaults/persistence/terminal.ts +0 -83
  375. package/src/plugins/defaults/title-generate/terminal.ts +0 -31
  376. package/src/plugins/defaults/token-estimate/middlewares/tokenEstimate.ts +0 -23
  377. package/src/plugins/defaults/token-estimate/package.json +0 -15
  378. package/src/plugins/defaults/token-estimate/register.ts +0 -34
  379. package/src/plugins/defaults/token-estimate/terminal.ts +0 -40
  380. package/src/plugins/defaults/tool-error/middlewares/toolError.ts +0 -21
  381. package/src/plugins/defaults/tool-error/terminal.ts +0 -47
  382. package/src/plugins/defaults/tool-execute/middlewares/toolExecute.ts +0 -23
  383. package/src/plugins/defaults/tool-execute/package.json +0 -15
  384. package/src/plugins/defaults/tool-execute/register.ts +0 -49
  385. package/src/plugins/defaults/tool-result-truncate/middlewares/toolResultTruncate.ts +0 -23
  386. package/src/plugins/defaults/tool-result-truncate/types.ts +0 -22
  387. package/src/skills/category-inference.ts +0 -111
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vellumai/assistant",
3
- "version": "0.8.7",
3
+ "version": "0.8.8",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "exports": {
@@ -56,12 +56,24 @@ const RouteBodySchemaSchema = z.any().refine(
56
56
  { message: "Expected a Zod schema or a plain JSON Schema object" },
57
57
  );
58
58
 
59
- const RouteRequestBodyVariantSchema = z.object({
59
+ /** Explicit `{ contentType, schema }` body for non-JSON media types. */
60
+ const RouteBodyWithContentTypeSchema = z.object({
60
61
  contentType: z.string(),
61
62
  /** Zod schema OR plain JSON Schema fragment. */
62
63
  schema: z.any(),
63
64
  });
64
65
 
66
+ /**
67
+ * A route's request or success-response body: either a bare Zod/JSON schema
68
+ * (advertised as `application/json`) or an explicit `{ contentType, schema }`
69
+ * pair for non-JSON media (e.g. an `application/octet-stream` upload or binary
70
+ * download).
71
+ */
72
+ const RouteContentBodySchema = z.union([
73
+ RouteBodyWithContentTypeSchema,
74
+ RouteBodySchemaSchema,
75
+ ]);
76
+
65
77
  const RouteAdditionalResponseSchema = z.object({
66
78
  description: z.string(),
67
79
  schema: z.any().optional(),
@@ -79,12 +91,10 @@ const RouteEntrySchema = z.object({
79
91
  tags: z.array(z.string()).optional(),
80
92
  /** Query parameter definitions. */
81
93
  queryParams: z.array(RouteQueryParamSchema).optional(),
82
- /** JSON Schema for the request body. */
83
- requestBody: RouteBodySchemaSchema.optional(),
84
- /** Multi-content-type request body variants (overrides `requestBody` when present). */
85
- requestBodies: z.array(RouteRequestBodyVariantSchema).optional(),
86
- /** JSON Schema for the success response body. */
87
- responseBody: RouteBodySchemaSchema.optional(),
94
+ /** Request body: a bare Zod/JSON schema (JSON) or `{ contentType, schema }`. */
95
+ requestBody: RouteContentBodySchema.optional(),
96
+ /** Success response body: a bare Zod/JSON schema (JSON) or `{ contentType, schema }`. */
97
+ responseBody: RouteContentBodySchema.optional(),
88
98
  /** HTTP status code for the success response. Defaults to "200".
89
99
  * Callable responseStatus values (used at runtime) are ignored here. */
90
100
  responseStatus: z.preprocess(
@@ -292,6 +302,11 @@ interface OpenApiParameter {
292
302
  description?: string;
293
303
  }
294
304
 
305
+ interface OpenApiResponse {
306
+ description: string;
307
+ content?: Record<string, { schema: JSONSchemaObject }>;
308
+ }
309
+
295
310
  interface OpenApiOperation {
296
311
  operationId: string;
297
312
  summary?: string;
@@ -302,13 +317,27 @@ interface OpenApiOperation {
302
317
  required: boolean;
303
318
  content: Record<string, { schema: JSONSchemaObject }>;
304
319
  };
305
- responses: Record<
306
- string,
307
- {
308
- description: string;
309
- content?: Record<string, { schema: JSONSchemaObject }>;
310
- }
311
- >;
320
+ responses: Record<string, OpenApiResponse>;
321
+ }
322
+
323
+ /**
324
+ * Resolve a body declaration (request or success response) into its media type
325
+ * and the schema source to convert. A bare Zod/JSON schema is advertised as
326
+ * `application/json`; the explicit `{ contentType, schema }` form carries its
327
+ * own media type (e.g. `application/octet-stream` for binary bodies).
328
+ */
329
+ function resolveBodyContent(body: unknown): {
330
+ contentType: string;
331
+ schemaSource: unknown;
332
+ } {
333
+ const hasContentType =
334
+ typeof body === "object" && body !== null && "contentType" in body;
335
+ return {
336
+ contentType: hasContentType
337
+ ? (body as { contentType: string }).contentType
338
+ : "application/json",
339
+ schemaSource: hasContentType ? (body as { schema: unknown }).schema : body,
340
+ };
312
341
  }
313
342
 
314
343
  interface OpenApiPathItem {
@@ -420,22 +449,27 @@ function buildSpec(
420
449
  // that enqueue a job and return immediately set responseStatus: "202"
421
450
  // so the generated spec matches the handler's actual response code.
422
451
  const successStatus = entry.responseStatus ?? "200";
452
+ let successResponse: OpenApiResponse = {
453
+ description: "Successful response",
454
+ };
455
+ if (entry.responseBody) {
456
+ const { contentType, schemaSource } = resolveBodyContent(
457
+ entry.responseBody,
458
+ );
459
+ successResponse = {
460
+ description: "Successful response",
461
+ content: {
462
+ [contentType]: { schema: toJSONSchemaObject(schemaSource) },
463
+ },
464
+ };
465
+ }
423
466
  const operation: OpenApiOperation = {
424
467
  operationId,
425
468
  ...(entry.summary ? { summary: entry.summary } : {}),
426
469
  ...(entry.description ? { description: entry.description } : {}),
427
470
  ...(tags ? { tags } : {}),
428
471
  responses: {
429
- [successStatus]: entry.responseBody
430
- ? {
431
- description: "Successful response",
432
- content: {
433
- "application/json": {
434
- schema: toJSONSchemaObject(entry.responseBody),
435
- },
436
- },
437
- }
438
- : { description: "Successful response" },
472
+ [successStatus]: successResponse,
439
473
  },
440
474
  };
441
475
 
@@ -443,26 +477,19 @@ function buildSpec(
443
477
  operation.parameters = parameters;
444
478
  }
445
479
 
446
- // Multi-content-type request bodies take precedence over the single
447
- // application/json requestBody. This lets an endpoint advertise a
448
- // `oneOf`-style choice between `application/octet-stream`,
449
- // `multipart/form-data`, and `application/json` on the same URL.
450
- if (entry.requestBodies && entry.requestBodies.length > 0) {
451
- const content: Record<string, { schema: JSONSchemaObject }> = {};
452
- for (const variant of entry.requestBodies) {
453
- content[variant.contentType] = {
454
- schema: toJSONSchemaObject(variant.schema, {
455
- stripRequiredDefaults: true,
456
- }),
457
- };
458
- }
459
- operation.requestBody = { required: true, content };
460
- } else if (entry.requestBody) {
480
+ // A bare Zod/JSON schema is advertised as `application/json`; the
481
+ // explicit `{ contentType, schema }` form lets a route declare a non-JSON
482
+ // body (e.g. a raw `application/octet-stream` upload) so the generated SDK
483
+ // describes a real body type instead of `never`.
484
+ if (entry.requestBody) {
485
+ const { contentType, schemaSource } = resolveBodyContent(
486
+ entry.requestBody,
487
+ );
461
488
  operation.requestBody = {
462
489
  required: true,
463
490
  content: {
464
- "application/json": {
465
- schema: toJSONSchemaObject(entry.requestBody, {
491
+ [contentType]: {
492
+ schema: toJSONSchemaObject(schemaSource, {
466
493
  stripRequiredDefaults: true,
467
494
  }),
468
495
  },
@@ -1,18 +1,17 @@
1
1
  /**
2
- * Tests for the `agent_loop_exit` instrumentation added in this PR.
2
+ * Tests for the `agent_loop_exit` instrumentation.
3
3
  *
4
4
  * Coverage targets:
5
- * 1. **One emit per run** — the idempotency guard fires once, even if the
6
- * code path would otherwise reach two emit sites (the empty-response
7
- * throw catch-block fallback case).
5
+ * 1. **One emit per run** — the idempotency guard fires once, even when
6
+ * multiple exit conditions stack and the code path would otherwise
7
+ * reach a second emit site.
8
8
  * 2. **Reason matches break site** — for each reachable break site, the
9
9
  * emitted reason is the one documented in `AgentLoopExitReason`.
10
10
  * 3. **Always the last AgentEvent of terminal runs** — consumers can rely on
11
11
  * positional ordering to find it when a run reaches a terminal state.
12
12
  *
13
- * Sites not exercised here (`empty_response_exhausted`, `aborted_via_error`)
14
- * require deeper provider fakery and are best covered by integration tests
15
- * once we wire up the empty-response pipeline mock.
13
+ * Sites not exercised here (`aborted_via_error`) require deeper provider
14
+ * fakery and are best covered by integration tests.
16
15
  */
17
16
  import { describe, expect, spyOn, test } from "bun:test";
18
17
 
@@ -379,40 +378,40 @@ describe("AgentLoop exit-reason instrumentation", () => {
379
378
  toolExecutor: toolExecutor,
380
379
  });
381
380
 
382
- let prepared = false;
383
- let appliedResult = false;
384
381
  let reinjected = false;
382
+ const events: AgentEvent[] = [];
385
383
  const compaction: MidLoopCompaction = {
386
- prepare: (history) => {
387
- prepared = true;
388
- return { rawHistory: history, options: undefined };
389
- },
390
- applyResult: async () => {
391
- appliedResult = true;
392
- },
393
- reinject: async () => {
384
+ postCompactionHook: async () => {
394
385
  reinjected = true;
395
386
  return [userMessage];
396
387
  },
397
388
  };
398
389
 
399
390
  // WHEN the in-loop budget gate trips at the checkpoint
400
- const result = await loop.run([userMessage], () => {}, {
401
- resolveContextWindow: () => ({
402
- maxInputTokens: 10,
403
- overflowRecovery: { enabled: true, safetyMarginRatio: 0 },
404
- }),
405
- compaction,
406
- turnContext: fakeCompactionTurnContext({
407
- compacted: true,
408
- exhausted: false,
409
- }),
410
- });
391
+ const result = await loop.run(
392
+ [userMessage],
393
+ (event) => {
394
+ events.push(event);
395
+ },
396
+ {
397
+ resolveContextWindow: () => ({
398
+ maxInputTokens: 10,
399
+ overflowRecovery: { enabled: true, safetyMarginRatio: 0 },
400
+ }),
401
+ compaction,
402
+ turnContext: fakeCompactionTurnContext({
403
+ compacted: true,
404
+ exhausted: false,
405
+ }),
406
+ },
407
+ );
411
408
 
412
409
  // THEN the loop runs the compaction ceremony in place and continues to a
413
- // clean exit instead of yielding for budget.
414
- expect(prepared).toBe(true);
415
- expect(appliedResult).toBe(true);
410
+ // clean exit instead of yielding for budget. The durable commit is
411
+ // signalled via a `compaction_completed` event rather than an injected hook.
412
+ expect(events.some((event) => event.type === "compaction_completed")).toBe(
413
+ true,
414
+ );
416
415
  expect(reinjected).toBe(true);
417
416
  expect(result.exitReason).not.toBe("budget");
418
417
  });
@@ -429,10 +428,8 @@ describe("AgentLoop exit-reason instrumentation", () => {
429
428
  });
430
429
 
431
430
  const compaction: MidLoopCompaction = {
432
- prepare: (history) => ({ rawHistory: history, options: undefined }),
433
- applyResult: async () => {},
434
- reinject: async () => {
435
- throw new Error("reinject must not run after a timeout");
431
+ postCompactionHook: async () => {
432
+ throw new Error("postCompactionHook must not run after a timeout");
436
433
  },
437
434
  };
438
435
  const recordOutcomeSpy = spyOn(loop.compactionCircuit, "recordOutcome");
@@ -467,10 +464,8 @@ describe("AgentLoop exit-reason instrumentation", () => {
467
464
  });
468
465
 
469
466
  const compaction: MidLoopCompaction = {
470
- prepare: (history) => ({ rawHistory: history, options: undefined }),
471
- applyResult: async () => {},
472
- reinject: async () => {
473
- throw new Error("reinject must not run when exhausted");
467
+ postCompactionHook: async () => {
468
+ throw new Error("postCompactionHook must not run when exhausted");
474
469
  },
475
470
  };
476
471
 
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Integration tests for the agent loop's `provider_error` recording path.
3
3
  *
4
- * When the `llmCall` pipeline throws (provider rejected the request before
4
+ * When the provider call throws (provider rejected the request before
5
5
  * returning a usable response), the loop must emit a `provider_error` event
6
6
  * carrying the loop-level raw request and the thrown error so downstream
7
7
  * consumers can persist an `llm_request_logs` row. Without this, rejected
@@ -1,4 +1,4 @@
1
- import { describe, expect, test } from "bun:test";
1
+ import { beforeEach, describe, expect, test } from "bun:test";
2
2
 
3
3
  import type {
4
4
  AgentEvent,
@@ -6,90 +6,24 @@ import type {
6
6
  CheckpointInfo,
7
7
  } from "../agent/loop.js";
8
8
  import { AgentLoop } from "../agent/loop.js";
9
+ import { resetPluginRegistryAndRegisterDefaults } from "../plugins/defaults/index.js";
9
10
  import type {
10
11
  ContentBlock,
11
12
  Message,
12
13
  Provider,
13
14
  ProviderResponse,
14
- SendMessageOptions,
15
15
  ToolDefinition,
16
16
  } from "../providers/types.js";
17
+ import {
18
+ createMockProvider,
19
+ textResponse,
20
+ toolUseResponse,
21
+ } from "./helpers/mock-provider.js";
17
22
 
18
23
  // ---------------------------------------------------------------------------
19
24
  // Helpers
20
25
  // ---------------------------------------------------------------------------
21
26
 
22
- /** A mock provider that returns pre-configured responses in sequence. */
23
- function createMockProvider(responses: ProviderResponse[]): {
24
- provider: Provider;
25
- calls: {
26
- messages: Message[];
27
- tools?: ToolDefinition[];
28
- systemPrompt?: string;
29
- options?: SendMessageOptions;
30
- }[];
31
- } {
32
- const calls: {
33
- messages: Message[];
34
- tools?: ToolDefinition[];
35
- systemPrompt?: string;
36
- options?: SendMessageOptions;
37
- }[] = [];
38
- let callIndex = 0;
39
-
40
- const provider: Provider = {
41
- name: "mock",
42
- async sendMessage(
43
- messages: Message[],
44
- options?: SendMessageOptions,
45
- ): Promise<ProviderResponse> {
46
- calls.push({
47
- messages: [...messages],
48
- tools: options?.tools,
49
- systemPrompt: options?.systemPrompt,
50
- options,
51
- });
52
- const response = responses[callIndex] ?? responses[responses.length - 1];
53
- callIndex++;
54
-
55
- // Emit streaming events if the response has text blocks
56
- if (options?.onEvent) {
57
- for (const block of response.content) {
58
- if (block.type === "text") {
59
- options.onEvent({ type: "text_delta", text: block.text });
60
- }
61
- }
62
- }
63
-
64
- return response;
65
- },
66
- };
67
-
68
- return { provider, calls };
69
- }
70
-
71
- function textResponse(text: string): ProviderResponse {
72
- return {
73
- content: [{ type: "text", text }],
74
- model: "mock-model",
75
- usage: { inputTokens: 10, outputTokens: 5 },
76
- stopReason: "end_turn",
77
- };
78
- }
79
-
80
- function toolUseResponse(
81
- id: string,
82
- name: string,
83
- input: Record<string, unknown>,
84
- ): ProviderResponse {
85
- return {
86
- content: [{ type: "tool_use", id, name, input }],
87
- model: "mock-model",
88
- usage: { inputTokens: 10, outputTokens: 5 },
89
- stopReason: "tool_use",
90
- };
91
- }
92
-
93
27
  const dummyTools: ToolDefinition[] = [
94
28
  {
95
29
  name: "read_file",
@@ -112,6 +46,13 @@ function collectEvents(events: AgentEvent[]): (event: AgentEvent) => void {
112
46
  // ---------------------------------------------------------------------------
113
47
 
114
48
  describe("AgentLoop", () => {
49
+ // The agent loop fires the `post-tool-use` hook for tool-result
50
+ // truncation, which only runs when the default plugin is registered.
51
+ // Register the defaults so the loop behaves as it does in production.
52
+ beforeEach(() => {
53
+ resetPluginRegistryAndRegisterDefaults();
54
+ });
55
+
115
56
  // 1. Basic text response
116
57
  test("returns history with assistant message for simple text response", async () => {
117
58
  const { provider } = createMockProvider([textResponse("Hi there!")]);
@@ -1569,9 +1510,11 @@ describe("AgentLoop", () => {
1569
1510
  expect(textBlock!.text).toBe("Normal response with no placeholders.");
1570
1511
  });
1571
1512
 
1572
- // Tool error retry nudge — when a tool returns isError: true, the loop
1573
- // should inject a system_notice nudging the LLM to retry instead of ending.
1574
- test("injects retry nudge system_notice when tool returns an error", async () => {
1513
+ // Tool error retry coaching — when a tool returns isError: true, the coaching
1514
+ // notice is appended as a separate text block in the tool-result user message
1515
+ // (not into the tool_result content), nudging the LLM to retry instead of
1516
+ // ending the turn while keeping the tool's actual output clean.
1517
+ test("appends retry coaching as a separate block when a tool returns an error", async () => {
1575
1518
  const { provider, calls } = createMockProvider([
1576
1519
  // First turn: LLM calls a tool that errors
1577
1520
  toolUseResponse("t1", "read_file", { path: "/missing.txt" }),
@@ -1606,7 +1549,8 @@ describe("AgentLoop", () => {
1606
1549
  // Provider should have been called 3 times (error -> retry -> final text)
1607
1550
  expect(calls).toHaveLength(3);
1608
1551
 
1609
- // The second call's messages should contain the retry nudge system_notice
1552
+ // The second call's messages should carry the retry coaching as a separate
1553
+ // text block, with the tool_result's own content left untouched.
1610
1554
  const secondCallMessages = calls[1].messages;
1611
1555
  const toolResultMessage = secondCallMessages[secondCallMessages.length - 1];
1612
1556
  expect(toolResultMessage.role).toBe("user");
@@ -1617,7 +1561,14 @@ describe("AgentLoop", () => {
1617
1561
  );
1618
1562
  expect(retryNudge).toBeDefined();
1619
1563
 
1620
- // The third call should NOT have the retry nudge (successful tool result)
1564
+ // The errored tool_result itself stays the tool's actual output.
1565
+ const erroredToolResult = toolResultMessage.content.find(
1566
+ (b): b is Extract<ContentBlock, { type: "tool_result" }> =>
1567
+ b.type === "tool_result",
1568
+ );
1569
+ expect(erroredToolResult?.content).not.toContain("looks recoverable");
1570
+
1571
+ // The third call should NOT have the retry coaching (successful tool result)
1621
1572
  const thirdCallMessages = calls[2].messages;
1622
1573
  const thirdToolResultMessage =
1623
1574
  thirdCallMessages[thirdCallMessages.length - 1];
@@ -1628,8 +1579,9 @@ describe("AgentLoop", () => {
1628
1579
  expect(noRetryNudge).toBeUndefined();
1629
1580
  });
1630
1581
 
1631
- // Retry nudge stops after MAX_CONSECUTIVE_ERROR_NUDGES (3) consecutive errors
1632
- test("stops injecting retry nudge after 3 consecutive error turns", async () => {
1582
+ // Retry coaching stops after a tool fails 3 times in a row — past that the
1583
+ // error is likely unrecoverable and further coaching only burns tokens.
1584
+ test("stops appending retry coaching after 3 consecutive failures of a tool", async () => {
1633
1585
  const { provider, calls } = createMockProvider([
1634
1586
  // 4 consecutive error turns, then final text
1635
1587
  toolUseResponse("t1", "read_file", { path: "/a" }),
@@ -1654,23 +1606,21 @@ describe("AgentLoop", () => {
1654
1606
 
1655
1607
  expect(calls).toHaveLength(5);
1656
1608
 
1657
- // Helper to check if a call's last user message has the retry nudge
1609
+ // Helper to check if a call's last user message has the retry coaching
1610
+ // (a separate text block, not part of the tool_result content).
1658
1611
  const hasRetryNudge = (callIndex: number): boolean => {
1659
1612
  const msgs = calls[callIndex].messages;
1660
1613
  const lastMsg = msgs[msgs.length - 1];
1661
1614
  return lastMsg.content.some(
1662
- (b) =>
1663
- b.type === "text" &&
1664
- "text" in b &&
1665
- (b as { text: string }).text.includes("looks recoverable"),
1615
+ (b) => b.type === "text" && b.text.includes("looks recoverable"),
1666
1616
  );
1667
1617
  };
1668
1618
 
1669
- // Turns 1-3 should have the nudge
1619
+ // Turns 1-3 should have the coaching
1670
1620
  expect(hasRetryNudge(1)).toBe(true);
1671
1621
  expect(hasRetryNudge(2)).toBe(true);
1672
1622
  expect(hasRetryNudge(3)).toBe(true);
1673
- // Turn 4 should NOT have the nudge (exceeded limit)
1623
+ // Turn 4 should NOT have the coaching (exceeded limit)
1674
1624
  expect(hasRetryNudge(4)).toBe(false);
1675
1625
  });
1676
1626
 
@@ -77,6 +77,8 @@ function makeTarget(): WakeTarget {
77
77
  run: (async (messages: Message[]) => ({
78
78
  history: messages,
79
79
  exitReason: null,
80
+ appendedNewMessages: false,
81
+ newMessages: [],
80
82
  })) as WakeTarget["agentLoop"]["run"],
81
83
  },
82
84
  getMessages: () => history,