@vellumai/assistant 0.5.1 → 0.5.3

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 (405) hide show
  1. package/ARCHITECTURE.md +163 -54
  2. package/docs/architecture/integrations.md +62 -67
  3. package/docs/credential-execution-service.md +3 -3
  4. package/docs/skills.md +100 -0
  5. package/package.json +1 -1
  6. package/src/__tests__/agent-loop.test.ts +111 -0
  7. package/src/__tests__/always-loaded-tools-guard.test.ts +3 -4
  8. package/src/__tests__/app-builder-tool-scripts.test.ts +13 -151
  9. package/src/__tests__/app-dir-path-guard.test.ts +78 -0
  10. package/src/__tests__/app-executors.test.ts +1 -291
  11. package/src/__tests__/app-git-history.test.ts +4 -4
  12. package/src/__tests__/app-routes-csp.test.ts +1 -0
  13. package/src/__tests__/app-store-dir-names.test.ts +426 -0
  14. package/src/__tests__/attachments-store.test.ts +169 -21
  15. package/src/__tests__/attachments.test.ts +115 -1
  16. package/src/__tests__/btw-routes.test.ts +1 -0
  17. package/src/__tests__/canonical-guardian-store.test.ts +38 -0
  18. package/src/__tests__/channel-reply-delivery.test.ts +55 -0
  19. package/src/__tests__/checker.test.ts +54 -0
  20. package/src/__tests__/claude-code-skill-regression.test.ts +2 -0
  21. package/src/__tests__/claude-code-tool-profiles.test.ts +2 -0
  22. package/src/__tests__/compaction.benchmark.test.ts +2 -1
  23. package/src/__tests__/config-schema-cmd.test.ts +68 -21
  24. package/src/__tests__/config-schema.test.ts +1 -1
  25. package/src/__tests__/conversation-agent-loop-overflow.test.ts +156 -5
  26. package/src/__tests__/conversation-agent-loop.test.ts +297 -2
  27. package/src/__tests__/conversation-attachments.test.ts +17 -19
  28. package/src/__tests__/conversation-disk-view-integration.test.ts +277 -0
  29. package/src/__tests__/conversation-disk-view.test.ts +810 -0
  30. package/src/__tests__/conversation-error.test.ts +1 -1
  31. package/src/__tests__/conversation-fork-crud.test.ts +551 -0
  32. package/src/__tests__/conversation-fork-route.test.ts +386 -0
  33. package/src/__tests__/conversation-history-web-search.test.ts +1 -1
  34. package/src/__tests__/conversation-key-store-disk-view.test.ts +130 -0
  35. package/src/__tests__/conversation-media-retry.test.ts +8 -2
  36. package/src/__tests__/conversation-memory-dirty-tail.test.ts +150 -0
  37. package/src/__tests__/conversation-provider-retry-repair.test.ts +7 -0
  38. package/src/__tests__/conversation-queue.test.ts +36 -1
  39. package/src/__tests__/conversation-routes-disk-view.test.ts +439 -0
  40. package/src/__tests__/conversation-routes-guardian-reply.test.ts +2 -2
  41. package/src/__tests__/conversation-routes-slash-commands.test.ts +2 -7
  42. package/src/__tests__/conversation-runtime-assembly.test.ts +17 -2
  43. package/src/__tests__/conversation-skill-tools.test.ts +4 -9
  44. package/src/__tests__/conversation-slash-commands.test.ts +149 -0
  45. package/src/__tests__/conversation-store.test.ts +24 -21
  46. package/src/__tests__/conversation-surfaces-state-update.test.ts +246 -0
  47. package/src/__tests__/conversation-surfaces-task-progress.test.ts +1 -0
  48. package/src/__tests__/conversation-title-service.test.ts +137 -0
  49. package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +25 -315
  50. package/src/__tests__/conversation-tool-setup-memory-scope.test.ts +1 -0
  51. package/src/__tests__/conversation-tool-setup-side-effect-flag.test.ts +1 -0
  52. package/src/__tests__/conversation-wipe.test.ts +226 -0
  53. package/src/__tests__/conversation-workspace-cache-state.test.ts +44 -2
  54. package/src/__tests__/conversation-workspace-injection.test.ts +11 -0
  55. package/src/__tests__/credential-security-invariants.test.ts +3 -0
  56. package/src/__tests__/credential-vault-unit.test.ts +5 -10
  57. package/src/__tests__/cu-unified-flow.test.ts +1 -0
  58. package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +241 -0
  59. package/src/__tests__/db-llm-request-log-provider-migration.test.ts +214 -0
  60. package/src/__tests__/db-memory-archive-migration.test.ts +372 -0
  61. package/src/__tests__/db-memory-brief-state-migration.test.ts +213 -0
  62. package/src/__tests__/db-memory-reducer-checkpoints.test.ts +273 -0
  63. package/src/__tests__/diagnostics-export.test.ts +70 -1
  64. package/src/__tests__/first-greeting.test.ts +80 -0
  65. package/src/__tests__/gateway-only-guard.test.ts +1 -0
  66. package/src/__tests__/handlers-user-message-approval-consumption.test.ts +3 -7
  67. package/src/__tests__/history-repair.test.ts +32 -10
  68. package/src/__tests__/http-conversation-lineage.test.ts +251 -0
  69. package/src/__tests__/image-source-path-reinject.test.ts +136 -0
  70. package/src/__tests__/inline-command-runner.test.ts +311 -0
  71. package/src/__tests__/inline-skill-authoring-guard.test.ts +220 -0
  72. package/src/__tests__/inline-skill-load-permissions.test.ts +435 -0
  73. package/src/__tests__/list-messages-attachments.test.ts +96 -0
  74. package/src/__tests__/llm-context-normalization.test.ts +1116 -0
  75. package/src/__tests__/llm-context-route-provider.test.ts +217 -0
  76. package/src/__tests__/llm-request-log-turn-query.test.ts +270 -0
  77. package/src/__tests__/media-generate-image.test.ts +47 -94
  78. package/src/__tests__/memory-brief-open-loops.test.ts +530 -0
  79. package/src/__tests__/memory-brief-time.test.ts +285 -0
  80. package/src/__tests__/memory-brief-wrapper.test.ts +311 -0
  81. package/src/__tests__/memory-chunk-archive.test.ts +400 -0
  82. package/src/__tests__/memory-chunk-dual-write.test.ts +453 -0
  83. package/src/__tests__/memory-episode-archive.test.ts +370 -0
  84. package/src/__tests__/memory-episode-dual-write.test.ts +626 -0
  85. package/src/__tests__/memory-lifecycle-e2e.test.ts +3 -1
  86. package/src/__tests__/memory-observation-archive.test.ts +375 -0
  87. package/src/__tests__/memory-observation-dual-write.test.ts +318 -0
  88. package/src/__tests__/memory-recall-quality.test.ts +7 -7
  89. package/src/__tests__/memory-reducer-store.test.ts +728 -0
  90. package/src/__tests__/memory-reducer-types.test.ts +699 -0
  91. package/src/__tests__/memory-reducer.test.ts +698 -0
  92. package/src/__tests__/memory-regressions.test.ts +6 -4
  93. package/src/__tests__/memory-simplified-config.test.ts +281 -0
  94. package/src/__tests__/migration-cross-version-compatibility.test.ts +4 -1
  95. package/src/__tests__/migration-export-http.test.ts +3 -1
  96. package/src/__tests__/migration-import-commit-http.test.ts +18 -4
  97. package/src/__tests__/migration-import-preflight-http.test.ts +1 -3
  98. package/src/__tests__/mime-builder.test.ts +3 -2
  99. package/src/__tests__/non-member-access-request.test.ts +12 -1
  100. package/src/__tests__/notification-decision-identity.test.ts +52 -0
  101. package/src/__tests__/oauth-apps-routes.test.ts +103 -0
  102. package/src/__tests__/oauth-store.test.ts +115 -0
  103. package/src/__tests__/parse-identity-fields.test.ts +129 -0
  104. package/src/__tests__/provider-error-scenarios.test.ts +1 -3
  105. package/src/__tests__/provider-failover-actual-provider.test.ts +66 -0
  106. package/src/__tests__/recording-handler.test.ts +17 -0
  107. package/src/__tests__/registry.test.ts +3 -8
  108. package/src/__tests__/relay-server.test.ts +1 -1
  109. package/src/__tests__/runtime-attachment-metadata.test.ts +7 -3
  110. package/src/__tests__/schema-transforms.test.ts +165 -5
  111. package/src/__tests__/server-history-render.test.ts +2 -2
  112. package/src/__tests__/skill-load-inline-command.test.ts +598 -0
  113. package/src/__tests__/skill-load-inline-includes.test.ts +644 -0
  114. package/src/__tests__/skills-inline-command-expansions.test.ts +301 -0
  115. package/src/__tests__/skills-transitive-hash.test.ts +333 -0
  116. package/src/__tests__/slack-app-setup-skill-regression.test.ts +3 -1
  117. package/src/__tests__/slack-inbound-verification.test.ts +2 -2
  118. package/src/__tests__/starter-task-flow.test.ts +1 -0
  119. package/src/__tests__/suggestion-routes.test.ts +443 -0
  120. package/src/__tests__/swarm-conversation-integration.test.ts +1 -0
  121. package/src/__tests__/swarm-recursion.test.ts +1 -0
  122. package/src/__tests__/swarm-tool.test.ts +1 -0
  123. package/src/__tests__/tool-execution-abort-cleanup.test.ts +1 -0
  124. package/src/__tests__/tool-preview-lifecycle.test.ts +32 -5
  125. package/src/__tests__/top-level-renderer.test.ts +22 -0
  126. package/src/__tests__/turn-boundary-resolution.test.ts +243 -0
  127. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +320 -0
  128. package/src/__tests__/web-fetch.test.ts +6 -2
  129. package/src/__tests__/workspace-migration-006-services-config.test.ts +335 -0
  130. package/src/__tests__/workspace-migration-007-web-search-provider-rename.test.ts +312 -0
  131. package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +278 -0
  132. package/src/__tests__/workspace-migration-010-app-dir-rename.test.ts +275 -0
  133. package/src/__tests__/workspace-migration-012-rename-conversation-disk-view-dirs.test.ts +77 -0
  134. package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +401 -0
  135. package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +328 -0
  136. package/src/__tests__/workspace-migration-seed-device-id.test.ts +6 -10
  137. package/src/agent/attachments.ts +27 -1
  138. package/src/agent/loop.ts +29 -1
  139. package/src/avatar/traits-png-sync.ts +80 -25
  140. package/src/bundler/app-bundler.ts +4 -4
  141. package/src/calls/call-domain.ts +1 -0
  142. package/src/calls/voice-session-bridge.ts +1 -0
  143. package/src/cli/commands/auth.ts +92 -0
  144. package/src/cli/commands/avatar.ts +7 -6
  145. package/src/cli/commands/config.ts +2 -0
  146. package/src/cli/commands/oauth/providers.ts +29 -0
  147. package/src/cli/program.ts +12 -0
  148. package/src/cli.ts +15 -48
  149. package/src/config/bundled-skills/app-builder/SKILL.md +103 -28
  150. package/src/config/bundled-skills/app-builder/TOOLS.json +5 -199
  151. package/src/config/bundled-skills/app-builder/tools/{app-query.ts → app-refresh.ts} +2 -2
  152. package/src/config/bundled-skills/contacts/tools/google-contacts.ts +2 -3
  153. package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +6 -9
  154. package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +4 -6
  155. package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +2 -3
  156. package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +2 -3
  157. package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +2 -3
  158. package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +2 -3
  159. package/src/config/bundled-skills/gmail/tools/gmail-label.ts +4 -6
  160. package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +2 -3
  161. package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +2 -3
  162. package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +2 -3
  163. package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +2 -3
  164. package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +2 -3
  165. package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +2 -3
  166. package/src/config/bundled-skills/google-calendar/tools/shared.ts +1 -1
  167. package/src/config/bundled-skills/image-studio/SKILL.md +2 -2
  168. package/src/config/bundled-skills/image-studio/TOOLS.json +2 -2
  169. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +45 -72
  170. package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +2 -2
  171. package/src/config/bundled-skills/messaging/tools/shared.ts +1 -1
  172. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +19 -3
  173. package/src/config/bundled-skills/skill-management/SKILL.md +1 -1
  174. package/src/config/bundled-skills/skill-management/TOOLS.json +2 -2
  175. package/src/config/bundled-skills/slack/tools/shared.ts +19 -4
  176. package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +2 -3
  177. package/src/config/bundled-skills/transcribe/SKILL.md +1 -1
  178. package/src/config/bundled-skills/transcribe/TOOLS.json +2 -6
  179. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +19 -83
  180. package/src/config/bundled-tool-registry.ts +2 -14
  181. package/src/config/feature-flag-registry.json +24 -0
  182. package/src/config/loader.ts +65 -0
  183. package/src/config/raw-config-utils.ts +58 -0
  184. package/src/config/schema-utils.ts +28 -7
  185. package/src/config/schema.ts +20 -0
  186. package/src/config/schemas/elevenlabs.ts +18 -0
  187. package/src/config/schemas/memory-lifecycle.ts +4 -2
  188. package/src/config/schemas/memory-simplified.ts +101 -0
  189. package/src/config/schemas/memory-storage.ts +1 -1
  190. package/src/config/schemas/memory.ts +4 -0
  191. package/src/config/schemas/services.ts +8 -6
  192. package/src/config/skills.ts +50 -4
  193. package/src/contacts/contact-store.ts +13 -6
  194. package/src/contacts/contacts-write.ts +0 -1
  195. package/src/context/window-manager.ts +13 -2
  196. package/src/daemon/conversation-agent-loop-handlers.ts +54 -8
  197. package/src/daemon/conversation-agent-loop.ts +127 -20
  198. package/src/daemon/conversation-attachments.ts +18 -36
  199. package/src/daemon/conversation-error.ts +2 -1
  200. package/src/daemon/conversation-history.ts +18 -4
  201. package/src/daemon/conversation-lifecycle.ts +50 -16
  202. package/src/daemon/conversation-messaging.ts +70 -26
  203. package/src/daemon/conversation-process.ts +58 -34
  204. package/src/daemon/conversation-runtime-assembly.ts +22 -38
  205. package/src/daemon/conversation-slash.ts +121 -256
  206. package/src/daemon/conversation-surfaces.ts +170 -24
  207. package/src/daemon/conversation-tool-setup.ts +0 -6
  208. package/src/daemon/conversation-workspace.ts +21 -1
  209. package/src/daemon/conversation.ts +69 -30
  210. package/src/daemon/first-greeting.ts +35 -0
  211. package/src/daemon/handlers/config-embeddings.ts +156 -0
  212. package/src/daemon/handlers/config-model.ts +62 -26
  213. package/src/daemon/handlers/conversations.ts +0 -23
  214. package/src/daemon/handlers/identity.ts +12 -1
  215. package/src/daemon/handlers/recording.ts +26 -21
  216. package/src/daemon/host-cu-proxy.ts +2 -2
  217. package/src/daemon/lifecycle.ts +115 -65
  218. package/src/daemon/message-protocol.ts +3 -0
  219. package/src/daemon/message-types/conversations.ts +18 -0
  220. package/src/daemon/message-types/messages.ts +1 -0
  221. package/src/daemon/message-types/shared.ts +2 -0
  222. package/src/daemon/message-types/surfaces.ts +2 -0
  223. package/src/daemon/message-types/upgrades.ts +23 -0
  224. package/src/daemon/server.ts +83 -12
  225. package/src/daemon/shutdown-handlers.ts +8 -5
  226. package/src/daemon/startup-error.ts +9 -0
  227. package/src/daemon/tool-side-effects.ts +11 -28
  228. package/src/events/tool-permission-telemetry-listener.ts +1 -3
  229. package/src/followups/followup-store.ts +47 -1
  230. package/src/instrument.ts +0 -4
  231. package/src/media/app-icon-generator.ts +2 -2
  232. package/src/memory/app-git-service.ts +28 -16
  233. package/src/memory/app-store.ts +230 -41
  234. package/src/memory/archive-store.ts +400 -0
  235. package/src/memory/attachments-store.ts +558 -130
  236. package/src/memory/brief-formatting.ts +33 -0
  237. package/src/memory/brief-open-loops.ts +266 -0
  238. package/src/memory/brief-time.ts +161 -0
  239. package/src/memory/brief.ts +75 -0
  240. package/src/memory/conversation-attention-store.ts +70 -0
  241. package/src/memory/conversation-crud.ts +591 -8
  242. package/src/memory/conversation-directories.ts +125 -0
  243. package/src/memory/conversation-disk-view.ts +390 -0
  244. package/src/memory/conversation-key-store.ts +17 -5
  245. package/src/memory/conversation-queries.ts +5 -1
  246. package/src/memory/conversation-title-service.ts +21 -49
  247. package/src/memory/db-init.ts +40 -0
  248. package/src/memory/embedding-backend.ts +42 -53
  249. package/src/memory/embedding-gemini.test.ts +4 -4
  250. package/src/memory/embedding-local.ts +1 -3
  251. package/src/memory/embedding-ollama.ts +1 -3
  252. package/src/memory/embedding-openai.ts +1 -3
  253. package/src/memory/indexer.ts +114 -21
  254. package/src/memory/items-extractor.ts +42 -13
  255. package/src/memory/job-handlers/conversation-starters.ts +6 -1
  256. package/src/memory/job-handlers/embedding.test.ts +2 -4
  257. package/src/memory/job-handlers/embedding.ts +83 -0
  258. package/src/memory/job-utils.ts +1 -1
  259. package/src/memory/jobs-store.ts +6 -0
  260. package/src/memory/jobs-worker.ts +12 -0
  261. package/src/memory/llm-request-log-store.ts +100 -1
  262. package/src/memory/migrations/102-alter-table-columns.ts +5 -0
  263. package/src/memory/migrations/146-schedule-oneshot-routing.ts +3 -3
  264. package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +66 -70
  265. package/src/memory/migrations/148-drop-reminders-table.ts +5 -9
  266. package/src/memory/migrations/160-drop-loopback-port-column.ts +1 -3
  267. package/src/memory/migrations/174-rename-thread-starters-table.ts +0 -7
  268. package/src/memory/migrations/178-oauth-providers-managed-service-config-key.ts +15 -0
  269. package/src/memory/migrations/179-llm-request-log-message-id.ts +16 -0
  270. package/src/memory/migrations/180-backfill-inline-attachments-to-disk.ts +66 -0
  271. package/src/memory/migrations/181-rename-thread-starters-checkpoints.ts +46 -0
  272. package/src/memory/migrations/182-oauth-providers-display-metadata.ts +20 -0
  273. package/src/memory/migrations/183-add-conversation-fork-lineage.ts +22 -0
  274. package/src/memory/migrations/184-llm-request-log-provider.ts +12 -0
  275. package/src/memory/migrations/185-memory-brief-state.ts +52 -0
  276. package/src/memory/migrations/186-memory-archive.ts +109 -0
  277. package/src/memory/migrations/187-memory-reducer-checkpoints.ts +19 -0
  278. package/src/memory/migrations/index.ts +10 -0
  279. package/src/memory/migrations/registry.ts +13 -0
  280. package/src/memory/qdrant-client.ts +23 -4
  281. package/src/memory/reducer-store.ts +271 -0
  282. package/src/memory/reducer-types.ts +99 -0
  283. package/src/memory/reducer.ts +453 -0
  284. package/src/memory/retriever.test.ts +601 -2
  285. package/src/memory/retriever.ts +85 -9
  286. package/src/memory/schema/conversations.ts +9 -0
  287. package/src/memory/schema/index.ts +2 -0
  288. package/src/memory/schema/infrastructure.ts +13 -7
  289. package/src/memory/schema/memory-archive.ts +121 -0
  290. package/src/memory/schema/memory-brief.ts +55 -0
  291. package/src/memory/schema/oauth.ts +6 -0
  292. package/src/memory/search/semantic.ts +17 -4
  293. package/src/messaging/providers/gmail/mime-builder.ts +3 -1
  294. package/src/notifications/copy-composer.ts +26 -0
  295. package/src/notifications/decision-engine.ts +14 -1
  296. package/src/notifications/emit-signal.ts +1 -1
  297. package/src/notifications/signal.ts +36 -0
  298. package/src/oauth/byo-connection.test.ts +1 -45
  299. package/src/oauth/byo-connection.ts +2 -8
  300. package/src/oauth/connect-orchestrator.ts +15 -11
  301. package/src/oauth/connection-resolver.test.ts +191 -0
  302. package/src/oauth/connection-resolver.ts +66 -38
  303. package/src/oauth/connection.ts +0 -1
  304. package/src/oauth/oauth-store.ts +99 -47
  305. package/src/oauth/platform-connection.test.ts +0 -1
  306. package/src/oauth/platform-connection.ts +11 -3
  307. package/src/oauth/seed-providers.ts +78 -3
  308. package/src/oauth/token-persistence.ts +16 -10
  309. package/src/permissions/checker.ts +160 -14
  310. package/src/permissions/defaults.ts +14 -0
  311. package/src/prompts/templates/BOOTSTRAP.md +2 -0
  312. package/src/providers/anthropic/client.ts +8 -1
  313. package/src/providers/failover.ts +4 -1
  314. package/src/providers/gemini/client.ts +50 -0
  315. package/src/providers/model-catalog.ts +92 -0
  316. package/src/providers/model-intents.ts +29 -20
  317. package/src/providers/openai/client.ts +49 -0
  318. package/src/providers/types.ts +2 -0
  319. package/src/runtime/access-request-helper.ts +16 -7
  320. package/src/runtime/auth/credential-service.ts +3 -1
  321. package/src/runtime/auth/route-policy.ts +14 -1
  322. package/src/runtime/btw-sidechain.ts +101 -0
  323. package/src/runtime/channel-reply-delivery.ts +17 -1
  324. package/src/runtime/http-router.ts +3 -1
  325. package/src/runtime/http-server.ts +196 -141
  326. package/src/runtime/http-types.ts +1 -0
  327. package/src/runtime/migrations/vbundle-builder.ts +5 -1
  328. package/src/runtime/routes/access-request-decision.ts +41 -0
  329. package/src/runtime/routes/app-management-routes.ts +6 -3
  330. package/src/runtime/routes/app-routes.ts +7 -3
  331. package/src/runtime/routes/approval-routes.ts +1 -0
  332. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +34 -2
  333. package/src/runtime/routes/attachment-routes.ts +45 -15
  334. package/src/runtime/routes/btw-routes.ts +21 -61
  335. package/src/runtime/routes/conversation-management-routes.ts +74 -0
  336. package/src/runtime/routes/conversation-query-routes.ts +187 -10
  337. package/src/runtime/routes/conversation-routes.ts +269 -28
  338. package/src/runtime/routes/conversation-starter-routes.ts +9 -11
  339. package/src/runtime/routes/diagnostics-routes.ts +1 -0
  340. package/src/runtime/routes/identity-routes.ts +2 -35
  341. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -2
  342. package/src/runtime/routes/llm-context-normalization.ts +1212 -0
  343. package/src/runtime/routes/log-export-routes.ts +3 -0
  344. package/src/runtime/routes/memory-item-routes.test.ts +34 -0
  345. package/src/runtime/routes/memory-item-routes.ts +94 -5
  346. package/src/runtime/routes/migration-routes.ts +4 -1
  347. package/src/runtime/routes/oauth-apps.ts +291 -0
  348. package/src/runtime/routes/secret-routes.ts +30 -1
  349. package/src/runtime/routes/settings-routes.ts +14 -0
  350. package/src/runtime/routes/surface-action-routes.ts +68 -1
  351. package/src/runtime/routes/trace-event-routes.ts +4 -1
  352. package/src/schedule/schedule-store.ts +30 -21
  353. package/src/security/secure-keys.ts +21 -0
  354. package/src/signals/bash.ts +1 -1
  355. package/src/skills/inline-command-expansions.ts +204 -0
  356. package/src/skills/inline-command-render.ts +127 -0
  357. package/src/skills/inline-command-runner.ts +242 -0
  358. package/src/skills/transitive-version-hash.ts +88 -0
  359. package/src/swarm/backend-claude-code.ts +3 -6
  360. package/src/tasks/task-store.ts +43 -1
  361. package/src/telemetry/usage-telemetry-reporter.test.ts +3 -2
  362. package/src/telemetry/usage-telemetry-reporter.ts +3 -1
  363. package/src/tools/AGENTS.md +6 -10
  364. package/src/tools/apps/executors.ts +17 -232
  365. package/src/tools/claude-code/claude-code.ts +2 -3
  366. package/src/tools/credentials/vault.ts +7 -12
  367. package/src/tools/host-filesystem/read.ts +13 -10
  368. package/src/tools/network/__tests__/web-search.test.ts +4 -2
  369. package/src/tools/permission-checker.ts +8 -1
  370. package/src/tools/schedule/list.ts +2 -7
  371. package/src/tools/schema-transforms.ts +5 -0
  372. package/src/tools/shared/filesystem/format-diff.ts +2 -7
  373. package/src/tools/skills/execute.ts +1 -1
  374. package/src/tools/skills/load.ts +140 -6
  375. package/src/tools/tool-manifest.ts +0 -6
  376. package/src/tools/ui-surface/definitions.ts +2 -2
  377. package/src/util/device-id.ts +28 -5
  378. package/src/util/platform.ts +24 -0
  379. package/src/util/pricing.ts +1 -0
  380. package/src/util/retry.ts +1 -3
  381. package/src/workspace/migrations/003-seed-device-id.ts +3 -4
  382. package/src/workspace/migrations/006-services-config.ts +5 -0
  383. package/src/workspace/migrations/008-voice-timeout-and-max-steps.ts +12 -0
  384. package/src/workspace/migrations/009-backfill-conversation-disk-view.ts +10 -0
  385. package/src/workspace/migrations/010-app-dir-rename.ts +223 -0
  386. package/src/workspace/migrations/{002-backfill-installation-id.ts → 011-backfill-installation-id.ts} +24 -13
  387. package/src/workspace/migrations/012-rename-conversation-disk-view-dirs.ts +64 -0
  388. package/src/workspace/migrations/013-repair-conversation-disk-view.ts +11 -0
  389. package/src/workspace/migrations/rebuild-conversation-disk-view.ts +186 -0
  390. package/src/workspace/migrations/registry.ts +11 -1
  391. package/src/workspace/top-level-renderer.ts +12 -0
  392. package/src/__tests__/asset-materialize-tool.test.ts +0 -523
  393. package/src/__tests__/asset-search-tool.test.ts +0 -536
  394. package/src/__tests__/fixtures/media-reuse-fixtures.ts +0 -56
  395. package/src/__tests__/media-reuse-story.e2e.test.ts +0 -762
  396. package/src/__tests__/media-visibility-policy.test.ts +0 -190
  397. package/src/config/bundled-skills/app-builder/tools/app-file-edit.ts +0 -14
  398. package/src/config/bundled-skills/app-builder/tools/app-file-list.ts +0 -13
  399. package/src/config/bundled-skills/app-builder/tools/app-file-read.ts +0 -21
  400. package/src/config/bundled-skills/app-builder/tools/app-file-write.ts +0 -14
  401. package/src/config/bundled-skills/app-builder/tools/app-list.ts +0 -13
  402. package/src/config/bundled-skills/app-builder/tools/app-update.ts +0 -23
  403. package/src/daemon/media-visibility-policy.ts +0 -59
  404. package/src/tools/assets/materialize.ts +0 -248
  405. package/src/tools/assets/search.ts +0 -400
@@ -10,11 +10,8 @@
10
10
 
11
11
  import { compileApp } from "../../bundler/app-compiler.js";
12
12
  import { generateAppIcon } from "../../media/app-icon-generator.js";
13
- import type {
14
- AppDefinition,
15
- EditEngineResult,
16
- } from "../../memory/app-store.js";
17
- import { getAppsDir, isMultifileApp } from "../../memory/app-store.js";
13
+ import type { AppDefinition } from "../../memory/app-store.js";
14
+ import { getAppDirPath } from "../../memory/app-store.js";
18
15
 
19
16
  // ---------------------------------------------------------------------------
20
17
  // Shared result type
@@ -35,9 +32,6 @@ export interface ExecutorResult {
35
32
  export interface AppStoreReader {
36
33
  getApp(id: string): AppDefinition | null;
37
34
  listApps(): AppDefinition[];
38
- queryAppRecords(appId: string): unknown[];
39
- listAppFiles(appId: string): string[];
40
- readAppFile(appId: string, path: string): string;
41
35
  }
42
36
 
43
37
  export interface AppStoreWriter {
@@ -61,13 +55,6 @@ export interface AppStoreWriter {
61
55
  ): AppDefinition;
62
56
  deleteApp(id: string): void;
63
57
  writeAppFile(appId: string, path: string, content: string): void;
64
- editAppFile(
65
- appId: string,
66
- path: string,
67
- oldString: string,
68
- newString: string,
69
- replaceAll?: boolean,
70
- ): EditEngineResult;
71
58
  }
72
59
 
73
60
  export type AppStore = AppStoreReader & AppStoreWriter;
@@ -81,28 +68,6 @@ export type ProxyResolver = (
81
68
  input: Record<string, unknown>,
82
69
  ) => Promise<ExecutorResult>;
83
70
 
84
- // ---------------------------------------------------------------------------
85
- // Path resolution - multifile apps default to src/ for file operations
86
- // ---------------------------------------------------------------------------
87
-
88
- /**
89
- * For multifile (formatVersion 2) apps, prepend `src/` to paths that don't
90
- * already target a known top-level directory (src/, dist/, records/).
91
- * Legacy apps pass through unchanged.
92
- */
93
- export function resolveAppFilePath(app: AppDefinition, path: string): string {
94
- if (!isMultifileApp(app)) return path;
95
- const normalized = path.replace(/\\/g, "/").replace(/^\.\//, "");
96
- if (
97
- normalized.startsWith("src/") ||
98
- normalized.startsWith("dist/") ||
99
- normalized.startsWith("records/")
100
- ) {
101
- return normalized;
102
- }
103
- return `src/${normalized}`;
104
- }
105
-
106
71
  // ---------------------------------------------------------------------------
107
72
  // app_create
108
73
  // ---------------------------------------------------------------------------
@@ -222,8 +187,7 @@ render(<App />, document.getElementById('app')!);
222
187
  store.writeAppFile(app.id, "src/main.tsx", mainTsx);
223
188
 
224
189
  // Compile src/ → dist/
225
- const { join } = await import("node:path");
226
- const appDir = join(getAppsDir(), app.id);
190
+ const appDir = getAppDirPath(app.id);
227
191
  const compileResult = await compileApp(appDir);
228
192
  if (!compileResult.ok) {
229
193
  return {
@@ -286,72 +250,6 @@ render(<App />, document.getElementById('app')!);
286
250
  return { content: JSON.stringify(app), isError: false };
287
251
  }
288
252
 
289
- // ---------------------------------------------------------------------------
290
- // app_list
291
- // ---------------------------------------------------------------------------
292
-
293
- export function executeAppList(store: AppStoreReader): ExecutorResult {
294
- const apps = store.listApps().map((a) => ({
295
- id: a.id,
296
- name: a.name,
297
- description: a.description,
298
- updatedAt: a.updatedAt,
299
- }));
300
- return { content: JSON.stringify(apps), isError: false };
301
- }
302
-
303
- // ---------------------------------------------------------------------------
304
- // app_query
305
- // ---------------------------------------------------------------------------
306
-
307
- export interface AppQueryInput {
308
- app_id: string;
309
- }
310
-
311
- export function executeAppQuery(
312
- input: AppQueryInput,
313
- store: AppStoreReader,
314
- ): ExecutorResult {
315
- const records = store.queryAppRecords(input.app_id);
316
- return { content: JSON.stringify(records), isError: false };
317
- }
318
-
319
- // ---------------------------------------------------------------------------
320
- // app_update
321
- // ---------------------------------------------------------------------------
322
-
323
- export interface AppUpdateInput {
324
- app_id: string;
325
- name?: string;
326
- description?: string;
327
- schema_json?: string;
328
- html?: string;
329
- pages?: Record<string, string>;
330
- }
331
-
332
- export function executeAppUpdate(
333
- input: AppUpdateInput,
334
- store: AppStore,
335
- ): ExecutorResult {
336
- const updates: Partial<
337
- Pick<
338
- AppDefinition,
339
- "name" | "description" | "schemaJson" | "htmlDefinition" | "pages"
340
- >
341
- > = {};
342
- if (typeof input.name === "string") updates.name = input.name;
343
- if (typeof input.description === "string")
344
- updates.description = input.description;
345
- if (typeof input.schema_json === "string")
346
- updates.schemaJson = input.schema_json;
347
- if (typeof input.html === "string") updates.htmlDefinition = input.html;
348
- if (input.pages && typeof input.pages === "object")
349
- updates.pages = input.pages;
350
-
351
- const app = store.updateApp(input.app_id, updates);
352
- return { content: JSON.stringify(app), isError: false };
353
- }
354
-
355
253
  // ---------------------------------------------------------------------------
356
254
  // app_delete
357
255
  // ---------------------------------------------------------------------------
@@ -372,131 +270,15 @@ export function executeAppDelete(
372
270
  }
373
271
 
374
272
  // ---------------------------------------------------------------------------
375
- // app_file_list
376
- // ---------------------------------------------------------------------------
377
-
378
- export interface AppFileListInput {
379
- app_id: string;
380
- }
381
-
382
- export function executeAppFileList(
383
- input: AppFileListInput,
384
- store: AppStoreReader,
385
- ): ExecutorResult {
386
- const files = store.listAppFiles(input.app_id);
387
- const app = store.getApp(input.app_id);
388
-
389
- if (app && isMultifileApp(app)) {
390
- // Separate build output paths from source paths without mutating the
391
- // file path strings - consumers need clean paths for subsequent tool calls.
392
- const buildOutputPaths = files.filter((f) =>
393
- f.replace(/\\/g, "/").startsWith("dist/"),
394
- );
395
- return {
396
- content: JSON.stringify({
397
- files,
398
- buildOutput: buildOutputPaths,
399
- }),
400
- isError: false,
401
- };
402
- }
403
-
404
- return { content: JSON.stringify(files), isError: false };
405
- }
406
-
407
- // ---------------------------------------------------------------------------
408
- // app_file_read
409
- // ---------------------------------------------------------------------------
410
-
411
- export interface AppFileReadInput {
412
- app_id: string;
413
- path: string;
414
- offset?: number;
415
- limit?: number;
416
- }
417
-
418
- export function executeAppFileRead(
419
- input: AppFileReadInput,
420
- store: AppStoreReader,
421
- ): ExecutorResult {
422
- const offset = input.offset ?? 1;
423
- const limit = input.limit;
424
-
425
- const app = store.getApp(input.app_id);
426
- const resolvedPath = app ? resolveAppFilePath(app, input.path) : input.path;
427
- const raw = store.readAppFile(input.app_id, resolvedPath);
428
- const allLines = raw.split("\n");
429
- const startIndex = Math.max(0, offset - 1);
430
- const sliced =
431
- limit != null
432
- ? allLines.slice(startIndex, startIndex + limit)
433
- : allLines.slice(startIndex);
434
-
435
- const formatted = sliced
436
- .map((line, i) => {
437
- const lineNum = startIndex + i + 1;
438
- return `${String(lineNum).padStart(6)}\t${line}`;
439
- })
440
- .join("\n");
441
-
442
- return { content: formatted, isError: false };
443
- }
444
-
445
- // ---------------------------------------------------------------------------
446
- // app_file_edit
447
- // ---------------------------------------------------------------------------
448
-
449
- export interface AppFileEditInput {
450
- app_id: string;
451
- path: string;
452
- old_string: string;
453
- new_string: string;
454
- replace_all?: boolean;
455
- status?: string;
456
- }
457
-
458
- export function executeAppFileEdit(
459
- input: AppFileEditInput,
460
- store: AppStore,
461
- ): ExecutorResult {
462
- if (!input.old_string) {
463
- return {
464
- content: JSON.stringify({ error: "old_string must not be empty" }),
465
- isError: true,
466
- };
467
- }
468
-
469
- const app = store.getApp(input.app_id);
470
- const resolvedPath = app ? resolveAppFilePath(app, input.path) : input.path;
471
-
472
- const replaceAll = input.replace_all ?? false;
473
- const result = store.editAppFile(
474
- input.app_id,
475
- resolvedPath,
476
- input.old_string,
477
- input.new_string,
478
- replaceAll,
479
- );
480
- return {
481
- content: JSON.stringify(result),
482
- isError: false,
483
- status: input.status,
484
- };
485
- }
486
-
487
- // ---------------------------------------------------------------------------
488
- // app_file_write
273
+ // app_refresh
489
274
  // ---------------------------------------------------------------------------
490
275
 
491
- export interface AppFileWriteInput {
276
+ export interface AppRefreshInput {
492
277
  app_id: string;
493
- path: string;
494
- content: string;
495
- status?: string;
496
278
  }
497
279
 
498
- export function executeAppFileWrite(
499
- input: AppFileWriteInput,
280
+ export function executeAppRefresh(
281
+ input: AppRefreshInput,
500
282
  store: AppStore,
501
283
  ): ExecutorResult {
502
284
  const app = store.getApp(input.app_id);
@@ -507,12 +289,16 @@ export function executeAppFileWrite(
507
289
  };
508
290
  }
509
291
 
510
- const resolvedPath = resolveAppFilePath(app, input.path);
511
- store.writeAppFile(input.app_id, resolvedPath, input.content);
292
+ // Empty update bumps updatedAt timestamp, triggering recompilation and
293
+ // surface refresh on the client side.
294
+ const updated = store.updateApp(input.app_id, {});
512
295
  return {
513
- content: JSON.stringify({ written: true, path: resolvedPath }),
296
+ content: JSON.stringify({
297
+ refreshed: true,
298
+ appId: updated.id,
299
+ name: updated.name,
300
+ }),
514
301
  isError: false,
515
- status: input.status,
516
302
  };
517
303
  }
518
304
 
@@ -541,9 +327,8 @@ export async function executeAppGenerateIcon(
541
327
  // destroying an existing icon if generation fails.
542
328
  const { existsSync, renameSync, unlinkSync } = await import("node:fs");
543
329
  const { join } = await import("node:path");
544
- const { getAppsDir } = await import("../../memory/app-store.js");
545
- const iconPath = join(getAppsDir(), input.app_id, "icon.png");
546
- const tempPath = join(getAppsDir(), input.app_id, "icon.tmp.png");
330
+ const iconPath = join(getAppDirPath(input.app_id), "icon.png");
331
+ const tempPath = join(getAppDirPath(input.app_id), "icon.tmp.png");
547
332
 
548
333
  // Temporarily move existing icon aside so generateAppIcon doesn't skip
549
334
  if (existsSync(iconPath)) {
@@ -4,7 +4,7 @@ import {
4
4
  } from "../../commands/cc-command-registry.js";
5
5
  import { RiskLevel } from "../../permissions/types.js";
6
6
  import type { ToolDefinition } from "../../providers/types.js";
7
- import { getSecureKeyAsync } from "../../security/secure-keys.js";
7
+ import { getProviderKeyAsync } from "../../security/secure-keys.js";
8
8
  import type { WorkerProfile } from "../../swarm/worker-backend.js";
9
9
  import { getProfilePolicy } from "../../swarm/worker-backend.js";
10
10
  import { getLogger } from "../../util/logger.js";
@@ -203,8 +203,7 @@ export const claudeCodeTool: Tool = {
203
203
  const profilePolicy = getProfilePolicy(profileName);
204
204
 
205
205
  // Validate API key
206
- const apiKey =
207
- (await getSecureKeyAsync("anthropic")) ?? process.env.ANTHROPIC_API_KEY;
206
+ const apiKey = await getProviderKeyAsync("anthropic");
208
207
  if (!apiKey) {
209
208
  return {
210
209
  content:
@@ -7,8 +7,8 @@ import { orchestrateOAuthConnect } from "../../oauth/connect-orchestrator.js";
7
7
  import { syncManualTokenConnection } from "../../oauth/manual-token-connection.js";
8
8
  import {
9
9
  disconnectOAuthProvider,
10
+ getActiveConnection,
10
11
  getAppByProviderAndClientId,
11
- getConnectionByProviderAndAccount,
12
12
  getMostRecentAppByProvider,
13
13
  getProvider,
14
14
  } from "../../oauth/oauth-store.js";
@@ -66,9 +66,7 @@ async function storeSlackChannelCredential(
66
66
  : setSlackChannelConfig(undefined, value);
67
67
  }
68
68
 
69
- function formatSlackChannelStatus(
70
- result: SlackChannelConfigResult,
71
- ): string {
69
+ function formatSlackChannelStatus(result: SlackChannelConfigResult): string {
72
70
  if (result.connected) {
73
71
  const teamLabel = result.teamName ?? "Slack";
74
72
  const botLabel = result.botUsername ? ` (@${result.botUsername})` : "";
@@ -366,8 +364,7 @@ class CredentialStoreTool implements Tool {
366
364
  if (!slackChannelResult.success) {
367
365
  return {
368
366
  content: `Error: ${
369
- slackChannelResult.error ??
370
- "failed to configure Slack channel"
367
+ slackChannelResult.error ?? "failed to configure Slack channel"
371
368
  }`,
372
369
  isError: true,
373
370
  };
@@ -523,10 +520,9 @@ class CredentialStoreTool implements Tool {
523
520
  const accountHint = input.account as string | undefined;
524
521
  let oauthResult: "disconnected" | "not-found" | "error";
525
522
  if (accountHint) {
526
- const targetConn = getConnectionByProviderAndAccount(
527
- service,
528
- accountHint,
529
- );
523
+ const targetConn = getActiveConnection(service, {
524
+ account: accountHint,
525
+ });
530
526
  oauthResult = targetConn
531
527
  ? await disconnectOAuthProvider(service, undefined, targetConn.id)
532
528
  : "not-found";
@@ -778,8 +774,7 @@ class CredentialStoreTool implements Tool {
778
774
  if (!slackChannelResult.success) {
779
775
  return {
780
776
  content: `Error: ${
781
- slackChannelResult.error ??
782
- "failed to configure Slack channel"
777
+ slackChannelResult.error ?? "failed to configure Slack channel"
783
778
  }`,
784
779
  isError: true,
785
780
  };
@@ -54,6 +54,19 @@ class HostFileReadTool implements Tool {
54
54
  };
55
55
  }
56
56
 
57
+ // Image files must be handled locally — the host-file proxy protocol
58
+ // only carries {content, isError} and cannot transport contentBlocks
59
+ // (base64 image data). Check for image extensions before the proxy
60
+ // short-circuit so image reads work in managed/macOS+iOS sessions.
61
+ const ext = extname(rawPath).toLowerCase();
62
+ if (IMAGE_EXTENSIONS.has(ext)) {
63
+ const pathCheck = hostPolicy(rawPath);
64
+ if (!pathCheck.ok) {
65
+ return { content: `Error: ${pathCheck.error}`, isError: true };
66
+ }
67
+ return readImageFile(pathCheck.resolved);
68
+ }
69
+
57
70
  // Proxy to connected client for execution on the user's machine
58
71
  // when a capable client is available (managed/cloud-hosted mode).
59
72
  if (context.hostFileProxy?.isAvailable()) {
@@ -69,16 +82,6 @@ class HostFileReadTool implements Tool {
69
82
  );
70
83
  }
71
84
 
72
- // For image files, delegate to the shared image reader.
73
- const ext = extname(rawPath).toLowerCase();
74
- if (IMAGE_EXTENSIONS.has(ext)) {
75
- const pathCheck = hostPolicy(rawPath);
76
- if (!pathCheck.ok) {
77
- return { content: `Error: ${pathCheck.error}`, isError: true };
78
- }
79
- return readImageFile(pathCheck.resolved);
80
- }
81
-
82
85
  const ops = new FileSystemOps(hostPolicy);
83
86
 
84
87
  const result = ops.readFileSafe({
@@ -16,12 +16,14 @@ mock.module("../../registry.js", () => ({
16
16
 
17
17
  mock.module("../../../config/loader.js", () => ({
18
18
  getConfig: () => ({
19
- webSearchProvider: mockWebSearchProvider,
19
+ services: {
20
+ "web-search": { provider: mockWebSearchProvider },
21
+ },
20
22
  }),
21
23
  }));
22
24
 
23
25
  mock.module("../../../security/secure-keys.js", () => ({
24
- getSecureKeyAsync: async (provider: string) => {
26
+ getProviderKeyAsync: async (provider: string) => {
25
27
  if (provider === "brave") return mockBraveSecureKey;
26
28
  if (provider === "perplexity") return mockPerplexitySecureKey;
27
29
  return undefined;
@@ -142,10 +142,17 @@ export class PermissionChecker {
142
142
  // is the owner - prompting makes no sense when there is no client.
143
143
  // Exception: requireFreshApproval tools cannot be auto-approved -
144
144
  // without a human present, bundle installation must be denied.
145
+ // Exception: inline-command skill loads (skill_load_dynamic:*) must
146
+ // never be silently auto-approved — they execute embedded commands
147
+ // and require explicit human review or a pinned trust rule.
148
+ const isDynamicSkillLoad =
149
+ result.matchedRule?.pattern.startsWith("skill_load_dynamic:") ===
150
+ true;
145
151
  if (
146
152
  context.isInteractive === false &&
147
153
  context.trustClass === "guardian" &&
148
- !context.requireFreshApproval
154
+ !context.requireFreshApproval &&
155
+ !isDynamicSkillLoad
149
156
  ) {
150
157
  log.info(
151
158
  { toolName: name, riskLevel },
@@ -62,15 +62,10 @@ export async function executeScheduleList(
62
62
  );
63
63
  }
64
64
 
65
- lines.push(
66
- ` Enabled: ${job.enabled}`,
67
- ` Message: ${job.message}`,
68
- );
65
+ lines.push(` Enabled: ${job.enabled}`, ` Message: ${job.message}`);
69
66
 
70
67
  if (!oneShot) {
71
- lines.push(
72
- ` Next run: ${formatLocalDate(job.nextRunAt)}`,
73
- );
68
+ lines.push(` Next run: ${formatLocalDate(job.nextRunAt)}`);
74
69
  }
75
70
 
76
71
  lines.push(
@@ -29,7 +29,12 @@ export function injectActivityField(
29
29
  }
30
30
 
31
31
  const properties = schema.properties as Record<string, unknown>;
32
+
32
33
  if (schemaDefinesProperty(schema, "activity")) {
34
+ // Activity is already defined somewhere in the schema (top-level properties
35
+ // or composite sub-schemas). Don't modify schemas we don't own — MCP tools
36
+ // may define activity as intentionally optional or with server-specific
37
+ // semantics.
33
38
  return def;
34
39
  }
35
40
 
@@ -4,13 +4,9 @@
4
4
  */
5
5
  export function formatEditDiff(oldString: string, newString: string): string {
6
6
  const removed =
7
- oldString.length > 0
8
- ? oldString.split("\n").map((l) => `- ${l}`)
9
- : [];
7
+ oldString.length > 0 ? oldString.split("\n").map((l) => `- ${l}`) : [];
10
8
  const added =
11
- newString.length > 0
12
- ? newString.split("\n").map((l) => `+ ${l}`)
13
- : [];
9
+ newString.length > 0 ? newString.split("\n").map((l) => `+ ${l}`) : [];
14
10
 
15
11
  return [...removed, ...added].join("\n");
16
12
  }
@@ -30,4 +26,3 @@ export function formatWriteSummary(
30
26
  const oldLineCount = oldContent.split("\n").length;
31
27
  return `(${oldLineCount} → ${newLineCount} lines)`;
32
28
  }
33
-
@@ -33,7 +33,7 @@ export class SkillExecuteTool implements Tool {
33
33
  "Brief non-technical explanation of what you are doing and why, shown to the user as a status update.",
34
34
  },
35
35
  },
36
- required: ["tool", "input"],
36
+ required: ["tool", "input", "activity"],
37
37
  },
38
38
  };
39
39
  }